diff options
author | Tao Ma <boyu.mt@taobao.com> | 2012-12-10 14:06:00 -0500 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2012-12-10 14:06:00 -0500 |
commit | e8e948e7802a2ab05c146d3e72a39b93b5718236 (patch) | |
tree | 3e6914f6b16c457e0d14cee75bf0149f730bbd99 /fs | |
parent | 7335cd3b41b1e704608ca46159641ca9cb598121 (diff) |
ext4: let ext4_find_entry handle inline data
Create a new function ext4_find_inline_entry() to handle the case of
inline data.
Signed-off-by: Tao Ma <boyu.mt@taobao.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ext4/inline.c | 48 | ||||
-rw-r--r-- | fs/ext4/namei.c | 10 | ||||
-rw-r--r-- | fs/ext4/xattr.h | 13 |
3 files changed, 70 insertions, 1 deletions
diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c index 471504133c7..0a8f5a86549 100644 --- a/fs/ext4/inline.c +++ b/fs/ext4/inline.c @@ -1462,6 +1462,54 @@ out: return ret; } +struct buffer_head *ext4_find_inline_entry(struct inode *dir, + const struct qstr *d_name, + struct ext4_dir_entry_2 **res_dir, + int *has_inline_data) +{ + int ret; + struct ext4_iloc iloc; + void *inline_start; + int inline_size; + + if (ext4_get_inode_loc(dir, &iloc)) + return NULL; + + down_read(&EXT4_I(dir)->xattr_sem); + if (!ext4_has_inline_data(dir)) { + *has_inline_data = 0; + goto out; + } + + inline_start = (void *)ext4_raw_inode(&iloc)->i_block + + EXT4_INLINE_DOTDOT_SIZE; + inline_size = EXT4_MIN_INLINE_DATA_SIZE - EXT4_INLINE_DOTDOT_SIZE; + ret = search_dir(iloc.bh, inline_start, inline_size, + dir, d_name, 0, res_dir); + if (ret == 1) + goto out_find; + if (ret < 0) + goto out; + + if (ext4_get_inline_size(dir) == EXT4_MIN_INLINE_DATA_SIZE) + goto out; + + inline_start = ext4_get_inline_xattr_pos(dir, &iloc); + inline_size = ext4_get_inline_size(dir) - EXT4_MIN_INLINE_DATA_SIZE; + + ret = search_dir(iloc.bh, inline_start, inline_size, + dir, d_name, 0, res_dir); + if (ret == 1) + goto out_find; + +out: + brelse(iloc.bh); + iloc.bh = NULL; +out_find: + up_read(&EXT4_I(dir)->xattr_sem); + return iloc.bh; +} + int ext4_destroy_inline_data(handle_t *handle, struct inode *inode) { int ret; diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index d50684b9149..b498cafed12 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -1015,7 +1015,6 @@ static inline int search_dirblock(struct buffer_head *bh, d_name, offset, res_dir); } - /* * Directory block splitting, compacting */ @@ -1198,6 +1197,15 @@ static struct buffer_head * ext4_find_entry (struct inode *dir, namelen = d_name->len; if (namelen > EXT4_NAME_LEN) return NULL; + + if (ext4_has_inline_data(dir)) { + int has_inline_data = 1; + ret = ext4_find_inline_entry(dir, d_name, res_dir, + &has_inline_data); + if (has_inline_data) + return ret; + } + if ((namelen <= 2) && (name[0] == '.') && (name[1] == '.' || name[1] == '\0')) { /* diff --git a/fs/ext4/xattr.h b/fs/ext4/xattr.h index 539e6a08c95..c6f3dea88d6 100644 --- a/fs/ext4/xattr.h +++ b/fs/ext4/xattr.h @@ -171,6 +171,10 @@ extern int ext4_try_create_inline_dir(handle_t *handle, extern int ext4_read_inline_dir(struct file *filp, void *dirent, filldir_t filldir, int *has_inline_data); +extern struct buffer_head *ext4_find_inline_entry(struct inode *dir, + const struct qstr *d_name, + struct ext4_dir_entry_2 **res_dir, + int *has_inline_data); # else /* CONFIG_EXT4_FS_XATTR */ static inline int @@ -355,6 +359,15 @@ static inline int ext4_read_inline_dir(struct file *filp, { return 0; } + +static inline struct buffer_head * +ext4_find_inline_entry(struct inode *dir, + const struct qstr *d_name, + struct ext4_dir_entry_2 **res_dir, + int *has_inline_data) +{ + return NULL; +} # endif /* CONFIG_EXT4_FS_XATTR */ #ifdef CONFIG_EXT4_FS_SECURITY |