diff options
-rw-r--r-- | fs/btrfs/ctree.h | 1 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 6 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 31 | ||||
-rw-r--r-- | fs/btrfs/ioctl.c | 41 |
4 files changed, 72 insertions, 7 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 9d0f59142afa..8302ecd4197f 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -1282,6 +1282,7 @@ struct btrfs_root { | |||
1282 | #define BTRFS_INODE_NODUMP (1 << 8) | 1282 | #define BTRFS_INODE_NODUMP (1 << 8) |
1283 | #define BTRFS_INODE_NOATIME (1 << 9) | 1283 | #define BTRFS_INODE_NOATIME (1 << 9) |
1284 | #define BTRFS_INODE_DIRSYNC (1 << 10) | 1284 | #define BTRFS_INODE_DIRSYNC (1 << 10) |
1285 | #define BTRFS_INODE_COMPRESS (1 << 11) | ||
1285 | 1286 | ||
1286 | /* some macros to generate set/get funcs for the struct fields. This | 1287 | /* some macros to generate set/get funcs for the struct fields. This |
1287 | * assumes there is a lefoo_to_cpu for every type, so lets make a simple | 1288 | * assumes there is a lefoo_to_cpu for every type, so lets make a simple |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 2bdb124333ab..125639ddaffe 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -1854,6 +1854,12 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1854 | 1854 | ||
1855 | btrfs_check_super_valid(fs_info, sb->s_flags & MS_RDONLY); | 1855 | btrfs_check_super_valid(fs_info, sb->s_flags & MS_RDONLY); |
1856 | 1856 | ||
1857 | /* | ||
1858 | * In the long term, we'll store the compression type in the super | ||
1859 | * block, and it'll be used for per file compression control. | ||
1860 | */ | ||
1861 | fs_info->compress_type = BTRFS_COMPRESS_ZLIB; | ||
1862 | |||
1857 | ret = btrfs_parse_options(tree_root, options); | 1863 | ret = btrfs_parse_options(tree_root, options); |
1858 | if (ret) { | 1864 | if (ret) { |
1859 | err = ret; | 1865 | err = ret; |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index eaa271484199..7a7a202b82ab 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -384,7 +384,8 @@ again: | |||
384 | */ | 384 | */ |
385 | if (!(BTRFS_I(inode)->flags & BTRFS_INODE_NOCOMPRESS) && | 385 | if (!(BTRFS_I(inode)->flags & BTRFS_INODE_NOCOMPRESS) && |
386 | (btrfs_test_opt(root, COMPRESS) || | 386 | (btrfs_test_opt(root, COMPRESS) || |
387 | (BTRFS_I(inode)->force_compress))) { | 387 | (BTRFS_I(inode)->force_compress) || |
388 | (BTRFS_I(inode)->flags & BTRFS_INODE_COMPRESS))) { | ||
388 | WARN_ON(pages); | 389 | WARN_ON(pages); |
389 | pages = kzalloc(sizeof(struct page *) * nr_pages, GFP_NOFS); | 390 | pages = kzalloc(sizeof(struct page *) * nr_pages, GFP_NOFS); |
390 | 391 | ||
@@ -1256,7 +1257,8 @@ static int run_delalloc_range(struct inode *inode, struct page *locked_page, | |||
1256 | ret = run_delalloc_nocow(inode, locked_page, start, end, | 1257 | ret = run_delalloc_nocow(inode, locked_page, start, end, |
1257 | page_started, 0, nr_written); | 1258 | page_started, 0, nr_written); |
1258 | else if (!btrfs_test_opt(root, COMPRESS) && | 1259 | else if (!btrfs_test_opt(root, COMPRESS) && |
1259 | !(BTRFS_I(inode)->force_compress)) | 1260 | !(BTRFS_I(inode)->force_compress) && |
1261 | !(BTRFS_I(inode)->flags & BTRFS_INODE_COMPRESS)) | ||
1260 | ret = cow_file_range(inode, locked_page, start, end, | 1262 | ret = cow_file_range(inode, locked_page, start, end, |
1261 | page_started, nr_written, 1); | 1263 | page_started, nr_written, 1); |
1262 | else | 1264 | else |
@@ -4584,7 +4586,8 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, | |||
4584 | if ((mode & S_IFREG)) { | 4586 | if ((mode & S_IFREG)) { |
4585 | if (btrfs_test_opt(root, NODATASUM)) | 4587 | if (btrfs_test_opt(root, NODATASUM)) |
4586 | BTRFS_I(inode)->flags |= BTRFS_INODE_NODATASUM; | 4588 | BTRFS_I(inode)->flags |= BTRFS_INODE_NODATASUM; |
4587 | if (btrfs_test_opt(root, NODATACOW)) | 4589 | if (btrfs_test_opt(root, NODATACOW) || |
4590 | (BTRFS_I(dir)->flags & BTRFS_INODE_NODATACOW)) | ||
4588 | BTRFS_I(inode)->flags |= BTRFS_INODE_NODATACOW; | 4591 | BTRFS_I(inode)->flags |= BTRFS_INODE_NODATACOW; |
4589 | } | 4592 | } |
4590 | 4593 | ||
@@ -6866,6 +6869,26 @@ static int btrfs_getattr(struct vfsmount *mnt, | |||
6866 | return 0; | 6869 | return 0; |
6867 | } | 6870 | } |
6868 | 6871 | ||
6872 | /* | ||
6873 | * If a file is moved, it will inherit the cow and compression flags of the new | ||
6874 | * directory. | ||
6875 | */ | ||
6876 | static void fixup_inode_flags(struct inode *dir, struct inode *inode) | ||
6877 | { | ||
6878 | struct btrfs_inode *b_dir = BTRFS_I(dir); | ||
6879 | struct btrfs_inode *b_inode = BTRFS_I(inode); | ||
6880 | |||
6881 | if (b_dir->flags & BTRFS_INODE_NODATACOW) | ||
6882 | b_inode->flags |= BTRFS_INODE_NODATACOW; | ||
6883 | else | ||
6884 | b_inode->flags &= ~BTRFS_INODE_NODATACOW; | ||
6885 | |||
6886 | if (b_dir->flags & BTRFS_INODE_COMPRESS) | ||
6887 | b_inode->flags |= BTRFS_INODE_COMPRESS; | ||
6888 | else | ||
6889 | b_inode->flags &= ~BTRFS_INODE_COMPRESS; | ||
6890 | } | ||
6891 | |||
6869 | static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry, | 6892 | static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry, |
6870 | struct inode *new_dir, struct dentry *new_dentry) | 6893 | struct inode *new_dir, struct dentry *new_dentry) |
6871 | { | 6894 | { |
@@ -6999,6 +7022,8 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
6999 | } | 7022 | } |
7000 | } | 7023 | } |
7001 | 7024 | ||
7025 | fixup_inode_flags(new_dir, old_inode); | ||
7026 | |||
7002 | ret = btrfs_add_link(trans, new_dir, old_inode, | 7027 | ret = btrfs_add_link(trans, new_dir, old_inode, |
7003 | new_dentry->d_name.name, | 7028 | new_dentry->d_name.name, |
7004 | new_dentry->d_name.len, 0, index); | 7029 | new_dentry->d_name.len, 0, index); |
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 88d3cb2eaf75..32c980ae0f1c 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -138,6 +138,24 @@ static int btrfs_ioctl_getflags(struct file *file, void __user *arg) | |||
138 | return 0; | 138 | return 0; |
139 | } | 139 | } |
140 | 140 | ||
141 | static int check_flags(unsigned int flags) | ||
142 | { | ||
143 | if (flags & ~(FS_IMMUTABLE_FL | FS_APPEND_FL | \ | ||
144 | FS_NOATIME_FL | FS_NODUMP_FL | \ | ||
145 | FS_SYNC_FL | FS_DIRSYNC_FL | \ | ||
146 | FS_NOCOMP_FL | FS_COMPR_FL | \ | ||
147 | FS_NOCOW_FL | FS_COW_FL)) | ||
148 | return -EOPNOTSUPP; | ||
149 | |||
150 | if ((flags & FS_NOCOMP_FL) && (flags & FS_COMPR_FL)) | ||
151 | return -EINVAL; | ||
152 | |||
153 | if ((flags & FS_NOCOW_FL) && (flags & FS_COW_FL)) | ||
154 | return -EINVAL; | ||
155 | |||
156 | return 0; | ||
157 | } | ||
158 | |||
141 | static int btrfs_ioctl_setflags(struct file *file, void __user *arg) | 159 | static int btrfs_ioctl_setflags(struct file *file, void __user *arg) |
142 | { | 160 | { |
143 | struct inode *inode = file->f_path.dentry->d_inode; | 161 | struct inode *inode = file->f_path.dentry->d_inode; |
@@ -153,10 +171,9 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg) | |||
153 | if (copy_from_user(&flags, arg, sizeof(flags))) | 171 | if (copy_from_user(&flags, arg, sizeof(flags))) |
154 | return -EFAULT; | 172 | return -EFAULT; |
155 | 173 | ||
156 | if (flags & ~(FS_IMMUTABLE_FL | FS_APPEND_FL | \ | 174 | ret = check_flags(flags); |
157 | FS_NOATIME_FL | FS_NODUMP_FL | \ | 175 | if (ret) |
158 | FS_SYNC_FL | FS_DIRSYNC_FL)) | 176 | return ret; |
159 | return -EOPNOTSUPP; | ||
160 | 177 | ||
161 | if (!is_owner_or_cap(inode)) | 178 | if (!is_owner_or_cap(inode)) |
162 | return -EACCES; | 179 | return -EACCES; |
@@ -201,6 +218,22 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg) | |||
201 | else | 218 | else |
202 | ip->flags &= ~BTRFS_INODE_DIRSYNC; | 219 | ip->flags &= ~BTRFS_INODE_DIRSYNC; |
203 | 220 | ||
221 | /* | ||
222 | * The COMPRESS flag can only be changed by users, while the NOCOMPRESS | ||
223 | * flag may be changed automatically if compression code won't make | ||
224 | * things smaller. | ||
225 | */ | ||
226 | if (flags & FS_NOCOMP_FL) { | ||
227 | ip->flags &= ~BTRFS_INODE_COMPRESS; | ||
228 | ip->flags |= BTRFS_INODE_NOCOMPRESS; | ||
229 | } else if (flags & FS_COMPR_FL) { | ||
230 | ip->flags |= BTRFS_INODE_COMPRESS; | ||
231 | ip->flags &= ~BTRFS_INODE_NOCOMPRESS; | ||
232 | } | ||
233 | if (flags & FS_NOCOW_FL) | ||
234 | ip->flags |= BTRFS_INODE_NODATACOW; | ||
235 | else if (flags & FS_COW_FL) | ||
236 | ip->flags &= ~BTRFS_INODE_NODATACOW; | ||
204 | 237 | ||
205 | trans = btrfs_join_transaction(root, 1); | 238 | trans = btrfs_join_transaction(root, 1); |
206 | BUG_ON(IS_ERR(trans)); | 239 | BUG_ON(IS_ERR(trans)); |