aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/ctree.h1
-rw-r--r--fs/btrfs/disk-io.c6
-rw-r--r--fs/btrfs/inode.c31
-rw-r--r--fs/btrfs/ioctl.c41
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 */
6876static 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
6869static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry, 6892static 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
141static 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
141static int btrfs_ioctl_setflags(struct file *file, void __user *arg) 159static 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));