Btrfs: Per file/directory controls for COW and compression
Subsystems (2)
PATCH 2/2 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).
--- fs/btrfs/ctree.h | 1 + fs/btrfs/disk-io.c | 6 ++++++ fs/btrfs/inode.c | 32 ++++++++++++++++++++++++++++---- fs/btrfs/ioctl.c | 41 +++++++++++++++++++++++++++++++++++++---- 4 files changed, 72 insertions(+), 8 deletions(-)
fs/btrfs/ctree.h +1 -0
@@ -1274,6 +1274,7 @@ struct btrfs_root {#define BTRFS_INODE_NODUMP (1 << 8)#define BTRFS_INODE_NOATIME (1 << 9)#define BTRFS_INODE_DIRSYNC (1 << 10) +#define BTRFS_INODE_COMPRESS (1 << 11)/* some macros to generate set/get funcs for the struct fields. This * assumes there is a lefoo_to_cpu for every type, so lets make a simple
fs/btrfs/disk-io.c +6 -0
@@ -1762,6 +1762,12 @@ struct btrfs_root *open_ctree(struct super_block *sb,btrfs_check_super_valid (fs_info, sb->s_flags &MS_RDONLY ); +/* +* In the long term, we'll store the compression type in the super +* block, and it'll be used for per file compression control. +*/ + fs_info->compress_type =BTRFS_COMPRESS_ZLIB ; + ret =btrfs_parse_options (tree_root, options);if (ret) { err = ret;
fs/btrfs/inode.c +28 -4
@@ -381,7 +381,8 @@ again:*/ if (!(BTRFS_I (inode)->flags &BTRFS_INODE_NOCOMPRESS ) && (btrfs_test_opt (root,COMPRESS ) || - (BTRFS_I (inode)->force_compress))) { + (BTRFS_I (inode)->force_compress) || + (BTRFS_I (inode)->flags &BTRFS_INODE_COMPRESS ))) {WARN_ON (pages); pages =kzalloc (sizeof (struct page *) * nr_pages,GFP_NOFS );
@@ -1253,7 +1254,8 @@ static int run_delalloc_range(struct inode *inode, struct page *locked_page, ret =run_delalloc_nocow (inode, locked_page, start, end, page_started,0 , nr_written); else if (!btrfs_test_opt(root, COMPRESS) && - !(BTRFS_I(inode)->force_compress)) + !(BTRFS_I(inode)->force_compress) && + !(BTRFS_I(inode)->flags & BTRFS_INODE_COMPRESS)) ret =cow_file_range (inode, locked_page, start, end, page_started, nr_written,1 ); else
@@ -4581,8 +4583,6 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, location->offset =0 ;btrfs_set_key_type (location,BTRFS_INODE_ITEM_KEY ); -btrfs_inherit_iflags (inode, dir); -if ((mode &S_IFREG )) {if (btrfs_test_opt (root,NODATASUM ))BTRFS_I (inode)->flags |=BTRFS_INODE_NODATASUM ;
@@ -4590,6 +4590,8 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,BTRFS_I (inode)->flags |=BTRFS_INODE_NODATACOW ; } +btrfs_inherit_iflags (inode, dir); +insert_inode_hash (inode);inode_tree_add (inode);return inode;
@@ -6801,6 +6803,26 @@ static int btrfs_getattr(struct vfsmount *mnt,return 0 ; } +/* +* If a file is moved, it will inherit the cow and compression flags of the new +* directory. +*/ +static void fixup_inode_flags (struct inode *dir,struct inode *inode) +{ +struct btrfs_inode *b_dir =BTRFS_I (dir); +struct btrfs_inode *b_inode =BTRFS_I (inode); + +if (b_dir->flags &BTRFS_INODE_NODATACOW ) + b_inode->flags |=BTRFS_INODE_NODATACOW ; +else + b_inode->flags &= ~BTRFS_INODE_NODATACOW ; + +if (b_dir->flags &BTRFS_INODE_COMPRESS ) + b_inode->flags |=BTRFS_INODE_COMPRESS ; +else + b_inode->flags &= ~BTRFS_INODE_COMPRESS ; +} +static int btrfs_rename (struct inode *old_dir,struct dentry *old_dentry,struct inode *new_dir,struct dentry *new_dentry) {
@@ -6934,6 +6956,8 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry, } } +fixup_inode_flags (new_dir, old_inode); + ret =btrfs_add_link (trans, new_dir, old_inode, new_dentry->d_name.name, new_dentry->d_name.len,0 , index);
fs/btrfs/ioctl.c +37 -4
59 lines not on this page · raw message
Signature · 1 line
1.6.5.2