+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;
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;
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;
};
/*
-@@ -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 | \
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
#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,
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)
{
}
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);
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.
#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,
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);
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;
+ 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))
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);
}
+
+ 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);
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,
{
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;
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;
+ * 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;
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,
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));
}
/*
-@@ -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;
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 */
/*
* 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);
/* 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;
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);
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;
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;
}
+ 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);
- 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);
}
+ 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;
+ 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;
}
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;
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,
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"},
{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},