f2fs: fix to truncate inline data in inode page when setattr
authorChao Yu <chao2.yu@samsung.com>
Tue, 29 Apr 2014 01:03:03 +0000 (09:03 +0800)
committerJaegeuk Kim <jaegeuk.kim@samsung.com>
Wed, 7 May 2014 01:21:58 +0000 (10:21 +0900)
Previous we do not truncate inline data in inode page when setattr, so following
case could still read the inline data which has already truncated:

1.write inline data
2.ftruncate size to 0
3.ftruncate size to max inline data size
4.read from offset 0

This patch introduces truncate_inline_data() to fix this problem.

change log from v1:
 o fix a bug and do not truncate first page data after truncate inline data.

Signed-off-by: Chao Yu <chao2.yu@samsung.com>
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
fs/f2fs/f2fs.h
fs/f2fs/file.c
fs/f2fs/inline.c

index 2b67679f88b6aa5b7c93297916aba198857e2a55..676a2c6ccec744d6962787a80743f478339a7c9e 100644 (file)
@@ -1410,5 +1410,6 @@ bool f2fs_may_inline(struct inode *);
 int f2fs_read_inline_data(struct inode *, struct page *);
 int f2fs_convert_inline_data(struct inode *, pgoff_t);
 int f2fs_write_inline_data(struct inode *, struct page *, unsigned int);
+void truncate_inline_data(struct inode *, u64);
 int recover_inline_data(struct inode *, struct page *);
 #endif
index b9f4fbf5c07ed5c1dbeb29ec57a835b0d43ebbd8..d97e5c458f360bab7e531c771ba7e60026650dfa 100644 (file)
@@ -369,6 +369,9 @@ static void truncate_partial_data_page(struct inode *inode, u64 from)
        unsigned offset = from & (PAGE_CACHE_SIZE - 1);
        struct page *page;
 
+       if (f2fs_has_inline_data(inode))
+               return truncate_inline_data(inode, from);
+
        if (!offset)
                return;
 
index 3258c7cf00d5b62312f8f1ad634100f4844f06ae..d215dbb09f07dab9feba5d7a03479a9d01fb04b5 100644 (file)
@@ -176,6 +176,24 @@ int f2fs_write_inline_data(struct inode *inode,
        return 0;
 }
 
+void truncate_inline_data(struct inode *inode, u64 from)
+{
+       struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+       struct page *ipage;
+
+       if (from >= MAX_INLINE_DATA)
+               return;
+
+       ipage = get_node_page(sbi, inode->i_ino);
+       if (IS_ERR(ipage))
+               return;
+
+       zero_user_segment(ipage, INLINE_DATA_OFFSET + from,
+                               INLINE_DATA_OFFSET + MAX_INLINE_DATA);
+       set_page_dirty(ipage);
+       f2fs_put_page(ipage, 1);
+}
+
 int recover_inline_data(struct inode *inode, struct page *npage)
 {
        struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);