aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/ioctl.c')
-rw-r--r--fs/btrfs/ioctl.c31
1 files changed, 27 insertions, 4 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 38e3d6ab89d3..4d7f4bbf4c96 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -181,6 +181,7 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
181 int ret; 181 int ret;
182 u64 ip_oldflags; 182 u64 ip_oldflags;
183 unsigned int i_oldflags; 183 unsigned int i_oldflags;
184 umode_t mode;
184 185
185 if (btrfs_root_readonly(root)) 186 if (btrfs_root_readonly(root))
186 return -EROFS; 187 return -EROFS;
@@ -203,6 +204,7 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
203 204
204 ip_oldflags = ip->flags; 205 ip_oldflags = ip->flags;
205 i_oldflags = inode->i_flags; 206 i_oldflags = inode->i_flags;
207 mode = inode->i_mode;
206 208
207 flags = btrfs_mask_flags(inode->i_mode, flags); 209 flags = btrfs_mask_flags(inode->i_mode, flags);
208 oldflags = btrfs_flags_to_ioctl(ip->flags); 210 oldflags = btrfs_flags_to_ioctl(ip->flags);
@@ -237,10 +239,31 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
237 ip->flags |= BTRFS_INODE_DIRSYNC; 239 ip->flags |= BTRFS_INODE_DIRSYNC;
238 else 240 else
239 ip->flags &= ~BTRFS_INODE_DIRSYNC; 241 ip->flags &= ~BTRFS_INODE_DIRSYNC;
240 if (flags & FS_NOCOW_FL) 242 if (flags & FS_NOCOW_FL) {
241 ip->flags |= BTRFS_INODE_NODATACOW; 243 if (S_ISREG(mode)) {
242 else 244 /*
243 ip->flags &= ~BTRFS_INODE_NODATACOW; 245 * It's safe to turn csums off here, no extents exist.
246 * Otherwise we want the flag to reflect the real COW
247 * status of the file and will not set it.
248 */
249 if (inode->i_size == 0)
250 ip->flags |= BTRFS_INODE_NODATACOW
251 | BTRFS_INODE_NODATASUM;
252 } else {
253 ip->flags |= BTRFS_INODE_NODATACOW;
254 }
255 } else {
256 /*
257 * Revert back under same assuptions as above
258 */
259 if (S_ISREG(mode)) {
260 if (inode->i_size == 0)
261 ip->flags &= ~(BTRFS_INODE_NODATACOW
262 | BTRFS_INODE_NODATASUM);
263 } else {
264 ip->flags &= ~BTRFS_INODE_NODATACOW;
265 }
266 }
244 267
245 /* 268 /*
246 * The COMPRESS flag can only be changed by users, while the NOCOMPRESS 269 * The COMPRESS flag can only be changed by users, while the NOCOMPRESS