aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/namei.c
diff options
context:
space:
mode:
authorTao Ma <boyu.mt@taobao.com>2012-12-10 14:05:59 -0500
committerTheodore Ts'o <tytso@mit.edu>2012-12-10 14:05:59 -0500
commit3c47d54170b6a678875566b1b8d6dcf57904e49b (patch)
tree6fdde24d7d168265eb227e63c209f23931e7f53b /fs/ext4/namei.c
parent978fef914a2e6b8ad5672d0a39f9201b7aa7c396 (diff)
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: Tao Ma <boyu.mt@taobao.com> Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/namei.c')
-rw-r--r--fs/ext4/namei.c34
1 files changed, 24 insertions, 10 deletions
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index bb9259d20b55..3cde36bd8020 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -202,13 +202,8 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
202 struct inode *inode); 202 struct inode *inode);
203 203
204/* checksumming functions */ 204/* checksumming functions */
205#define EXT4_DIRENT_TAIL(block, blocksize) \ 205void initialize_dirent_tail(struct ext4_dir_entry_tail *t,
206 ((struct ext4_dir_entry_tail *)(((void *)(block)) + \ 206 unsigned int blocksize)
207 ((blocksize) - \
208 sizeof(struct ext4_dir_entry_tail))))
209
210static void initialize_dirent_tail(struct ext4_dir_entry_tail *t,
211 unsigned int blocksize)
212{ 207{
213 memset(t, 0, sizeof(struct ext4_dir_entry_tail)); 208 memset(t, 0, sizeof(struct ext4_dir_entry_tail));
214 t->det_rec_len = ext4_rec_len_to_disk( 209 t->det_rec_len = ext4_rec_len_to_disk(
@@ -307,9 +302,9 @@ static void ext4_dirent_csum_set(struct inode *inode,
307 (void *)t - (void *)dirent); 302 (void *)t - (void *)dirent);
308} 303}
309 304
310static inline int ext4_handle_dirty_dirent_node(handle_t *handle, 305int ext4_handle_dirty_dirent_node(handle_t *handle,
311 struct inode *inode, 306 struct inode *inode,
312 struct buffer_head *bh) 307 struct buffer_head *bh)
313{ 308{
314 ext4_dirent_csum_set(inode, (struct ext4_dir_entry *)bh->b_data); 309 ext4_dirent_csum_set(inode, (struct ext4_dir_entry *)bh->b_data);
315 return ext4_handle_dirty_metadata(handle, inode, bh); 310 return ext4_handle_dirty_metadata(handle, inode, bh);
@@ -1878,6 +1873,17 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
1878 blocksize = sb->s_blocksize; 1873 blocksize = sb->s_blocksize;
1879 if (!dentry->d_name.len) 1874 if (!dentry->d_name.len)
1880 return -EINVAL; 1875 return -EINVAL;
1876
1877 if (ext4_has_inline_data(dir)) {
1878 retval = ext4_try_add_inline_entry(handle, dentry, inode);
1879 if (retval < 0)
1880 return retval;
1881 if (retval == 1) {
1882 retval = 0;
1883 return retval;
1884 }
1885 }
1886
1881 if (is_dx(dir)) { 1887 if (is_dx(dir)) {
1882 retval = ext4_dx_add_entry(handle, dentry, inode); 1888 retval = ext4_dx_add_entry(handle, dentry, inode);
1883 if (!retval || (retval != ERR_BAD_DX_DIR)) 1889 if (!retval || (retval != ERR_BAD_DX_DIR))
@@ -2301,6 +2307,14 @@ static int ext4_init_new_dir(handle_t *handle, struct inode *dir,
2301 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) 2307 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
2302 csum_size = sizeof(struct ext4_dir_entry_tail); 2308 csum_size = sizeof(struct ext4_dir_entry_tail);
2303 2309
2310 if (ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA)) {
2311 err = ext4_try_create_inline_dir(handle, dir, inode);
2312 if (err < 0 && err != -ENOSPC)
2313 goto out;
2314 if (!err)
2315 goto out;
2316 }
2317
2304 inode->i_size = EXT4_I(inode)->i_disksize = blocksize; 2318 inode->i_size = EXT4_I(inode)->i_disksize = blocksize;
2305 dir_block = ext4_bread(handle, inode, 0, 1, &err); 2319 dir_block = ext4_bread(handle, inode, 0, 1, &err);
2306 if (!(dir_block = ext4_bread(handle, inode, 0, 1, &err))) { 2320 if (!(dir_block = ext4_bread(handle, inode, 0, 1, &err))) {