|
@@ -796,22 +796,26 @@ int f2fs_setattr(struct dentry *dentry, struct iattr *attr)
|
|
|
}
|
|
|
|
|
|
if (attr->ia_valid & ATTR_SIZE) {
|
|
|
- if (attr->ia_size <= i_size_read(inode)) {
|
|
|
- down_write(&F2FS_I(inode)->i_mmap_sem);
|
|
|
- truncate_setsize(inode, attr->ia_size);
|
|
|
+ bool to_smaller = (attr->ia_size <= i_size_read(inode));
|
|
|
+
|
|
|
+ down_write(&F2FS_I(inode)->i_mmap_sem);
|
|
|
+ down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
|
|
|
+
|
|
|
+ truncate_setsize(inode, attr->ia_size);
|
|
|
+
|
|
|
+ if (to_smaller)
|
|
|
err = f2fs_truncate(inode);
|
|
|
- up_write(&F2FS_I(inode)->i_mmap_sem);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
- } else {
|
|
|
- /*
|
|
|
- * do not trim all blocks after i_size if target size is
|
|
|
- * larger than i_size.
|
|
|
- */
|
|
|
- down_write(&F2FS_I(inode)->i_mmap_sem);
|
|
|
- truncate_setsize(inode, attr->ia_size);
|
|
|
- up_write(&F2FS_I(inode)->i_mmap_sem);
|
|
|
+ /*
|
|
|
+ * do not trim all blocks after i_size if target size is
|
|
|
+ * larger than i_size.
|
|
|
+ */
|
|
|
+ up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
|
|
|
+ up_write(&F2FS_I(inode)->i_mmap_sem);
|
|
|
|
|
|
+ if (err)
|
|
|
+ return err;
|
|
|
+
|
|
|
+ if (!to_smaller) {
|
|
|
/* should convert inline inode here */
|
|
|
if (!f2fs_may_inline_data(inode)) {
|
|
|
err = f2fs_convert_inline_inode(inode);
|
|
@@ -958,13 +962,18 @@ static int punch_hole(struct inode *inode, loff_t offset, loff_t len)
|
|
|
|
|
|
blk_start = (loff_t)pg_start << PAGE_SHIFT;
|
|
|
blk_end = (loff_t)pg_end << PAGE_SHIFT;
|
|
|
+
|
|
|
down_write(&F2FS_I(inode)->i_mmap_sem);
|
|
|
+ down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
|
|
|
+
|
|
|
truncate_inode_pages_range(mapping, blk_start,
|
|
|
blk_end - 1);
|
|
|
|
|
|
f2fs_lock_op(sbi);
|
|
|
ret = f2fs_truncate_hole(inode, pg_start, pg_end);
|
|
|
f2fs_unlock_op(sbi);
|
|
|
+
|
|
|
+ up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
|
|
|
up_write(&F2FS_I(inode)->i_mmap_sem);
|
|
|
}
|
|
|
}
|