Merge tag 'erofs-for-5.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/xiang...
[linux-2.6-microblaze.git] / fs / erofs / inode.c
index aa8a0d7..31ac3a7 100644 (file)
@@ -2,6 +2,7 @@
 /*
  * Copyright (C) 2017-2018 HUAWEI, Inc.
  *             https://www.huawei.com/
+ * Copyright (C) 2021, Alibaba Cloud
  */
 #include "xattr.h"
 
@@ -122,8 +123,11 @@ static struct page *erofs_read_inode(struct inode *inode,
                /* total blocks for compressed files */
                if (erofs_inode_is_data_compressed(vi->datalayout))
                        nblks = le32_to_cpu(die->i_u.compressed_blocks);
-
+               else if (vi->datalayout == EROFS_INODE_CHUNK_BASED)
+                       /* fill chunked inode summary info */
+                       vi->chunkformat = le16_to_cpu(die->i_u.c.format);
                kfree(copied);
+               copied = NULL;
                break;
        case EROFS_INODE_LAYOUT_COMPACT:
                vi->inode_isize = sizeof(struct erofs_inode_compact);
@@ -160,6 +164,8 @@ static struct page *erofs_read_inode(struct inode *inode,
                inode->i_size = le32_to_cpu(dic->i_size);
                if (erofs_inode_is_data_compressed(vi->datalayout))
                        nblks = le32_to_cpu(dic->i_u.compressed_blocks);
+               else if (vi->datalayout == EROFS_INODE_CHUNK_BASED)
+                       vi->chunkformat = le16_to_cpu(dic->i_u.c.format);
                break;
        default:
                erofs_err(inode->i_sb,
@@ -169,11 +175,26 @@ static struct page *erofs_read_inode(struct inode *inode,
                goto err_out;
        }
 
+       if (vi->datalayout == EROFS_INODE_CHUNK_BASED) {
+               if (!(vi->chunkformat & EROFS_CHUNK_FORMAT_ALL)) {
+                       erofs_err(inode->i_sb,
+                                 "unsupported chunk format %x of nid %llu",
+                                 vi->chunkformat, vi->nid);
+                       err = -EOPNOTSUPP;
+                       goto err_out;
+               }
+               vi->chunkbits = LOG_BLOCK_SIZE +
+                       (vi->chunkformat & EROFS_CHUNK_FORMAT_BLKBITS_MASK);
+       }
        inode->i_mtime.tv_sec = inode->i_ctime.tv_sec;
        inode->i_atime.tv_sec = inode->i_ctime.tv_sec;
        inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec;
        inode->i_atime.tv_nsec = inode->i_ctime.tv_nsec;
 
+       inode->i_flags &= ~S_DAX;
+       if (test_opt(&sbi->ctx, DAX_ALWAYS) && S_ISREG(inode->i_mode) &&
+           vi->datalayout == EROFS_INODE_FLAT_PLAIN)
+               inode->i_flags |= S_DAX;
        if (!nblks)
                /* measure inode.i_blocks as generic filesystems */
                inode->i_blocks = roundup(inode->i_size, EROFS_BLKSIZ) >> 9;
@@ -247,7 +268,10 @@ static int erofs_fill_inode(struct inode *inode, int isdir)
        switch (inode->i_mode & S_IFMT) {
        case S_IFREG:
                inode->i_op = &erofs_generic_iops;
-               inode->i_fop = &generic_ro_fops;
+               if (erofs_inode_is_data_compressed(vi->datalayout))
+                       inode->i_fop = &generic_ro_fops;
+               else
+                       inode->i_fop = &erofs_file_fops;
                break;
        case S_IFDIR:
                inode->i_op = &erofs_dir_iops;
@@ -358,6 +382,7 @@ const struct inode_operations erofs_generic_iops = {
        .getattr = erofs_getattr,
        .listxattr = erofs_listxattr,
        .get_acl = erofs_get_acl,
+       .fiemap = erofs_fiemap,
 };
 
 const struct inode_operations erofs_symlink_iops = {