diff options
Diffstat (limited to 'fs/f2fs/file.c')
-rw-r--r-- | fs/f2fs/file.c | 58 |
1 files changed, 44 insertions, 14 deletions
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 1cae864f8dfc..d2d2b7dbdcc1 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c | |||
@@ -63,9 +63,10 @@ static int f2fs_vm_page_mkwrite(struct vm_area_struct *vma, | |||
63 | f2fs_put_dnode(&dn); | 63 | f2fs_put_dnode(&dn); |
64 | mutex_unlock_op(sbi, ilock); | 64 | mutex_unlock_op(sbi, ilock); |
65 | 65 | ||
66 | file_update_time(vma->vm_file); | ||
66 | lock_page(page); | 67 | lock_page(page); |
67 | if (page->mapping != inode->i_mapping || | 68 | if (page->mapping != inode->i_mapping || |
68 | page_offset(page) >= i_size_read(inode) || | 69 | page_offset(page) > i_size_read(inode) || |
69 | !PageUptodate(page)) { | 70 | !PageUptodate(page)) { |
70 | unlock_page(page); | 71 | unlock_page(page); |
71 | err = -EFAULT; | 72 | err = -EFAULT; |
@@ -76,10 +77,7 @@ static int f2fs_vm_page_mkwrite(struct vm_area_struct *vma, | |||
76 | * check to see if the page is mapped already (no holes) | 77 | * check to see if the page is mapped already (no holes) |
77 | */ | 78 | */ |
78 | if (PageMappedToDisk(page)) | 79 | if (PageMappedToDisk(page)) |
79 | goto out; | 80 | goto mapped; |
80 | |||
81 | /* fill the page */ | ||
82 | wait_on_page_writeback(page); | ||
83 | 81 | ||
84 | /* page is wholly or partially inside EOF */ | 82 | /* page is wholly or partially inside EOF */ |
85 | if (((page->index + 1) << PAGE_CACHE_SHIFT) > i_size_read(inode)) { | 83 | if (((page->index + 1) << PAGE_CACHE_SHIFT) > i_size_read(inode)) { |
@@ -90,7 +88,9 @@ static int f2fs_vm_page_mkwrite(struct vm_area_struct *vma, | |||
90 | set_page_dirty(page); | 88 | set_page_dirty(page); |
91 | SetPageUptodate(page); | 89 | SetPageUptodate(page); |
92 | 90 | ||
93 | file_update_time(vma->vm_file); | 91 | mapped: |
92 | /* fill the page */ | ||
93 | wait_on_page_writeback(page); | ||
94 | out: | 94 | out: |
95 | sb_end_pagefault(inode->i_sb); | 95 | sb_end_pagefault(inode->i_sb); |
96 | return block_page_mkwrite_return(err); | 96 | return block_page_mkwrite_return(err); |
@@ -102,6 +102,24 @@ static const struct vm_operations_struct f2fs_file_vm_ops = { | |||
102 | .remap_pages = generic_file_remap_pages, | 102 | .remap_pages = generic_file_remap_pages, |
103 | }; | 103 | }; |
104 | 104 | ||
105 | static int get_parent_ino(struct inode *inode, nid_t *pino) | ||
106 | { | ||
107 | struct dentry *dentry; | ||
108 | |||
109 | inode = igrab(inode); | ||
110 | dentry = d_find_any_alias(inode); | ||
111 | iput(inode); | ||
112 | if (!dentry) | ||
113 | return 0; | ||
114 | |||
115 | inode = igrab(dentry->d_parent->d_inode); | ||
116 | dput(dentry); | ||
117 | |||
118 | *pino = inode->i_ino; | ||
119 | iput(inode); | ||
120 | return 1; | ||
121 | } | ||
122 | |||
105 | int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) | 123 | int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) |
106 | { | 124 | { |
107 | struct inode *inode = file->f_mapping->host; | 125 | struct inode *inode = file->f_mapping->host; |
@@ -114,7 +132,7 @@ int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) | |||
114 | .for_reclaim = 0, | 132 | .for_reclaim = 0, |
115 | }; | 133 | }; |
116 | 134 | ||
117 | if (inode->i_sb->s_flags & MS_RDONLY) | 135 | if (f2fs_readonly(inode->i_sb)) |
118 | return 0; | 136 | return 0; |
119 | 137 | ||
120 | trace_f2fs_sync_file_enter(inode); | 138 | trace_f2fs_sync_file_enter(inode); |
@@ -134,7 +152,7 @@ int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) | |||
134 | 152 | ||
135 | if (!S_ISREG(inode->i_mode) || inode->i_nlink != 1) | 153 | if (!S_ISREG(inode->i_mode) || inode->i_nlink != 1) |
136 | need_cp = true; | 154 | need_cp = true; |
137 | else if (is_cp_file(inode)) | 155 | else if (file_wrong_pino(inode)) |
138 | need_cp = true; | 156 | need_cp = true; |
139 | else if (!space_for_roll_forward(sbi)) | 157 | else if (!space_for_roll_forward(sbi)) |
140 | need_cp = true; | 158 | need_cp = true; |
@@ -142,11 +160,23 @@ int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) | |||
142 | need_cp = true; | 160 | need_cp = true; |
143 | 161 | ||
144 | if (need_cp) { | 162 | if (need_cp) { |
163 | nid_t pino; | ||
164 | |||
145 | /* all the dirty node pages should be flushed for POR */ | 165 | /* all the dirty node pages should be flushed for POR */ |
146 | ret = f2fs_sync_fs(inode->i_sb, 1); | 166 | ret = f2fs_sync_fs(inode->i_sb, 1); |
167 | if (file_wrong_pino(inode) && inode->i_nlink == 1 && | ||
168 | get_parent_ino(inode, &pino)) { | ||
169 | F2FS_I(inode)->i_pino = pino; | ||
170 | file_got_pino(inode); | ||
171 | mark_inode_dirty_sync(inode); | ||
172 | ret = f2fs_write_inode(inode, NULL); | ||
173 | if (ret) | ||
174 | goto out; | ||
175 | } | ||
147 | } else { | 176 | } else { |
148 | /* if there is no written node page, write its inode page */ | 177 | /* if there is no written node page, write its inode page */ |
149 | while (!sync_node_pages(sbi, inode->i_ino, &wbc)) { | 178 | while (!sync_node_pages(sbi, inode->i_ino, &wbc)) { |
179 | mark_inode_dirty_sync(inode); | ||
150 | ret = f2fs_write_inode(inode, NULL); | 180 | ret = f2fs_write_inode(inode, NULL); |
151 | if (ret) | 181 | if (ret) |
152 | goto out; | 182 | goto out; |
@@ -168,7 +198,7 @@ static int f2fs_file_mmap(struct file *file, struct vm_area_struct *vma) | |||
168 | return 0; | 198 | return 0; |
169 | } | 199 | } |
170 | 200 | ||
171 | static int truncate_data_blocks_range(struct dnode_of_data *dn, int count) | 201 | int truncate_data_blocks_range(struct dnode_of_data *dn, int count) |
172 | { | 202 | { |
173 | int nr_free = 0, ofs = dn->ofs_in_node; | 203 | int nr_free = 0, ofs = dn->ofs_in_node; |
174 | struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb); | 204 | struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb); |
@@ -185,10 +215,10 @@ static int truncate_data_blocks_range(struct dnode_of_data *dn, int count) | |||
185 | 215 | ||
186 | update_extent_cache(NULL_ADDR, dn); | 216 | update_extent_cache(NULL_ADDR, dn); |
187 | invalidate_blocks(sbi, blkaddr); | 217 | invalidate_blocks(sbi, blkaddr); |
188 | dec_valid_block_count(sbi, dn->inode, 1); | ||
189 | nr_free++; | 218 | nr_free++; |
190 | } | 219 | } |
191 | if (nr_free) { | 220 | if (nr_free) { |
221 | dec_valid_block_count(sbi, dn->inode, nr_free); | ||
192 | set_page_dirty(dn->node_page); | 222 | set_page_dirty(dn->node_page); |
193 | sync_inode_page(dn); | 223 | sync_inode_page(dn); |
194 | } | 224 | } |
@@ -291,7 +321,7 @@ void f2fs_truncate(struct inode *inode) | |||
291 | } | 321 | } |
292 | } | 322 | } |
293 | 323 | ||
294 | static int f2fs_getattr(struct vfsmount *mnt, | 324 | int f2fs_getattr(struct vfsmount *mnt, |
295 | struct dentry *dentry, struct kstat *stat) | 325 | struct dentry *dentry, struct kstat *stat) |
296 | { | 326 | { |
297 | struct inode *inode = dentry->d_inode; | 327 | struct inode *inode = dentry->d_inode; |
@@ -387,7 +417,7 @@ static void fill_zero(struct inode *inode, pgoff_t index, | |||
387 | f2fs_balance_fs(sbi); | 417 | f2fs_balance_fs(sbi); |
388 | 418 | ||
389 | ilock = mutex_lock_op(sbi); | 419 | ilock = mutex_lock_op(sbi); |
390 | page = get_new_data_page(inode, index, false); | 420 | page = get_new_data_page(inode, NULL, index, false); |
391 | mutex_unlock_op(sbi, ilock); | 421 | mutex_unlock_op(sbi, ilock); |
392 | 422 | ||
393 | if (!IS_ERR(page)) { | 423 | if (!IS_ERR(page)) { |
@@ -575,10 +605,10 @@ long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
575 | int ret; | 605 | int ret; |
576 | 606 | ||
577 | switch (cmd) { | 607 | switch (cmd) { |
578 | case FS_IOC_GETFLAGS: | 608 | case F2FS_IOC_GETFLAGS: |
579 | flags = fi->i_flags & FS_FL_USER_VISIBLE; | 609 | flags = fi->i_flags & FS_FL_USER_VISIBLE; |
580 | return put_user(flags, (int __user *) arg); | 610 | return put_user(flags, (int __user *) arg); |
581 | case FS_IOC_SETFLAGS: | 611 | case F2FS_IOC_SETFLAGS: |
582 | { | 612 | { |
583 | unsigned int oldflags; | 613 | unsigned int oldflags; |
584 | 614 | ||