diff options
Diffstat (limited to 'fs/ubifs')
| -rw-r--r-- | fs/ubifs/file.c | 17 | ||||
| -rw-r--r-- | fs/ubifs/ubifs.h | 4 |
2 files changed, 12 insertions, 9 deletions
diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c index 5692cf72b80..12f445cee9f 100644 --- a/fs/ubifs/file.c +++ b/fs/ubifs/file.c | |||
| @@ -967,12 +967,15 @@ static int do_writepage(struct page *page, int len) | |||
| 967 | * the page locked, and it locks @ui_mutex. However, write-back does take inode | 967 | * the page locked, and it locks @ui_mutex. However, write-back does take inode |
| 968 | * @i_mutex, which means other VFS operations may be run on this inode at the | 968 | * @i_mutex, which means other VFS operations may be run on this inode at the |
| 969 | * same time. And the problematic one is truncation to smaller size, from where | 969 | * same time. And the problematic one is truncation to smaller size, from where |
| 970 | * we have to call 'vmtruncate()', which first changes @inode->i_size, then | 970 | * we have to call 'simple_setsize()', which first changes @inode->i_size, then |
| 971 | * drops the truncated pages. And while dropping the pages, it takes the page | 971 | * drops the truncated pages. And while dropping the pages, it takes the page |
| 972 | * lock. This means that 'do_truncation()' cannot call 'vmtruncate()' with | 972 | * lock. This means that 'do_truncation()' cannot call 'simple_setsize()' with |
| 973 | * @ui_mutex locked, because it would deadlock with 'ubifs_writepage()'. This | 973 | * @ui_mutex locked, because it would deadlock with 'ubifs_writepage()'. This |
| 974 | * means that @inode->i_size is changed while @ui_mutex is unlocked. | 974 | * means that @inode->i_size is changed while @ui_mutex is unlocked. |
| 975 | * | 975 | * |
| 976 | * XXX: with the new truncate the above is not true anymore, the simple_setsize | ||
| 977 | * calls can be replaced with the individual components. | ||
| 978 | * | ||
| 976 | * But in 'ubifs_writepage()' we have to guarantee that we do not write beyond | 979 | * But in 'ubifs_writepage()' we have to guarantee that we do not write beyond |
| 977 | * inode size. How do we do this if @inode->i_size may became smaller while we | 980 | * inode size. How do we do this if @inode->i_size may became smaller while we |
| 978 | * are in the middle of 'ubifs_writepage()'? The UBIFS solution is the | 981 | * are in the middle of 'ubifs_writepage()'? The UBIFS solution is the |
| @@ -1125,7 +1128,7 @@ static int do_truncation(struct ubifs_info *c, struct inode *inode, | |||
| 1125 | budgeted = 0; | 1128 | budgeted = 0; |
| 1126 | } | 1129 | } |
| 1127 | 1130 | ||
| 1128 | err = vmtruncate(inode, new_size); | 1131 | err = simple_setsize(inode, new_size); |
| 1129 | if (err) | 1132 | if (err) |
| 1130 | goto out_budg; | 1133 | goto out_budg; |
| 1131 | 1134 | ||
| @@ -1214,7 +1217,7 @@ static int do_setattr(struct ubifs_info *c, struct inode *inode, | |||
| 1214 | 1217 | ||
| 1215 | if (attr->ia_valid & ATTR_SIZE) { | 1218 | if (attr->ia_valid & ATTR_SIZE) { |
| 1216 | dbg_gen("size %lld -> %lld", inode->i_size, new_size); | 1219 | dbg_gen("size %lld -> %lld", inode->i_size, new_size); |
| 1217 | err = vmtruncate(inode, new_size); | 1220 | err = simple_setsize(inode, new_size); |
| 1218 | if (err) | 1221 | if (err) |
| 1219 | goto out; | 1222 | goto out; |
| 1220 | } | 1223 | } |
| @@ -1223,7 +1226,7 @@ static int do_setattr(struct ubifs_info *c, struct inode *inode, | |||
| 1223 | if (attr->ia_valid & ATTR_SIZE) { | 1226 | if (attr->ia_valid & ATTR_SIZE) { |
| 1224 | /* Truncation changes inode [mc]time */ | 1227 | /* Truncation changes inode [mc]time */ |
| 1225 | inode->i_mtime = inode->i_ctime = ubifs_current_time(inode); | 1228 | inode->i_mtime = inode->i_ctime = ubifs_current_time(inode); |
| 1226 | /* 'vmtruncate()' changed @i_size, update @ui_size */ | 1229 | /* 'simple_setsize()' changed @i_size, update @ui_size */ |
| 1227 | ui->ui_size = inode->i_size; | 1230 | ui->ui_size = inode->i_size; |
| 1228 | } | 1231 | } |
| 1229 | 1232 | ||
| @@ -1304,9 +1307,9 @@ static void *ubifs_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
| 1304 | return NULL; | 1307 | return NULL; |
| 1305 | } | 1308 | } |
| 1306 | 1309 | ||
| 1307 | int ubifs_fsync(struct file *file, struct dentry *dentry, int datasync) | 1310 | int ubifs_fsync(struct file *file, int datasync) |
| 1308 | { | 1311 | { |
| 1309 | struct inode *inode = dentry->d_inode; | 1312 | struct inode *inode = file->f_mapping->host; |
| 1310 | struct ubifs_info *c = inode->i_sb->s_fs_info; | 1313 | struct ubifs_info *c = inode->i_sb->s_fs_info; |
| 1311 | int err; | 1314 | int err; |
| 1312 | 1315 | ||
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index bd2542dad01..2eef553d50c 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h | |||
| @@ -379,7 +379,7 @@ struct ubifs_gced_idx_leb { | |||
| 379 | * The @ui_size is a "shadow" variable for @inode->i_size and UBIFS uses | 379 | * The @ui_size is a "shadow" variable for @inode->i_size and UBIFS uses |
| 380 | * @ui_size instead of @inode->i_size. The reason for this is that UBIFS cannot | 380 | * @ui_size instead of @inode->i_size. The reason for this is that UBIFS cannot |
| 381 | * make sure @inode->i_size is always changed under @ui_mutex, because it | 381 | * make sure @inode->i_size is always changed under @ui_mutex, because it |
| 382 | * cannot call 'vmtruncate()' with @ui_mutex locked, because it would deadlock | 382 | * cannot call 'simple_setsize()' with @ui_mutex locked, because it would deadlock |
| 383 | * with 'ubifs_writepage()' (see file.c). All the other inode fields are | 383 | * with 'ubifs_writepage()' (see file.c). All the other inode fields are |
| 384 | * changed under @ui_mutex, so they do not need "shadow" fields. Note, one | 384 | * changed under @ui_mutex, so they do not need "shadow" fields. Note, one |
| 385 | * could consider to rework locking and base it on "shadow" fields. | 385 | * could consider to rework locking and base it on "shadow" fields. |
| @@ -1678,7 +1678,7 @@ const struct ubifs_lprops *ubifs_fast_find_frdi_idx(struct ubifs_info *c); | |||
| 1678 | int ubifs_calc_dark(const struct ubifs_info *c, int spc); | 1678 | int ubifs_calc_dark(const struct ubifs_info *c, int spc); |
| 1679 | 1679 | ||
| 1680 | /* file.c */ | 1680 | /* file.c */ |
| 1681 | int ubifs_fsync(struct file *file, struct dentry *dentry, int datasync); | 1681 | int ubifs_fsync(struct file *file, int datasync); |
| 1682 | int ubifs_setattr(struct dentry *dentry, struct iattr *attr); | 1682 | int ubifs_setattr(struct dentry *dentry, struct iattr *attr); |
| 1683 | 1683 | ||
| 1684 | /* dir.c */ | 1684 | /* dir.c */ |
