Whamcloud - gitweb
LU-13211 ldiskfs: rework data-in-dirent for linux 5.4.7+ 67/37467/6
authorShaun Tancheff <shaun.tancheff@hpe.com>
Thu, 20 Feb 2020 00:41:26 +0000 (18:41 -0600)
committerOleg Drokin <green@whamcloud.com>
Sun, 1 Mar 2020 05:37:12 +0000 (05:37 +0000)
Linux commit v5.4-rc3-92-g109ba779d6cc
ext4: check for directory entries too close to block end

This impacts the ext4-data-in-dirent.patch due to the usage
of EXT4_DIR_REC_LEN

Invert the original patch from:
  EXT4_DIR_REC_LEN(<int>)        => __EXT4_DIR_REC_LEN(<int>)
  EXT4_DIR_REC_LEN(de->name_len) => EXT4_DIR_REC_LEN(de)
to:
  EXT4_DIR_REC_LEN(<int>)        => EXT4_DIR_REC_LEN(<int>)
  EXT4_DIR_REC_LEN(de->name_len) => EXT4_DIR_ENTRY_LEN(de)

Doing this allows the patch to apply cleanly over a wider
range of kernel releases.

Test-Parameters: trivial
Cray-bug-id: LUS-8478
Signed-off-by: Shaun Tancheff <shaun.tancheff@hpe.com>
Change-Id: I95349743f323bb150854ff4541bd2c88f01662a6
Reviewed-on: https://review.whamcloud.com/37467
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Petros Koutoupis <petros.koutoupis@hpe.com>
Reviewed-by: James Simmons <jsimmons@infradead.org>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
ldiskfs/kernel_patches/patches/linux-5.4/ext4-data-in-dirent.patch
lustre/osd-ldiskfs/osd_handler.c

index 3c3fffc..002fd52 100644 (file)
@@ -1,31 +1,35 @@
+this patch implements feature which allows ext4 fs users (e.g. Lustre)
+to store data in ext4 dirent.
+data is stored in ext4 dirent after file-name, this space is accounted
+in de->rec_len. flag EXT4_DIRENT_LUFID added to d_type if extra data
+is present.
+
+make use of dentry->d_fsdata to pass fid to ext4. so no
+changes in ext4_add_entry() interface required.
+
 diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
-index c7843b1..191304f 100644
+index 9fdd2b2..2a73a69 100644
 --- a/fs/ext4/dir.c
 +++ b/fs/ext4/dir.c
-@@ -70,11 +70,11 @@ int __ext4_check_dir_entry(const char *function, unsigned int line,
-       const int rlen = ext4_rec_len_from_disk(de->rec_len,
-                                               dir->i_sb->s_blocksize);
--      if (unlikely(rlen < EXT4_DIR_REC_LEN(1)))
-+      if (unlikely(rlen < __EXT4_DIR_REC_LEN(1)))
+@@ -77,7 +77,7 @@ int __ext4_check_dir_entry(const char *function, unsigned int line,
                error_msg = "rec_len is smaller than minimal";
        else if (unlikely(rlen % 4 != 0))
                error_msg = "rec_len % 4 != 0";
 -      else if (unlikely(rlen < EXT4_DIR_REC_LEN(de->name_len)))
-+      else if (unlikely(rlen < EXT4_DIR_REC_LEN(de)))
++      else if (unlikely(rlen < EXT4_DIR_ENTRY_LEN(de)))
                error_msg = "rec_len is too small for name_len";
        else if (unlikely(((char *) de - buf) + rlen > size))
                error_msg = "directory entry overrun";
-@@ -219,7 +219,7 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
+@@ -220,7 +220,7 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
                                 * failure will be detected in the
                                 * dirent test below. */
                                if (ext4_rec_len_from_disk(de->rec_len,
 -                                      sb->s_blocksize) < EXT4_DIR_REC_LEN(1))
-+                                  sb->s_blocksize) < __EXT4_DIR_REC_LEN(1))
++                                  sb->s_blocksize) < EXT4_DIR_REC_LEN(1))
                                        break;
                                i += ext4_rec_len_from_disk(de->rec_len,
                                                            sb->s_blocksize);
-@@ -442,12 +442,17 @@ int ext4_htree_store_dirent(struct file *dir_file, __u32 hash,
+@@ -443,12 +443,17 @@ int ext4_htree_store_dirent(struct file *dir_file, __u32 hash,
        struct fname *fname, *new_fn;
        struct dir_private_info *info;
        int len;
@@ -44,7 +48,7 @@ index c7843b1..191304f 100644
        new_fn = kzalloc(len, GFP_KERNEL);
        if (!new_fn)
                return -ENOMEM;
-@@ -456,7 +461,7 @@ int ext4_htree_store_dirent(struct file *dir_file, __u32 hash,
+@@ -457,7 +462,7 @@ int ext4_htree_store_dirent(struct file *dir_file, __u32 hash,
        new_fn->inode = le32_to_cpu(dirent->inode);
        new_fn->name_len = ent_name->len;
        new_fn->file_type = dirent->file_type;
@@ -54,10 +58,10 @@ index c7843b1..191304f 100644
  
        while (*p) {
 diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
-index ce12383..e89e6ce 100644
+index cb649f0..fe35251 100644
 --- a/fs/ext4/ext4.h
 +++ b/fs/ext4/ext4.h
-@@ -1069,6 +1069,7 @@ struct ext4_inode_info {
+@@ -1094,6 +1094,7 @@ struct ext4_inode_info {
        __u32 i_csum_seed;
  
        kprojid_t i_projid;
@@ -65,15 +69,15 @@ index ce12383..e89e6ce 100644
  };
  
  /*
-@@ -1112,6 +1113,7 @@ struct ext4_inode_info {
+@@ -1137,6 +1138,7 @@ struct ext4_inode_info {
  #define EXT4_MOUNT_POSIX_ACL          0x08000 /* POSIX Access Control Lists */
  #define EXT4_MOUNT_NO_AUTO_DA_ALLOC   0x10000 /* No auto delalloc mapping */
  #define EXT4_MOUNT_BARRIER            0x20000 /* Use block barriers */
-+#define EXT4_MOUNT_DIRDATA            0x40000 /* Data in directory entries*/
++#define EXT4_MOUNT_DIRDATA            0x60000 /* Data in directory entries*/
  #define EXT4_MOUNT_QUOTA              0x40000 /* Some quota option set */
  #define EXT4_MOUNT_USRQUOTA           0x80000 /* "old" user quota,
                                                 * enable enforcement for hidden
-@@ -1804,6 +1806,7 @@ EXT4_FEATURE_INCOMPAT_FUNCS(casefold,            CASEFOLD)
+@@ -1843,6 +1845,7 @@ EXT4_FEATURE_INCOMPAT_FUNCS(casefold,            CASEFOLD)
                                         EXT4_FEATURE_INCOMPAT_FLEX_BG| \
                                         EXT4_FEATURE_INCOMPAT_EA_INODE| \
                                         EXT4_FEATURE_INCOMPAT_MMP | \
@@ -81,7 +85,7 @@ index ce12383..e89e6ce 100644
                                         EXT4_FEATURE_INCOMPAT_INLINE_DATA | \
                                         EXT4_FEATURE_INCOMPAT_ENCRYPT | \
                                         EXT4_FEATURE_INCOMPAT_CASEFOLD | \
-@@ -1980,6 +1983,43 @@ struct ext4_dir_entry_tail {
+@@ -2020,6 +2023,43 @@ struct ext4_dir_entry_tail {
  #define EXT4_FT_SYMLINK               7
  
  #define EXT4_FT_MAX           8
@@ -125,20 +129,25 @@ index ce12383..e89e6ce 100644
  
  #define EXT4_FT_DIR_CSUM      0xDE
  
-@@ -1990,8 +2030,11 @@ struct ext4_dir_entry_tail {
+@@ -2030,8 +2070,16 @@ struct ext4_dir_entry_tail {
   */
  #define EXT4_DIR_PAD                  4
  #define EXT4_DIR_ROUND                        (EXT4_DIR_PAD - 1)
 -#define EXT4_DIR_REC_LEN(name_len)    (((name_len) + 8 + EXT4_DIR_ROUND) & \
-+#define __EXT4_DIR_REC_LEN(name_len)  (((name_len) + 8 + EXT4_DIR_ROUND) & \
++#define EXT4_DIR_REC_LEN_(name_len)   (((name_len) + 8 + EXT4_DIR_ROUND) & \
                                         ~EXT4_DIR_ROUND)
-+#define EXT4_DIR_REC_LEN(de)          (__EXT4_DIR_REC_LEN((de)->name_len +\
++#define EXT4_DIR_ENTRY_LEN_(de)               (EXT4_DIR_REC_LEN_((de)->name_len +\
 +                                      ext4_get_dirent_data_len(de)))
++/* ldiskfs */
++#define EXT4_DIR_REC_LEN(name_len)    EXT4_DIR_REC_LEN_((name_len))
++#define EXT4_DIR_ENTRY_LEN(de)                EXT4_DIR_ENTRY_LEN_((de))
++/* lustre osd_handler compat */
++#define __EXT4_DIR_REC_LEN(name_len)  EXT4_DIR_REC_LEN_((name_len))
 +
  #define EXT4_MAX_REC_LEN              ((1<<16)-1)
  
  /*
-@@ -2418,11 +2461,11 @@ extern int ext4_find_dest_de(struct inode *dir, struct inode *inode,
+@@ -2491,11 +2539,11 @@ extern int ext4_find_dest_de(struct inode *dir, struct inode *inode,
                             struct buffer_head *bh,
                             void *buf, int buf_size,
                             struct ext4_filename *fname,
@@ -152,7 +161,7 @@ index ce12383..e89e6ce 100644
  static inline void ext4_update_dx_flag(struct inode *inode)
  {
        if (!ext4_has_feature_dir_index(inode->i_sb))
-@@ -2434,10 +2477,17 @@ static const unsigned char ext4_filetype_table[] = {
+@@ -2507,10 +2555,17 @@ static const unsigned char ext4_filetype_table[] = {
  
  static inline  unsigned char get_dtype(struct super_block *sb, int filetype)
  {
@@ -172,7 +181,7 @@ index ce12383..e89e6ce 100644
  }
  extern int ext4_check_all_de(struct inode *dir, struct buffer_head *bh,
                             void *buf, int buf_size);
-@@ -2600,6 +2650,8 @@ extern struct inode *ext4_create_inode(handle_t *handle,
+@@ -2673,6 +2728,8 @@ extern struct inode *ext4_create_inode(handle_t *handle,
  extern int ext4_delete_entry(handle_t *handle, struct inode * dir,
                             struct ext4_dir_entry_2 *de_del,
                             struct buffer_head *bh);
@@ -181,9 +190,9 @@ index ce12383..e89e6ce 100644
  extern int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
                                __u32 start_minor_hash, __u32 *next_hash);
  extern int ext4_search_dir(struct buffer_head *bh,
-@@ -3335,6 +3387,36 @@ static inline void ext4_clear_io_unwritten_flag(ext4_io_end_t *io_end)
- extern const struct iomap_ops ext4_iomap_ops;
+@@ -3428,6 +3485,36 @@ static inline int ext4_buffer_uptodate(struct buffer_head *bh)
+       return buffer_uptodate(bh);
+ }
  
 +/*
 + * Compute the total directory entry data length.
@@ -219,7 +228,7 @@ index ce12383..e89e6ce 100644
  
  #define EFSBADCRC     EBADMSG         /* Bad CRC detected */
 diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
-index f73bc39..7610cfe 100644
+index 2fec62d..3f35821 100644
 --- a/fs/ext4/inline.c
 +++ b/fs/ext4/inline.c
 @@ -1023,7 +1023,7 @@ static int ext4_add_dirent_to_inline(handle_t *handle,
@@ -240,58 +249,29 @@ index f73bc39..7610cfe 100644
  
        ext4_show_inline_dir(dir, iloc->bh, inline_start, inline_size);
  
-@@ -1100,7 +1100,7 @@ static int ext4_update_inline_dir(handle_t *handle, struct inode *dir,
-       int old_size = EXT4_I(dir)->i_inline_size - EXT4_MIN_INLINE_DATA_SIZE;
-       int new_size = get_max_inline_xattr_value_size(dir, iloc);
--      if (new_size - old_size <= EXT4_DIR_REC_LEN(1))
-+      if (new_size - old_size <= __EXT4_DIR_REC_LEN(1))
-               return -ENOSPC;
-       ret = ext4_update_inline_data(handle, dir,
-@@ -1381,7 +1381,7 @@ int htree_inlinedir_to_tree(struct file *dir_file,
+@@ -1378,7 +1378,7 @@ int ext4_inlinedir_to_tree(struct file *dir_file,
                        fake.name_len = 1;
                        strcpy(fake.name, ".");
                        fake.rec_len = ext4_rec_len_to_disk(
 -                                              EXT4_DIR_REC_LEN(fake.name_len),
-+                                              EXT4_DIR_REC_LEN(&fake),
++                                              EXT4_DIR_ENTRY_LEN(&fake),
                                                inline_size);
                        ext4_set_de_type(inode->i_sb, &fake, S_IFDIR);
                        de = &fake;
-@@ -1391,7 +1391,7 @@ int htree_inlinedir_to_tree(struct file *dir_file,
+@@ -1388,7 +1388,7 @@ int ext4_inlinedir_to_tree(struct file *dir_file,
                        fake.name_len = 2;
                        strcpy(fake.name, "..");
                        fake.rec_len = ext4_rec_len_to_disk(
 -                                              EXT4_DIR_REC_LEN(fake.name_len),
-+                                              EXT4_DIR_REC_LEN(&fake),
++                                              EXT4_DIR_ENTRY_LEN(&fake),
                                                inline_size);
                        ext4_set_de_type(inode->i_sb, &fake, S_IFDIR);
                        de = &fake;
-@@ -1489,8 +1489,8 @@ int ext4_read_inline_dir(struct file *file,
-        * So we will use extra_offset and extra_size to indicate them
-        * during the inline dir iteration.
-        */
--      dotdot_offset = EXT4_DIR_REC_LEN(1);
--      dotdot_size = dotdot_offset + EXT4_DIR_REC_LEN(2);
-+      dotdot_offset = __EXT4_DIR_REC_LEN(1);
-+      dotdot_size = dotdot_offset + __EXT4_DIR_REC_LEN(2);
-       extra_offset = dotdot_size - EXT4_INLINE_DOTDOT_SIZE;
-       extra_size = extra_offset + inline_size;
-@@ -1525,7 +1525,7 @@ int ext4_read_inline_dir(struct file *file,
-                        * failure will be detected in the
-                        * dirent test below. */
-                       if (ext4_rec_len_from_disk(de->rec_len, extra_size)
--                              < EXT4_DIR_REC_LEN(1))
-+                              < __EXT4_DIR_REC_LEN(1))
-                               break;
-                       i += ext4_rec_len_from_disk(de->rec_len,
-                                                   extra_size);
 diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
-index be8c35d..7c09936 100644
+index 8713671..23bd871 100644
 --- a/fs/ext4/namei.c
 +++ b/fs/ext4/namei.c
-@@ -245,7 +245,8 @@ static unsigned dx_get_count(struct dx_entry *entries);
+@@ -258,7 +258,8 @@ static unsigned dx_get_count(struct dx_entry *entries);
  static unsigned dx_get_limit(struct dx_entry *entries);
  static void dx_set_count(struct dx_entry *entries, unsigned value);
  static void dx_set_limit(struct dx_entry *entries, unsigned value);
@@ -301,7 +281,7 @@ index be8c35d..7c09936 100644
  static unsigned dx_node_limit(struct inode *dir);
  static struct dx_frame *dx_probe(struct ext4_filename *fname,
                                 struct inode *dir,
-@@ -388,22 +389,23 @@ static struct dx_countlimit *get_dx_countlimit(struct inode *inode,
+@@ -402,22 +403,23 @@ static struct dx_countlimit *get_dx_countlimit(struct inode *inode,
  {
        struct ext4_dir_entry *dp;
        struct dx_root_info *root;
@@ -320,7 +300,7 @@ index be8c35d..7c09936 100644
 +                  EXT4_BLOCK_SIZE(inode->i_sb) - dot_rec_len)
                        return NULL;
 -              root = (struct dx_root_info *)(((void *)dp + 12));
-+              dotdot_rec_len = EXT4_DIR_REC_LEN((struct ext4_dir_entry_2 *)dp);
++              dotdot_rec_len = EXT4_DIR_ENTRY_LEN((struct ext4_dir_entry_2 *)dp);
 +              root = (struct dx_root_info *)(((void *)dp + dotdot_rec_len));
                if (root->reserved_zero ||
                    root->info_length != sizeof(struct dx_root_info))
@@ -333,22 +313,22 @@ index be8c35d..7c09936 100644
  
        if (offset)
                *offset = count_offset;
-@@ -508,11 +510,12 @@ ext4_next_entry(struct ext4_dir_entry_2 *p, unsigned long blocksize)
+@@ -522,11 +524,12 @@ ext4_next_entry(struct ext4_dir_entry_2 *p, unsigned long blocksize)
   */
  struct dx_root_info *dx_get_dx_info(struct ext4_dir_entry_2 *de)
  {
 +      BUG_ON(de->name_len != 1);
        /* get dotdot first */
 -      de = (struct ext4_dir_entry_2 *)((char *)de + EXT4_DIR_REC_LEN(1));
-+      de = (struct ext4_dir_entry_2 *)((char *)de + EXT4_DIR_REC_LEN(de));
++      de = (struct ext4_dir_entry_2 *)((char *)de + EXT4_DIR_ENTRY_LEN(de));
  
        /* dx root info is after dotdot entry */
 -      de = (struct ext4_dir_entry_2 *)((char *)de + EXT4_DIR_REC_LEN(2));
-+      de = (struct ext4_dir_entry_2 *)((char *)de + EXT4_DIR_REC_LEN(de));
++      de = (struct ext4_dir_entry_2 *)((char *)de + EXT4_DIR_ENTRY_LEN(de));
  
        return (struct dx_root_info *)de;
  }
-@@ -557,10 +560,16 @@ static inline void dx_set_limit(struct dx_entry *entries, unsigned value)
+@@ -571,10 +574,16 @@ static inline void dx_set_limit(struct dx_entry *entries, unsigned value)
        ((struct dx_countlimit *) entries)->limit = cpu_to_le16(value);
  }
  
@@ -363,30 +343,21 @@ index be8c35d..7c09936 100644
 +
 +      BUG_ON(dot_de->name_len != 1);
 +      dotdot_de = ext4_next_entry(dot_de, dir->i_sb->s_blocksize);
-+      entry_space = dir->i_sb->s_blocksize - EXT4_DIR_REC_LEN(dot_de) -
-+                       EXT4_DIR_REC_LEN(dotdot_de) - infosize;
++      entry_space = dir->i_sb->s_blocksize - EXT4_DIR_ENTRY_LEN(dot_de) -
++                       EXT4_DIR_ENTRY_LEN(dotdot_de) - infosize;
  
        if (ext4_has_metadata_csum(dir->i_sb))
                entry_space -= sizeof(struct dx_tail);
-@@ -569,7 +578,7 @@ static inline unsigned dx_root_limit(struct inode *dir, unsigned infosize)
- static inline unsigned dx_node_limit(struct inode *dir)
- {
--      unsigned entry_space = dir->i_sb->s_blocksize - EXT4_DIR_REC_LEN(0);
-+      unsigned entry_space = dir->i_sb->s_blocksize - __EXT4_DIR_REC_LEN(0);
-       if (ext4_has_metadata_csum(dir->i_sb))
-               entry_space -= sizeof(struct dx_tail);
-@@ -681,7 +690,7 @@ static struct stats dx_show_leaf(struct inode *dir,
+@@ -695,7 +704,7 @@ static struct stats dx_show_leaf(struct inode *dir,
                                       (unsigned) ((char *) de - base));
  #endif
                        }
 -                      space += EXT4_DIR_REC_LEN(de->name_len);
-+                      space += EXT4_DIR_REC_LEN(de);
++                      space += EXT4_DIR_ENTRY_LEN(de);
                        names++;
                }
                de = ext4_next_entry(de, size);
-@@ -788,11 +797,14 @@ dx_probe(struct ext4_filename *fname, struct inode *dir,
+@@ -802,11 +811,14 @@ dx_probe(struct ext4_filename *fname, struct inode *dir,
  
        entries = (struct dx_entry *)(((char *)info) + info->info_length);
  
@@ -404,34 +375,25 @@ index be8c35d..7c09936 100644
                goto fail;
        }
  
-@@ -987,7 +999,7 @@ static int htree_dirblock_to_tree(struct file *dir_file,
-       de = (struct ext4_dir_entry_2 *) bh->b_data;
-       top = (struct ext4_dir_entry_2 *) ((char *) de +
-                                          dir->i_sb->s_blocksize -
--                                         EXT4_DIR_REC_LEN(0));
-+                                         __EXT4_DIR_REC_LEN(0));
- #ifdef CONFIG_FS_ENCRYPTION
-       /* Check if the directory is encrypted */
-       if (IS_ENCRYPTED(dir)) {
-@@ -1741,7 +1753,7 @@ dx_move_dirents(char *from, char *to, struct dx_map_entry *map, int count,
+@@ -1792,7 +1804,7 @@ dx_move_dirents(char *from, char *to, struct dx_map_entry *map, int count,
        while (count--) {
                struct ext4_dir_entry_2 *de = (struct ext4_dir_entry_2 *)
                                                (from + (map->offs<<2));
 -              rec_len = EXT4_DIR_REC_LEN(de->name_len);
-+              rec_len = EXT4_DIR_REC_LEN(de);
++              rec_len = EXT4_DIR_ENTRY_LEN(de);
                memcpy (to, de, rec_len);
                ((struct ext4_dir_entry_2 *) to)->rec_len =
                                ext4_rec_len_to_disk(rec_len, blocksize);
-@@ -1765,7 +1777,7 @@ static struct ext4_dir_entry_2* dx_pack_dirents(char *base, unsigned blocksize)
+@@ -1816,7 +1828,7 @@ static struct ext4_dir_entry_2* dx_pack_dirents(char *base, unsigned blocksize)
        while ((char*)de < base + blocksize) {
                next = ext4_next_entry(de, blocksize);
                if (de->inode && de->name_len) {
 -                      rec_len = EXT4_DIR_REC_LEN(de->name_len);
-+                      rec_len = EXT4_DIR_REC_LEN(de);
++                      rec_len = EXT4_DIR_ENTRY_LEN(de);
                        if (de > to)
                                memmove(to, de, rec_len);
                        to->rec_len = ext4_rec_len_to_disk(rec_len, blocksize);
-@@ -1896,14 +1908,16 @@ int ext4_find_dest_de(struct inode *dir, struct inode *inode,
+@@ -1943,14 +1955,16 @@ int ext4_find_dest_de(struct inode *dir, struct inode *inode,
                      struct buffer_head *bh,
                      void *buf, int buf_size,
                      struct ext4_filename *fname,
@@ -440,7 +402,7 @@ index be8c35d..7c09936 100644
  {
        struct ext4_dir_entry_2 *de;
 -      unsigned short reclen = EXT4_DIR_REC_LEN(fname_len(fname));
-+      unsigned short reclen = __EXT4_DIR_REC_LEN(fname_len(fname)) +
++      unsigned short reclen = EXT4_DIR_REC_LEN(fname_len(fname)) +
 +                                                (dlen ? *dlen : 0);
        int nlen, rlen;
        unsigned int offset = 0;
@@ -450,12 +412,12 @@ index be8c35d..7c09936 100644
        de = (struct ext4_dir_entry_2 *)buf;
        top = buf + buf_size - reclen;
        while ((char *) de <= top) {
-@@ -1912,10 +1926,26 @@ int ext4_find_dest_de(struct inode *dir, struct inode *inode,
+@@ -1959,10 +1973,26 @@ int ext4_find_dest_de(struct inode *dir, struct inode *inode,
                        return -EFSCORRUPTED;
                if (ext4_match(dir, fname, de))
                        return -EEXIST;
 -              nlen = EXT4_DIR_REC_LEN(de->name_len);
-+              nlen = EXT4_DIR_REC_LEN(de);
++              nlen = EXT4_DIR_ENTRY_LEN(de);
                rlen = ext4_rec_len_from_disk(de->rec_len, buf_size);
                if ((de->inode ? rlen - nlen : rlen) >= reclen)
                        break;
@@ -463,7 +425,7 @@ index be8c35d..7c09936 100644
 +               * required for just the entry, no FID */
 +              if (fname_len(fname) == 2 && memcmp(fname_name(fname), "..", 2) == 0) {
 +                      if ((de->inode ? rlen - nlen : rlen) >=
-+                          __EXT4_DIR_REC_LEN(fname_len(fname))) {
++                          EXT4_DIR_REC_LEN(fname_len(fname))) {
 +                              /* set dlen=1 to indicate not
 +                               * enough space store fid */
 +                              dlen ? *dlen = 1 : 0;
@@ -478,7 +440,7 @@ index be8c35d..7c09936 100644
                de = (struct ext4_dir_entry_2 *)((char *)de + rlen);
                offset += rlen;
        }
-@@ -1929,12 +1959,12 @@ int ext4_find_dest_de(struct inode *dir, struct inode *inode,
+@@ -1976,12 +2006,12 @@ int ext4_find_dest_de(struct inode *dir, struct inode *inode,
  void ext4_insert_dentry(struct inode *inode,
                        struct ext4_dir_entry_2 *de,
                        int buf_size,
@@ -489,11 +451,11 @@ index be8c35d..7c09936 100644
        int nlen, rlen;
  
 -      nlen = EXT4_DIR_REC_LEN(de->name_len);
-+      nlen = EXT4_DIR_REC_LEN(de);
++      nlen = EXT4_DIR_ENTRY_LEN(de);
        rlen = ext4_rec_len_from_disk(de->rec_len, buf_size);
        if (de->inode) {
                struct ext4_dir_entry_2 *de1 =
-@@ -1948,6 +1978,11 @@ void ext4_insert_dentry(struct inode *inode,
+@@ -1995,6 +2025,11 @@ void ext4_insert_dentry(struct inode *inode,
        ext4_set_de_type(inode->i_sb, de, inode->i_mode);
        de->name_len = fname_len(fname);
        memcpy(de->name, fname_name(fname), fname_len(fname));
@@ -505,7 +467,7 @@ index be8c35d..7c09936 100644
  }
  
  /*
-@@ -1965,14 +2000,19 @@ static int add_dirent_to_buf(handle_t *handle, struct ext4_filename *fname,
+@@ -2012,14 +2047,19 @@ static int add_dirent_to_buf(handle_t *handle, struct ext4_filename *fname,
  {
        unsigned int    blocksize = dir->i_sb->s_blocksize;
        int             csum_size = 0;
@@ -527,7 +489,7 @@ index be8c35d..7c09936 100644
                if (err)
                        return err;
        }
-@@ -1984,7 +2024,10 @@ static int add_dirent_to_buf(handle_t *handle, struct ext4_filename *fname,
+@@ -2031,7 +2071,10 @@ static int add_dirent_to_buf(handle_t *handle, struct ext4_filename *fname,
        }
  
        /* By now the buffer is marked for journaling */
@@ -539,7 +501,7 @@ index be8c35d..7c09936 100644
  
        /*
         * XXX shouldn't update any times until successful
-@@ -2093,7 +2136,8 @@ static int make_indexed_dir(handle_t *handle, struct ext4_filename *fname,
+@@ -2136,7 +2179,8 @@ static int make_indexed_dir(handle_t *handle, struct ext4_filename *fname,
  
        dx_set_block(entries, 1);
        dx_set_count(entries, 1);
@@ -549,7 +511,7 @@ index be8c35d..7c09936 100644
  
        /* Initialize as for dx_probe */
        fname->hinfo.hash_version = dx_info->hash_version;
-@@ -2143,6 +2187,8 @@ static int ext4_update_dotdot(handle_t *handle, struct dentry *dentry,
+@@ -2186,6 +2230,8 @@ static int ext4_update_dotdot(handle_t *handle, struct dentry *dentry,
        struct buffer_head *dir_block;
        struct ext4_dir_entry_2 *de;
        int len, journal = 0, err = 0;
@@ -558,42 +520,28 @@ index be8c35d..7c09936 100644
  
        if (IS_ERR(handle))
                return PTR_ERR(handle);
-@@ -2160,19 +2206,24 @@ static int ext4_update_dotdot(handle_t *handle, struct dentry *dentry,
-       /* the first item must be "." */
-       assert(de->name_len == 1 && de->name[0] == '.');
-       len = le16_to_cpu(de->rec_len);
--      assert(len >= EXT4_DIR_REC_LEN(1));
--      if (len > EXT4_DIR_REC_LEN(1)) {
-+      assert(len >= __EXT4_DIR_REC_LEN(1));
-+      if (len > __EXT4_DIR_REC_LEN(1)) {
-               BUFFER_TRACE(dir_block, "get_write_access");
-               err = ext4_journal_get_write_access(handle, dir_block);
-               if (err)
+@@ -2211,11 +2257,16 @@ static int ext4_update_dotdot(handle_t *handle, struct dentry *dentry,
                        goto out_journal;
  
                journal = 1;
 -              de->rec_len = cpu_to_le16(EXT4_DIR_REC_LEN(1));
-+              de->rec_len = cpu_to_le16(EXT4_DIR_REC_LEN(de));
++              de->rec_len = cpu_to_le16(EXT4_DIR_ENTRY_LEN(de));
        }
  
 -      len -= EXT4_DIR_REC_LEN(1);
 -      assert(len == 0 || len >= EXT4_DIR_REC_LEN(2));
-+      len -= EXT4_DIR_REC_LEN(de);
++      len -= EXT4_DIR_ENTRY_LEN(de);
 +      data = ext4_dentry_get_data(dir->i_sb,
 +                      (struct ext4_dentry_param *)dentry->d_fsdata);
 +      if (data)
 +              dlen = *data + 1;
-+      assert(len == 0 || len >= __EXT4_DIR_REC_LEN(2 + dlen));
++      assert(len == 0 || len >= EXT4_DIR_REC_LEN(2 + dlen));
 +
        de = (struct ext4_dir_entry_2 *)
                        ((char *) de + le16_to_cpu(de->rec_len));
        if (!journal) {
-@@ -2186,10 +2237,15 @@ static int ext4_update_dotdot(handle_t *handle, struct dentry *dentry,
-       if (len > 0)
-               de->rec_len = cpu_to_le16(len);
-       else
--              assert(le16_to_cpu(de->rec_len) >= EXT4_DIR_REC_LEN(2));
-+              assert(le16_to_cpu(de->rec_len) >= __EXT4_DIR_REC_LEN(2));
+@@ -2232,7 +2283,12 @@ static int ext4_update_dotdot(handle_t *handle, struct dentry *dentry,
+               assert(le16_to_cpu(de->rec_len) >= EXT4_DIR_REC_LEN(2));
        de->name_len = 2;
        strcpy(de->name, "..");
 -      ext4_set_de_type(dir->i_sb, de, S_IFDIR);
@@ -606,7 +554,7 @@ index be8c35d..7c09936 100644
  
  out_journal:
        if (journal) {
-@@ -2229,6 +2285,7 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
+@@ -2271,6 +2327,7 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
        ext4_lblk_t block, blocks;
        int     csum_size = 0;
  
@@ -614,7 +562,7 @@ index be8c35d..7c09936 100644
        if (ext4_has_metadata_csum(inode->i_sb))
                csum_size = sizeof(struct ext4_dir_entry_tail);
  
-@@ -2757,37 +2814,70 @@ err_unlock_inode:
+@@ -2803,37 +2860,70 @@ err_unlock_inode:
        return err;
  }
  
@@ -654,7 +602,7 @@ index be8c35d..7c09936 100644
 +              memcpy(&de->name[2], data1, *(char *) data1);
 +              de->file_type |= EXT4_DIRENT_LUFID;
 +      }
-+      de->rec_len = cpu_to_le16(EXT4_DIR_REC_LEN(de));
++      de->rec_len = cpu_to_le16(EXT4_DIR_ENTRY_LEN(de));
 +      dot_reclen = cpu_to_le16(de->rec_len);
        de = ext4_next_entry(de, blocksize);
        de->inode = cpu_to_le32(parent_ino);
@@ -678,7 +626,7 @@ index be8c35d..7c09936 100644
 -                              EXT4_DIR_REC_LEN(de->name_len), blocksize);
 -      strcpy(de->name, "..");
 -      ext4_set_de_type(inode->i_sb, de, S_IFDIR);
-+                              EXT4_DIR_REC_LEN(de), blocksize);
++                              EXT4_DIR_ENTRY_LEN(de), blocksize);
  
        return ext4_next_entry(de, blocksize);
  }
@@ -691,8 +639,8 @@ index be8c35d..7c09936 100644
 +      struct tp_block param;
        struct buffer_head *dir_block = NULL;
        struct ext4_dir_entry_2 *de;
-       struct ext4_dir_entry_tail *t;
-@@ -2812,7 +2902,11 @@ static int ext4_init_new_dir(handle_t *handle, struct inode *dir,
+       ext4_lblk_t block = 0;
+@@ -2857,7 +2947,11 @@ static int ext4_init_new_dir(handle_t *handle, struct inode *dir,
        if (IS_ERR(dir_block))
                return PTR_ERR(dir_block);
        de = (struct ext4_dir_entry_2 *)dir_block->b_data;
@@ -703,9 +651,9 @@ index be8c35d..7c09936 100644
 +      ext4_init_dot_dotdot((struct inode *)(&param), de, blocksize,
 +                           csum_size, dir->i_ino, 10);
        set_nlink(inode, 2);
-       if (csum_size) {
-               t = EXT4_DIRENT_TAIL(dir_block->b_data, blocksize);
-@@ -2829,6 +2923,29 @@ out:
+       if (csum_size)
+               ext4_initialize_dirent_tail(dir_block, blocksize);
+@@ -2872,6 +2966,29 @@ out:
        return err;
  }
  
@@ -735,7 +683,7 @@ index be8c35d..7c09936 100644
  static int ext4_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
  {
        handle_t *handle;
-@@ -2855,7 +2972,7 @@ retry:
+@@ -2898,7 +3015,7 @@ retry:
  
        inode->i_op = &ext4_dir_inode_operations;
        inode->i_fop = &ext4_dir_operations;
@@ -744,20 +692,11 @@ index be8c35d..7c09936 100644
        if (err)
                goto out_clear_inode;
        err = ext4_mark_inode_dirty(handle, inode);
-@@ -2906,7 +3023,7 @@ bool ext4_empty_dir(struct inode *inode)
-       }
-       sb = inode->i_sb;
--      if (inode->i_size < EXT4_DIR_REC_LEN(1) + EXT4_DIR_REC_LEN(2)) {
-+      if (inode->i_size < __EXT4_DIR_REC_LEN(1) + __EXT4_DIR_REC_LEN(2)) {
-               EXT4_ERROR_INODE(inode, "invalid size");
-               return true;
-       }
 diff --git a/fs/ext4/super.c b/fs/ext4/super.c
-index 1f1342f..33f7e88 100644
+index d202d6d..0fcc33b 100644
 --- a/fs/ext4/super.c
 +++ b/fs/ext4/super.c
-@@ -1445,7 +1445,7 @@ enum {
+@@ -1449,7 +1449,7 @@ enum {
        Opt_data_err_abort, Opt_data_err_ignore, Opt_test_dummy_encryption,
        Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
        Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_jqfmt_vfsv1, Opt_quota,
@@ -766,7 +705,7 @@ index 1f1342f..33f7e88 100644
        Opt_usrquota, Opt_grpquota, Opt_prjquota, Opt_i_version, Opt_dax,
        Opt_stripe, Opt_delalloc, Opt_nodelalloc, Opt_warn_on_error,
        Opt_nowarn_on_error, Opt_mblk_io_submit,
-@@ -1521,6 +1521,7 @@ static const match_table_t tokens = {
+@@ -1525,6 +1525,7 @@ static const match_table_t tokens = {
        {Opt_nolazytime, "nolazytime"},
        {Opt_debug_want_extra_isize, "debug_want_extra_isize=%u"},
        {Opt_nodelalloc, "nodelalloc"},
@@ -774,7 +713,7 @@ index 1f1342f..33f7e88 100644
        {Opt_removed, "mblk_io_submit"},
        {Opt_removed, "nomblk_io_submit"},
        {Opt_block_validity, "block_validity"},
-@@ -1744,6 +1745,7 @@ static const struct mount_opts {
+@@ -1748,6 +1749,7 @@ static const struct mount_opts {
        {Opt_usrjquota, 0, MOPT_Q},
        {Opt_grpjquota, 0, MOPT_Q},
        {Opt_offusrjquota, 0, MOPT_Q},
index 51dae97..f9c29ff 100644 (file)
@@ -6719,6 +6719,11 @@ static int osd_it_ea_key_size(const struct lu_env *env, const struct dt_it *di)
        return it->oie_dirent->oied_namelen;
 }
 
+#if defined LDISKFS_DIR_ENTRY_LEN && defined LDISKFS_DIR_ENTRY_LEN_
+#undef LDISKFS_DIR_REC_LEN
+#define LDISKFS_DIR_REC_LEN(de)                LDISKFS_DIR_ENTRY_LEN_((de))
+#endif
+
 static inline bool osd_dotdot_has_space(struct ldiskfs_dir_entry_2 *de)
 {
        if (LDISKFS_DIR_REC_LEN(de) >=