diff options
author | Tao Ma <boyu.mt@taobao.com> | 2012-12-10 20:04:52 +0100 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2012-12-10 20:04:52 +0100 |
commit | 46c7f254543dedcf134ad05091ed2b935a9a597d (patch) | |
tree | dbcb8b71bfe5aebef35964a04f086e2d4eee7ad7 /fs/ext4/inline.c | |
parent | ext4: add the basic function for inline data support (diff) | |
download | linux-46c7f254543dedcf134ad05091ed2b935a9a597d.tar.xz linux-46c7f254543dedcf134ad05091ed2b935a9a597d.zip |
ext4: add read support for inline data
Let readpage and readpages handle the case when we want to read an
inlined file.
Signed-off-by: Tao Ma <boyu.mt@taobao.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/inline.c')
-rw-r--r-- | fs/ext4/inline.c | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c index bec68b364832..e4a41d5d06db 100644 --- a/fs/ext4/inline.c +++ b/fs/ext4/inline.c @@ -454,6 +454,67 @@ out: return error; } +static int ext4_read_inline_page(struct inode *inode, struct page *page) +{ + void *kaddr; + int ret = 0; + size_t len; + struct ext4_iloc iloc; + + BUG_ON(!PageLocked(page)); + BUG_ON(!ext4_has_inline_data(inode)); + BUG_ON(page->index); + + if (!EXT4_I(inode)->i_inline_off) { + ext4_warning(inode->i_sb, "inode %lu doesn't have inline data.", + inode->i_ino); + goto out; + } + + ret = ext4_get_inode_loc(inode, &iloc); + if (ret) + goto out; + + len = min_t(size_t, ext4_get_inline_size(inode), i_size_read(inode)); + kaddr = kmap_atomic(page); + ret = ext4_read_inline_data(inode, kaddr, len, &iloc); + flush_dcache_page(page); + kunmap_atomic(kaddr); + zero_user_segment(page, len, PAGE_CACHE_SIZE); + SetPageUptodate(page); + brelse(iloc.bh); + +out: + return ret; +} + +int ext4_readpage_inline(struct inode *inode, struct page *page) +{ + int ret = 0; + + down_read(&EXT4_I(inode)->xattr_sem); + if (!ext4_has_inline_data(inode)) { + up_read(&EXT4_I(inode)->xattr_sem); + return -EAGAIN; + } + + /* + * Current inline data can only exist in the 1st page, + * So for all the other pages, just set them uptodate. + */ + if (!page->index) + ret = ext4_read_inline_page(inode, page); + else if (!PageUptodate(page)) { + zero_user_segment(page, 0, PAGE_CACHE_SIZE); + SetPageUptodate(page); + } + + up_read(&EXT4_I(inode)->xattr_sem); + + unlock_page(page); + return ret >= 0 ? 0 : ret; +} + int ext4_destroy_inline_data(handle_t *handle, struct inode *inode) { int ret; |