diff options
-rw-r--r-- | fs/btrfs/ioctl.c | 31 |
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 |