Commit 3c47d541 authored by Tao Ma's avatar Tao Ma Committed by Theodore Ts'o

ext4: let add_dir_entry handle inline data properly

This patch let add_dir_entry handle the inline data case. So the
dir is initialized as inline dir first and then we can try to add
some files to it, when the inline space can't hold all the entries,
a dir block will be created and the dir entry will be moved to it.

Also for an inlined dir, "." and ".." are removed and we only use
4 bytes to store the parent inode number. These 2 entries will be
added when we convert an inline dir to a block-based one.

[ Folded in patch from Dan Carpenter to remove an unused variable. ]
Signed-off-by: default avatarTao Ma <boyu.mt@taobao.com>
Signed-off-by: default avatarDan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: default avatar"Theodore Ts'o" <tytso@mit.edu>
parent 978fef91
...@@ -1616,6 +1616,11 @@ struct ext4_dir_entry_tail { ...@@ -1616,6 +1616,11 @@ struct ext4_dir_entry_tail {
__le32 det_checksum; /* crc32c(uuid+inum+dirblock) */ __le32 det_checksum; /* crc32c(uuid+inum+dirblock) */
}; };
#define EXT4_DIRENT_TAIL(block, blocksize) \
((struct ext4_dir_entry_tail *)(((void *)(block)) + \
((blocksize) - \
sizeof(struct ext4_dir_entry_tail))))
/* /*
* Ext4 directory file types. Only the low 3 bits are used. The * Ext4 directory file types. Only the low 3 bits are used. The
* other bits are reserved for now. * other bits are reserved for now.
...@@ -2435,6 +2440,11 @@ extern struct ext4_dir_entry_2 *ext4_init_dot_dotdot(struct inode *inode, ...@@ -2435,6 +2440,11 @@ extern struct ext4_dir_entry_2 *ext4_init_dot_dotdot(struct inode *inode,
struct ext4_dir_entry_2 *de, struct ext4_dir_entry_2 *de,
int blocksize, int csum_size, int blocksize, int csum_size,
unsigned int parent_ino, int dotdot_real_len); unsigned int parent_ino, int dotdot_real_len);
extern void initialize_dirent_tail(struct ext4_dir_entry_tail *t,
unsigned int blocksize);
extern int ext4_handle_dirty_dirent_node(handle_t *handle,
struct inode *inode,
struct buffer_head *bh);
/* symlink.c */ /* symlink.c */
extern const struct inode_operations ext4_symlink_inode_operations; extern const struct inode_operations ext4_symlink_inode_operations;
......
This diff is collapsed.
...@@ -202,13 +202,8 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry, ...@@ -202,13 +202,8 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
struct inode *inode); struct inode *inode);
/* checksumming functions */ /* checksumming functions */
#define EXT4_DIRENT_TAIL(block, blocksize) \ void initialize_dirent_tail(struct ext4_dir_entry_tail *t,
((struct ext4_dir_entry_tail *)(((void *)(block)) + \ unsigned int blocksize)
((blocksize) - \
sizeof(struct ext4_dir_entry_tail))))
static void initialize_dirent_tail(struct ext4_dir_entry_tail *t,
unsigned int blocksize)
{ {
memset(t, 0, sizeof(struct ext4_dir_entry_tail)); memset(t, 0, sizeof(struct ext4_dir_entry_tail));
t->det_rec_len = ext4_rec_len_to_disk( t->det_rec_len = ext4_rec_len_to_disk(
...@@ -307,9 +302,9 @@ static void ext4_dirent_csum_set(struct inode *inode, ...@@ -307,9 +302,9 @@ static void ext4_dirent_csum_set(struct inode *inode,
(void *)t - (void *)dirent); (void *)t - (void *)dirent);
} }
static inline int ext4_handle_dirty_dirent_node(handle_t *handle, int ext4_handle_dirty_dirent_node(handle_t *handle,
struct inode *inode, struct inode *inode,
struct buffer_head *bh) struct buffer_head *bh)
{ {
ext4_dirent_csum_set(inode, (struct ext4_dir_entry *)bh->b_data); ext4_dirent_csum_set(inode, (struct ext4_dir_entry *)bh->b_data);
return ext4_handle_dirty_metadata(handle, inode, bh); return ext4_handle_dirty_metadata(handle, inode, bh);
...@@ -1878,6 +1873,17 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry, ...@@ -1878,6 +1873,17 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
blocksize = sb->s_blocksize; blocksize = sb->s_blocksize;
if (!dentry->d_name.len) if (!dentry->d_name.len)
return -EINVAL; return -EINVAL;
if (ext4_has_inline_data(dir)) {
retval = ext4_try_add_inline_entry(handle, dentry, inode);
if (retval < 0)
return retval;
if (retval == 1) {
retval = 0;
return retval;
}
}
if (is_dx(dir)) { if (is_dx(dir)) {
retval = ext4_dx_add_entry(handle, dentry, inode); retval = ext4_dx_add_entry(handle, dentry, inode);
if (!retval || (retval != ERR_BAD_DX_DIR)) if (!retval || (retval != ERR_BAD_DX_DIR))
...@@ -2301,6 +2307,14 @@ static int ext4_init_new_dir(handle_t *handle, struct inode *dir, ...@@ -2301,6 +2307,14 @@ static int ext4_init_new_dir(handle_t *handle, struct inode *dir,
EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
csum_size = sizeof(struct ext4_dir_entry_tail); csum_size = sizeof(struct ext4_dir_entry_tail);
if (ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA)) {
err = ext4_try_create_inline_dir(handle, dir, inode);
if (err < 0 && err != -ENOSPC)
goto out;
if (!err)
goto out;
}
inode->i_size = EXT4_I(inode)->i_disksize = blocksize; inode->i_size = EXT4_I(inode)->i_disksize = blocksize;
dir_block = ext4_bread(handle, inode, 0, 1, &err); dir_block = ext4_bread(handle, inode, 0, 1, &err);
if (!(dir_block = ext4_bread(handle, inode, 0, 1, &err))) { if (!(dir_block = ext4_bread(handle, inode, 0, 1, &err))) {
......
...@@ -163,6 +163,11 @@ extern int ext4_da_write_inline_data_begin(struct address_space *mapping, ...@@ -163,6 +163,11 @@ extern int ext4_da_write_inline_data_begin(struct address_space *mapping,
extern int ext4_da_write_inline_data_end(struct inode *inode, loff_t pos, extern int ext4_da_write_inline_data_end(struct inode *inode, loff_t pos,
unsigned len, unsigned copied, unsigned len, unsigned copied,
struct page *page); struct page *page);
extern int ext4_try_add_inline_entry(handle_t *handle, struct dentry *dentry,
struct inode *inode);
extern int ext4_try_create_inline_dir(handle_t *handle,
struct inode *parent,
struct inode *inode);
# else /* CONFIG_EXT4_FS_XATTR */ # else /* CONFIG_EXT4_FS_XATTR */
static inline int static inline int
...@@ -327,6 +332,20 @@ static inline int ext4_da_write_inline_data_end(struct inode *inode, loff_t pos, ...@@ -327,6 +332,20 @@ static inline int ext4_da_write_inline_data_end(struct inode *inode, loff_t pos,
{ {
return 0; return 0;
} }
static inline int ext4_try_add_inline_entry(handle_t *handle,
struct dentry *dentry,
struct inode *inode)
{
return 0;
}
static inline int ext4_try_create_inline_dir(handle_t *handle,
struct inode *parent,
struct inode *inode)
{
return 0;
}
# endif /* CONFIG_EXT4_FS_XATTR */ # endif /* CONFIG_EXT4_FS_XATTR */
#ifdef CONFIG_EXT4_FS_SECURITY #ifdef CONFIG_EXT4_FS_SECURITY
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment