aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorLiu Bo <liubo2009@cn.fujitsu.com>2011-03-22 06:12:20 -0400
committerroot <Chris Mason chris.mason@oracle.com>2011-03-28 05:37:41 -0400
commit75e7cb7fe0c391561bd3af36515be3f3c64a04c6 (patch)
tree3738481e2db10b2904a4434e4ca42d326da02be7 /fs/btrfs
parent32471f6e1983922473573da62cbee58699574aa4 (diff)
Btrfs: Per file/directory controls for COW and compression
Data compression and data cow are controlled across the entire FS by mount options right now. ioctls are needed to set this on a per file or per directory basis. This has been proposed previously, but VFS developers wanted us to use generic ioctls rather than btrfs-specific ones. According to Chris's comment, there should be just one true compression method(probably LZO) stored in the super. However, before this, we would wait for that one method is stable enough to be adopted into the super. So I list it as a long term goal, and just store it in ram today. After applying this patch, we can use the generic "FS_IOC_SETFLAGS" ioctl to control file and directory's datacow and compression attribute. NOTE: - The compression type is selected by such rules: If we mount btrfs with compress options, ie, zlib/lzo, the type is it. Otherwise, we'll use the default compress type (zlib today). v1->v2: - rebase to the latest btrfs. v2->v3: - fix a problem, i.e. when a file is set NOCOW via mount option, then this NOCOW will be screwed by inheritance from parent directory. Signed-off-by: Liu Bo <liubo2009@cn.fujitsu.com> Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs')
-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));