Received: by 2002:ac0:a5a7:0:0:0:0:0 with SMTP id m36-v6csp383405imm; Thu, 26 Jul 2018 05:26:52 -0700 (PDT) X-Google-Smtp-Source: AAOMgpdfTFaMPzh1/6mK/HgEhi/YJ0V3Sw0RPm4IF5qjQID1ZVIKy6MtOy5EqfPdcQZWKSb7pr+z X-Received: by 2002:a17:902:aa4b:: with SMTP id c11-v6mr1768658plr.344.1532608012946; Thu, 26 Jul 2018 05:26:52 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1532608012; cv=none; d=google.com; s=arc-20160816; b=c0rVGjETbTB09r1rd6ZSgfMXh5OMkkba6nJg2xE1H2XohWzG7yHrKkSRpHL2GbOL0H pzFwtTNu5du2NsvIxQDiz43r3XUmMLBXJ+rDK+JmInk1yoCjBeR9VTPZ4yn3rpAwLqU2 sAp0S2eURT5eHlbssuhuv1zm5P6CL0irQ8ve1eYiPkhT1TMDPer9Ww2+J7pRMSz4mmcU BnIUYXQWw9LRU899XU1tMpaUFM7WtJOGmHYsR047GDxKUJh4397DYSqacxcxprBWNCUj w65EFRMyClPJGr22TX6JN8fqXvYsA0PzNuPykV18DijWwC+E0TJTw5ljB9OILIUR5rwZ CKkQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:arc-authentication-results; bh=4qyYZrpxhLT7KYns6bWpwyOnI4etYH4mLVrpYDCzMAE=; b=LS8eKfTrYI1bLXW0ArhSZdLzF1O7IvzajQyUQaBjQ5Rw7RA6eomRBFC7evMmlT0xqM BXDXV6npvg0lic2w8y+fDfEonKkJw+AO4vVt0OWobaEO3wDispd8zA9lkHNJRrDXEziL fZz7I2+qxCBYiZcT5p2ZIHr1aVWdyHPxp+zauJ0Q8LjNwWq3C5tsrI4ky3ttHt40cGl1 899lfDfpyviILjAFvzUD5PBctCrwtphv8p5E5SUkeoNAW/1CI2jHaL0966MAiBbwphty qLz8paWJYPSJOQuJQzUdO6kgSG29CyaiFbBx+ZUFEz4i1Z6ZQOivaQT+CVB1Ju9Cbkk8 E3DA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id f8-v6si1255414pgf.166.2018.07.26.05.26.37; Thu, 26 Jul 2018 05:26:52 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731033AbeGZNk7 (ORCPT + 99 others); Thu, 26 Jul 2018 09:40:59 -0400 Received: from szxga04-in.huawei.com ([45.249.212.190]:10129 "EHLO huawei.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1730280AbeGZNk7 (ORCPT ); Thu, 26 Jul 2018 09:40:59 -0400 Received: from DGGEMS408-HUB.china.huawei.com (unknown [172.30.72.59]) by Forcepoint Email with ESMTP id 5F88A8A35B451; Thu, 26 Jul 2018 20:24:19 +0800 (CST) Received: from szvp000100637.huawei.com (10.162.55.131) by smtp.huawei.com (10.3.19.208) with Microsoft SMTP Server (TLS) id 14.3.382.0; Thu, 26 Jul 2018 20:24:14 +0800 From: Gao Xiang To: Greg Kroah-Hartman , CC: , , , , , , , , Gao Xiang Subject: [PATCH 05/25] staging: erofs: add inode operations Date: Thu, 26 Jul 2018 20:21:48 +0800 Message-ID: <1532607728-103372-6-git-send-email-gaoxiang25@huawei.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1532607728-103372-1-git-send-email-gaoxiang25@huawei.com> References: <1527764767-22190-1-git-send-email-gaoxiang25@huawei.com> <1532607728-103372-1-git-send-email-gaoxiang25@huawei.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [10.162.55.131] X-CFilter-Loop: Reflected Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This adds core functions to get, read an inode. Signed-off-by: Miao Xie Signed-off-by: Chao Yu Signed-off-by: Gao Xiang --- drivers/staging/erofs/inode.c | 210 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 210 insertions(+) create mode 100644 drivers/staging/erofs/inode.c diff --git a/drivers/staging/erofs/inode.c b/drivers/staging/erofs/inode.c new file mode 100644 index 0000000..74e65be --- /dev/null +++ b/drivers/staging/erofs/inode.c @@ -0,0 +1,210 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * linux/drivers/staging/erofs/inode.c + * + * Copyright (C) 2017-2018 HUAWEI, Inc. + * http://www.huawei.com/ + * Created by Gao Xiang + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of the Linux + * distribution for more details. + */ +#include "internal.h" + +/* no locking */ +static int read_inode(struct inode *inode, void *data) +{ + struct erofs_vnode *vi = EROFS_V(inode); + struct erofs_inode_v1 *v1 = data; + const unsigned advise = le16_to_cpu(v1->i_advise); + + vi->data_mapping_mode = __inode_data_mapping(advise); + + if (unlikely(vi->data_mapping_mode >= EROFS_INODE_LAYOUT_MAX)) { + errln("unknown data mapping mode %u of nid %llu", + vi->data_mapping_mode, vi->nid); + DBG_BUGON(1); + return -EIO; + } + + if (__inode_version(advise) == EROFS_INODE_LAYOUT_V2) { + struct erofs_inode_v2 *v2 = data; + + vi->inode_isize = sizeof(struct erofs_inode_v2); + vi->xattr_isize = ondisk_xattr_ibody_size(v2->i_xattr_icount); + + vi->raw_blkaddr = le32_to_cpu(v2->i_u.raw_blkaddr); + inode->i_mode = le16_to_cpu(v2->i_mode); + + i_uid_write(inode, le32_to_cpu(v2->i_uid)); + i_gid_write(inode, le32_to_cpu(v2->i_gid)); + set_nlink(inode, le32_to_cpu(v2->i_nlink)); + + /* ns timestamp */ + inode->i_mtime.tv_sec = inode->i_ctime.tv_sec = + le64_to_cpu(v2->i_ctime); + inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = + le32_to_cpu(v2->i_ctime_nsec); + + inode->i_size = le64_to_cpu(v2->i_size); + } else if (__inode_version(advise) == EROFS_INODE_LAYOUT_V1) { + struct erofs_sb_info *sbi = EROFS_SB(inode->i_sb); + + vi->inode_isize = sizeof(struct erofs_inode_v1); + vi->xattr_isize = ondisk_xattr_ibody_size(v1->i_xattr_icount); + + vi->raw_blkaddr = le32_to_cpu(v1->i_u.raw_blkaddr); + inode->i_mode = le16_to_cpu(v1->i_mode); + + i_uid_write(inode, le16_to_cpu(v1->i_uid)); + i_gid_write(inode, le16_to_cpu(v1->i_gid)); + set_nlink(inode, le16_to_cpu(v1->i_nlink)); + + /* use build time to derive all file time */ + inode->i_mtime.tv_sec = inode->i_ctime.tv_sec = + sbi->build_time; + inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = + sbi->build_time_nsec; + + inode->i_size = le32_to_cpu(v1->i_size); + } else { + errln("unsupported on-disk inode version %u of nid %llu", + __inode_version(advise), vi->nid); + DBG_BUGON(1); + return -EIO; + } + + /* measure inode.i_blocks as the generic filesystem */ + inode->i_blocks = ((inode->i_size - 1) >> 9) + 1; + return 0; +} + +/* + * try_lock can be required since locking order is: + * file data(fs_inode) + * meta(bd_inode) + * but the majority of the callers is "iget", + * in that case we are pretty sure no deadlock since + * no data operations exist. However I tend to + * try_lock since it takes no much overhead and + * will success immediately. + */ +static int fill_inline_data(struct inode *inode, void *data, unsigned m_pofs) +{ + struct erofs_vnode *vi = EROFS_V(inode); + int mode = vi->data_mapping_mode; + + DBG_BUGON(mode >= EROFS_INODE_LAYOUT_MAX); + + /* should be inode inline C */ + if (mode != EROFS_INODE_LAYOUT_INLINE) + return 0; + + /* fast symlink (following ext4) */ + if (S_ISLNK(inode->i_mode) && inode->i_size < PAGE_SIZE) { + char *lnk = kmalloc(inode->i_size + 1, GFP_KERNEL); + + if (unlikely(lnk == NULL)) + return -ENOMEM; + + m_pofs += vi->inode_isize + vi->xattr_isize; + BUG_ON(m_pofs + inode->i_size > PAGE_SIZE); + + /* get in-page inline data */ + memcpy(lnk, data + m_pofs, inode->i_size); + lnk[inode->i_size] = '\0'; + + inode->i_link = lnk; + set_inode_fast_symlink(inode); + } + return -EAGAIN; +} + +static int fill_inode(struct inode *inode, int isdir) +{ + struct erofs_sb_info *sbi = EROFS_SB(inode->i_sb); + struct erofs_vnode *vi = EROFS_V(inode); + struct page *page; + void *data; + int err; + erofs_blk_t blkaddr; + unsigned ofs; + + blkaddr = erofs_blknr(iloc(sbi, vi->nid)); + ofs = erofs_blkoff(iloc(sbi, vi->nid)); + + debugln("%s, reading inode nid %llu at %u of blkaddr %u", + __func__, vi->nid, ofs, blkaddr); + + page = erofs_get_meta_page(inode->i_sb, blkaddr, isdir); + + if (IS_ERR(page)) { + errln("failed to get inode (nid: %llu) page, err %ld", + vi->nid, PTR_ERR(page)); + return PTR_ERR(page); + } + + BUG_ON(!PageUptodate(page)); + data = page_address(page); + + err = read_inode(inode, data + ofs); + if (!err) { + /* setup the new inode */ + if (S_ISREG(inode->i_mode)) { + inode->i_fop = &generic_ro_fops; + } else if (S_ISDIR(inode->i_mode)) { + inode->i_op = + &erofs_dir_iops; + inode->i_fop = &erofs_dir_fops; + } else if (S_ISLNK(inode->i_mode)) { + /* by default, page_get_link is used for symlink */ + inode->i_op = + &page_symlink_inode_operations; + inode_nohighmem(inode); + } else { + err = -EIO; + goto out_unlock; + } + + if (is_inode_layout_compression(inode)) { + err = -ENOTSUPP; + goto out_unlock; + } + + inode->i_mapping->a_ops = &erofs_raw_access_aops; + + /* fill last page if inline data is available */ + fill_inline_data(inode, data, ofs); + } + +out_unlock: + unlock_page(page); + put_page(page); + return err; +} + +struct inode *erofs_iget(struct super_block *sb, + erofs_nid_t nid, bool isdir) +{ + struct inode *inode = iget_locked(sb, nid); + + if (unlikely(inode == NULL)) + return ERR_PTR(-ENOMEM); + + if (inode->i_state & I_NEW) { + int err; + struct erofs_vnode *vi = EROFS_V(inode); + vi->nid = nid; + + err = fill_inode(inode, isdir); + if (likely(!err)) + unlock_new_inode(inode); + else { + iget_failed(inode); + inode = ERR_PTR(err); + } + } + return inode; +} + -- 1.9.1