From a7cf78b5eb326fb953613154feb0edb871498473 Mon Sep 17 00:00:00 2001 From: Shaun Tancheff Date: Wed, 19 Feb 2020 18:41:26 -0600 Subject: [PATCH] LU-13211 ldiskfs: rework data-in-dirent for linux 5.4.7+ 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() => __EXT4_DIR_REC_LEN() EXT4_DIR_REC_LEN(de->name_len) => EXT4_DIR_REC_LEN(de) to: EXT4_DIR_REC_LEN() => EXT4_DIR_REC_LEN() 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 Change-Id: I95349743f323bb150854ff4541bd2c88f01662a6 Reviewed-on: https://review.whamcloud.com/37467 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Andreas Dilger Reviewed-by: Petros Koutoupis Reviewed-by: James Simmons Reviewed-by: Oleg Drokin --- .../patches/linux-5.4/ext4-data-in-dirent.patch | 241 ++++++++------------- lustre/osd-ldiskfs/osd_handler.c | 5 + 2 files changed, 95 insertions(+), 151 deletions(-) diff --git a/ldiskfs/kernel_patches/patches/linux-5.4/ext4-data-in-dirent.patch b/ldiskfs/kernel_patches/patches/linux-5.4/ext4-data-in-dirent.patch index 3c3fffc..002fd52 100644 --- a/ldiskfs/kernel_patches/patches/linux-5.4/ext4-data-in-dirent.patch +++ b/ldiskfs/kernel_patches/patches/linux-5.4/ext4-data-in-dirent.patch @@ -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 *)(¶m), 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}, diff --git a/lustre/osd-ldiskfs/osd_handler.c b/lustre/osd-ldiskfs/osd_handler.c index 51dae97..f9c29ff 100644 --- a/lustre/osd-ldiskfs/osd_handler.c +++ b/lustre/osd-ldiskfs/osd_handler.c @@ -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) >= -- 1.8.3.1