diff options
author | Jaegeuk Kim <jaegeuk@kernel.org> | 2014-08-07 19:32:25 -0400 |
---|---|---|
committer | Jaegeuk Kim <jaegeuk@kernel.org> | 2014-08-19 13:01:33 -0400 |
commit | b067ba1f1b3fa7ec798d35e12aed6cdba9cea905 (patch) | |
tree | 1095778a55a4577811f6f98d0e1a21822bbf47ab | |
parent | e1c42045203071c4634b89e696037357810d3083 (diff) |
f2fs: should convert inline_data during the mkwrite
If mkwrite is called to an inode having inline_data, it can overwrite the data
index space as NEW_ADDR. (e.g., the first 4 bytes are coincidently zero)
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
-rw-r--r-- | fs/f2fs/data.c | 2 | ||||
-rw-r--r-- | fs/f2fs/f2fs.h | 2 | ||||
-rw-r--r-- | fs/f2fs/file.c | 11 | ||||
-rw-r--r-- | fs/f2fs/inline.c | 20 |
4 files changed, 22 insertions, 13 deletions
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 7aef28d1fffa..ac3ccc25386b 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c | |||
@@ -946,7 +946,7 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping, | |||
946 | 946 | ||
947 | f2fs_balance_fs(sbi); | 947 | f2fs_balance_fs(sbi); |
948 | repeat: | 948 | repeat: |
949 | err = f2fs_convert_inline_data(inode, pos + len); | 949 | err = f2fs_convert_inline_data(inode, pos + len, NULL); |
950 | if (err) | 950 | if (err) |
951 | goto fail; | 951 | goto fail; |
952 | 952 | ||
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 790a0738d314..c8288c9a4e1e 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h | |||
@@ -1439,7 +1439,7 @@ extern const struct inode_operations f2fs_special_inode_operations; | |||
1439 | */ | 1439 | */ |
1440 | bool f2fs_may_inline(struct inode *); | 1440 | bool f2fs_may_inline(struct inode *); |
1441 | int f2fs_read_inline_data(struct inode *, struct page *); | 1441 | int f2fs_read_inline_data(struct inode *, struct page *); |
1442 | int f2fs_convert_inline_data(struct inode *, pgoff_t); | 1442 | int f2fs_convert_inline_data(struct inode *, pgoff_t, struct page *); |
1443 | int f2fs_write_inline_data(struct inode *, struct page *, unsigned int); | 1443 | int f2fs_write_inline_data(struct inode *, struct page *, unsigned int); |
1444 | void truncate_inline_data(struct inode *, u64); | 1444 | void truncate_inline_data(struct inode *, u64); |
1445 | int recover_inline_data(struct inode *, struct page *); | 1445 | int recover_inline_data(struct inode *, struct page *); |
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 87cdac4efeec..ecbdf6a6381c 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c | |||
@@ -41,6 +41,11 @@ static int f2fs_vm_page_mkwrite(struct vm_area_struct *vma, | |||
41 | 41 | ||
42 | sb_start_pagefault(inode->i_sb); | 42 | sb_start_pagefault(inode->i_sb); |
43 | 43 | ||
44 | /* force to convert with normal data indices */ | ||
45 | err = f2fs_convert_inline_data(inode, MAX_INLINE_DATA + 1, page); | ||
46 | if (err) | ||
47 | goto out; | ||
48 | |||
44 | /* block allocation */ | 49 | /* block allocation */ |
45 | f2fs_lock_op(sbi); | 50 | f2fs_lock_op(sbi); |
46 | set_new_dnode(&dn, inode, NULL, NULL, 0); | 51 | set_new_dnode(&dn, inode, NULL, NULL, 0); |
@@ -533,7 +538,7 @@ int f2fs_setattr(struct dentry *dentry, struct iattr *attr) | |||
533 | 538 | ||
534 | if ((attr->ia_valid & ATTR_SIZE) && | 539 | if ((attr->ia_valid & ATTR_SIZE) && |
535 | attr->ia_size != i_size_read(inode)) { | 540 | attr->ia_size != i_size_read(inode)) { |
536 | err = f2fs_convert_inline_data(inode, attr->ia_size); | 541 | err = f2fs_convert_inline_data(inode, attr->ia_size, NULL); |
537 | if (err) | 542 | if (err) |
538 | return err; | 543 | return err; |
539 | 544 | ||
@@ -622,7 +627,7 @@ static int punch_hole(struct inode *inode, loff_t offset, loff_t len) | |||
622 | loff_t off_start, off_end; | 627 | loff_t off_start, off_end; |
623 | int ret = 0; | 628 | int ret = 0; |
624 | 629 | ||
625 | ret = f2fs_convert_inline_data(inode, MAX_INLINE_DATA + 1); | 630 | ret = f2fs_convert_inline_data(inode, MAX_INLINE_DATA + 1, NULL); |
626 | if (ret) | 631 | if (ret) |
627 | return ret; | 632 | return ret; |
628 | 633 | ||
@@ -678,7 +683,7 @@ static int expand_inode_data(struct inode *inode, loff_t offset, | |||
678 | if (ret) | 683 | if (ret) |
679 | return ret; | 684 | return ret; |
680 | 685 | ||
681 | ret = f2fs_convert_inline_data(inode, offset + len); | 686 | ret = f2fs_convert_inline_data(inode, offset + len, NULL); |
682 | if (ret) | 687 | if (ret) |
683 | return ret; | 688 | return ret; |
684 | 689 | ||
diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c index 5beeccef9ae1..1ec512d0bed3 100644 --- a/fs/f2fs/inline.c +++ b/fs/f2fs/inline.c | |||
@@ -124,9 +124,10 @@ out: | |||
124 | return err; | 124 | return err; |
125 | } | 125 | } |
126 | 126 | ||
127 | int f2fs_convert_inline_data(struct inode *inode, pgoff_t to_size) | 127 | int f2fs_convert_inline_data(struct inode *inode, pgoff_t to_size, |
128 | struct page *page) | ||
128 | { | 129 | { |
129 | struct page *page; | 130 | struct page *new_page = page; |
130 | int err; | 131 | int err; |
131 | 132 | ||
132 | if (!f2fs_has_inline_data(inode)) | 133 | if (!f2fs_has_inline_data(inode)) |
@@ -134,17 +135,20 @@ int f2fs_convert_inline_data(struct inode *inode, pgoff_t to_size) | |||
134 | else if (to_size <= MAX_INLINE_DATA) | 135 | else if (to_size <= MAX_INLINE_DATA) |
135 | return 0; | 136 | return 0; |
136 | 137 | ||
137 | page = grab_cache_page(inode->i_mapping, 0); | 138 | if (!page || page->index != 0) { |
138 | if (!page) | 139 | new_page = grab_cache_page(inode->i_mapping, 0); |
139 | return -ENOMEM; | 140 | if (!new_page) |
141 | return -ENOMEM; | ||
142 | } | ||
140 | 143 | ||
141 | err = __f2fs_convert_inline_data(inode, page); | 144 | err = __f2fs_convert_inline_data(inode, new_page); |
142 | f2fs_put_page(page, 1); | 145 | if (!page || page->index != 0) |
146 | f2fs_put_page(new_page, 1); | ||
143 | return err; | 147 | return err; |
144 | } | 148 | } |
145 | 149 | ||
146 | int f2fs_write_inline_data(struct inode *inode, | 150 | int f2fs_write_inline_data(struct inode *inode, |
147 | struct page *page, unsigned size) | 151 | struct page *page, unsigned size) |
148 | { | 152 | { |
149 | void *src_addr, *dst_addr; | 153 | void *src_addr, *dst_addr; |
150 | struct page *ipage; | 154 | struct page *ipage; |