Skip to contentSkip to conversation

Btrfs: Per file/directory controls for COW and compression

PATCH In review liubo 4 participants 7 messages Mar 21, 2011 – Apr 6, 2011 Btrfs file system

lore
Share & tools
lore

liubo

author
#0 lore raw

PATCH v2 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).

v1->v2:
Rebase the patch with the latest btrfs.

---
 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
index 8b4b9d1..b77d1a5 100644
@@ -1283,6 +1283,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
index 3e1ea3e..a894c12 100644
@@ -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
index db67821..e687bb9 100644
@@ -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;
@@ -6803,6 +6805,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)
 {
@@ -6936,6 +6958,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
#1 lore raw
Quoted 10 lines · liubo
fs/btrfs/inode.c +0 -2
@@ -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;

fs/btrfs/inode.c static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, · line 4593

Quoted 4 lines
fs/btrfs/inode.c +1 -0
@@ -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);

The problem is that btrfs_inherit_iflags() overwrites BTRFS_I(inode)->flags with the parent's flags, so you lose BTRFS_INODE_NODATA{SUM|COW}.

Johann

author
#2 lore raw
Quoted 14 lines · Johann Lombardi
Quoted 13 lines · liubo
fs/btrfs/inode.c +0 -2
@@ -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;
 	}
 
Quoted 4 lines

fs/btrfs/inode.c static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, · line 4593

Quoted 1 line
fs/btrfs/inode.c +1 -0
+	btrfs_inherit_iflags(inode, dir);

The problem is that btrfs_inherit_iflags() overwrites BTRFS_I(inode)->flags with the parent's flags, so you lose BTRFS_INODE_NODATA{SUM|COW}.

Thanks for pointing this, will fix it.

thanks,
liubo

Quoted 2 lines

Johann

author
#3 lore raw

PATCH v3 2/2 Btrfs: Per file/directory controls for COW and compression

In reply to Johann Lombardi

From: Liu Bo <[email protected]>

Subject: [PATCH 2/2 v3] 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.

---
 fs/btrfs/ctree.h   |    1 +
 fs/btrfs/disk-io.c |    6 ++++++
 fs/btrfs/inode.c   |   31 ++++++++++++++++++++++++++++---
 fs/btrfs/ioctl.c   |   41 +++++++++++++++++++++++++++++++++++++----
 4 files changed, 72 insertions(+), 7 deletions(-)
fs/btrfs/ctree.h +1 -0
index 8b4b9d1..b77d1a5 100644
@@ -1283,6 +1283,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
index 3e1ea3e..a894c12 100644
@@ -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 -3
index db67821..2d9910d 100644
@@ -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
@@ -4586,7 +4588,8 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
 	if ((mode & S_IFREG)) {
 		if (btrfs_test_opt(root, NODATASUM))
 			BTRFS_I(inode)->flags |= BTRFS_INODE_NODATASUM;
-		if (btrfs_test_opt(root, NODATACOW))
+		if (btrfs_test_opt(root, NODATACOW) ||
+		    (BTRFS_I(dir)->flags & BTRFS_INODE_NODATACOW))
 			BTRFS_I(inode)->flags |= BTRFS_INODE_NODATACOW;
 	}
 
@@ -6803,6 +6806,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)
 {
@@ -6936,6 +6959,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
#4 lore raw
In reply to liubo

Hello,
I would like to ask about the status of this feature/patch, is it=20 accepted into btrfs code, and how can I use it?

I am interested in enabling compression in a specific=20 folder(force-compress would be ideal) of a large btrfs volume, and=20 disabling it for the rest.

Quoted 1 line · liubo

Data compression and data cow are controlled across the entire FS by =

mount

Quoted 1 line

options right now. ioctls are needed to set this on a per file or pe=

r

Quoted 1 line

directory basis. This has been proposed previously, but VFS develope=

rs

Quoted 3 lines

wanted us to use generic ioctls rather than btrfs-specific ones.

According to chris's comment, there should be just one true compressi=

on

Quoted 1 line

method(probably LZO) stored in the super. However, before this, we w=

ould

Quoted 1 line

wait for that one method is stable enough to be adopted into the supe=

r.

Quoted 3 lines

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" i=

octl to

Quoted 5 lines

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 i=

s it.

Quoted 18 lines

Otherwise, we'll use the default compress type (zlib today).

v1->v2:
Rebase the patch with the latest btrfs.

---
  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 +0 -0
index 8b4b9d1..b77d1a5 100644

fs/btrfs/ctree.h struct btrfs_root { · line 1288

Quoted 6 lines
fs/btrfs/ctree.h +1 -0
@@ -1283,6 +1283,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.  Th=

is

fs/btrfs/ctree.h struct btrfs_root { · line 1289

Quoted 1 line
fs/btrfs/ctree.h +0 -0
   * assumes there is a lefoo_to_cpu for every type, so lets make a s=

imple

fs/btrfs/disk-io.c struct btrfs_root *open_ctree(struct super_blo=

Quoted 5 lines
fs/btrfs/disk-io.c +0 -0
index 3e1ea3e..a894c12 100644
@@ -1762,6 +1762,12 @@ struct btrfs_root *open_ctree(struct super_blo=

ck *sb,

fs/btrfs/inode.c static int run_delalloc_range(struct inode *ino=

Quoted 27 lines
fs/btrfs/disk-io.c +6 -0
  	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 =3D BTRFS_COMPRESS_ZLIB;
+
  	ret =3D btrfs_parse_options(tree_root, options);
  	if (ret) {
  		err =3D ret;
fs/btrfs/inode.c +2 -1
index db67821..e687bb9 100644
@@ -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 =3D kzalloc(sizeof(struct page *) * nr_pages, GFP_NOFS);
 
@@ -1253,7 +1254,8 @@ static int run_delalloc_range(struct inode *ino=

de, struct page *locked_page,

fs/btrfs/inode.c static struct inode *btrfs_new_inode(struct btr=

Quoted 10 lines
fs/btrfs/inode.c +2 -1
  		ret =3D 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 =3D 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 btr=

fs_trans_handle *trans,

fs/btrfs/inode.c static struct inode *btrfs_new_inode(struct btr=

Quoted 9 lines
fs/btrfs/inode.c +0 -2
  	location->offset =3D 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 |=3D BTRFS_INODE_NODATASUM;
@@ -4590,6 +4590,8 @@ static struct inode *btrfs_new_inode(struct btr=

fs_trans_handle *trans,

Quoted 9 lines
fs/btrfs/inode.c +2 -0
  			BTRFS_I(inode)->flags |=3D BTRFS_INODE_NODATACOW;
  	}
 
+	btrfs_inherit_iflags(inode, dir);
+
  	insert_inode_hash(inode);
  	inode_tree_add(inode);
  	return inode;

fs/btrfs/inode.c static int btrfs_getattr(struct vfsmount *mnt, · line 6809

Quoted 5 lines
fs/btrfs/inode.c +2 -0
@@ -6803,6 +6805,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

fs/btrfs/inode.c static int btrfs_getattr(struct vfsmount *mnt,

Quoted 3 lines
fs/btrfs/inode.c +3 -0
+ * directory.
+ */
+static void fixup_inode_flags(struct inode *dir, struct inode *inode=

)

Quoted 6 lines
fs/btrfs/inode.c +6 -0
+{
+	struct btrfs_inode *b_dir =3D BTRFS_I(dir);
+	struct btrfs_inode *b_inode =3D BTRFS_I(inode);
+
+	if (b_dir->flags&  BTRFS_INODE_NODATACOW)
+		b_inode->flags |=3D BTRFS_INODE_NODATACOW;

fs/btrfs/inode.c static int btrfs_getattr(struct vfsmount *mnt, · line 6828

Quoted 10 lines
fs/btrfs/inode.c +9 -0
+	else
+		b_inode->flags&=3D ~BTRFS_INODE_NODATACOW;
+
+	if (b_dir->flags&  BTRFS_INODE_COMPRESS)
+		b_inode->flags |=3D BTRFS_INODE_COMPRESS;
+	else
+		b_inode->flags&=3D ~BTRFS_INODE_COMPRESS;
+}
+
  static int btrfs_rename(struct inode *old_dir, struct dentry *old_d=

entry,

fs/btrfs/inode.c static int btrfs_rename(struct inode *old_dir, =

Quoted 3 lines
fs/btrfs/inode.c +0 -0
  			   struct inode *new_dir, struct dentry *new_dentry)
  {
@@ -6936,6 +6958,8 @@ static int btrfs_rename(struct inode *old_dir, =

struct dentry *old_dentry,

fs/btrfs/ioctl.c static int btrfs_ioctl_getflags(struct file *fil=

Quoted 13 lines
fs/btrfs/inode.c +2 -0
  		}
  	}
 
+	fixup_inode_flags(new_dir, old_inode);
+
  	ret =3D btrfs_add_link(trans, new_dir, old_inode,
  			     new_dentry->d_name.name,
  			     new_dentry->d_name.len, 0, index);
fs/btrfs/ioctl.c +0 -0
index 5fdb2ab..93e7f6c 100644
@@ -138,6 +138,24 @@ static int btrfs_ioctl_getflags(struct file *fil=

e, void __user *arg)

Quoted 12 lines
fs/btrfs/ioctl.c +9 -0
  	return 0;
  }
 
+static int check_flags(unsigned int flags)
+{
+	if (flags&  ~(FS_IMMUTABLE_FL | FS_APPEND_FL | \
+		      FS_NOATIME_FL | FS_NODUMP_FL | \
+		      FS_SYNC_FL | FS_DIRSYNC_FL | \
+		      FS_NOCOMP_FL | FS_COMPR_FL | \
+		      FS_NOCOW_FL | FS_COW_FL))
+		return -EOPNOTSUPP;
+

fs/btrfs/ioctl.c static int btrfs_ioctl_getflags(struct file *file, void __user *arg)

Quoted 10 lines
fs/btrfs/ioctl.c +9 -0
+	if ((flags&  FS_NOCOMP_FL)&&  (flags&  FS_COMPR_FL))
+		return -EINVAL;
+
+	if ((flags&  FS_NOCOW_FL)&&  (flags&  FS_COW_FL))
+		return -EINVAL;
+
+	return 0;
+}
+
  static int btrfs_ioctl_setflags(struct file *file, void __user *arg=

)

fs/btrfs/ioctl.c static int btrfs_ioctl_setflags(struct file *fil=

Quoted 3 lines
fs/btrfs/ioctl.c +0 -0
  {
  	struct inode *inode =3D file->f_path.dentry->d_inode;
@@ -153,10 +171,9 @@ static int btrfs_ioctl_setflags(struct file *fil=

e, void __user *arg)

fs/btrfs/ioctl.c static int btrfs_ioctl_setflags(struct file *fil=

Quoted 14 lines
fs/btrfs/ioctl.c +3 -4
  	if (copy_from_user(&flags, arg, sizeof(flags)))
  		return -EFAULT;
 
-	if (flags&  ~(FS_IMMUTABLE_FL | FS_APPEND_FL | \
-		      FS_NOATIME_FL | FS_NODUMP_FL | \
-		      FS_SYNC_FL | FS_DIRSYNC_FL))
-		return -EOPNOTSUPP;
+	ret =3D check_flags(flags);
+	if (ret)
+		return ret;
 
  	if (!is_owner_or_cap(inode))
  		return -EACCES;
@@ -201,6 +218,22 @@ static int btrfs_ioctl_setflags(struct file *fil=

e, void __user *arg)

fs/btrfs/ioctl.c static int btrfs_ioctl_setflags(struct file *file, void __user *arg)

Quoted 5 lines
fs/btrfs/ioctl.c +2 -0
  	else
  		ip->flags&=3D ~BTRFS_INODE_DIRSYNC;
 
+	/*
+	 * The COMPRESS flag can only be changed by users, while the NOCOMP=

RESS

Quoted 7 lines
fs/btrfs/ioctl.c +7 -0
+	 * flag may be changed automatically if compression code won't make
+	 * things smaller.
+	 */
+	if (flags&  FS_NOCOMP_FL) {
+		ip->flags&=3D ~BTRFS_INODE_COMPRESS;
+		ip->flags |=3D BTRFS_INODE_NOCOMPRESS;
+	} else if (flags&  FS_COMPR_FL) {

fs/btrfs/ioctl.c static int btrfs_ioctl_setflags(struct file *fil= · line 239

Quoted 10 lines
fs/btrfs/ioctl.c +7 -0
+		ip->flags |=3D BTRFS_INODE_COMPRESS;
+		ip->flags&=3D ~BTRFS_INODE_NOCOMPRESS;
+	}
+	if (flags&  FS_NOCOW_FL)
+		ip->flags |=3D BTRFS_INODE_NODATACOW;
+	else if (flags&  FS_COW_FL)
+		ip->flags&=3D ~BTRFS_INODE_NODATACOW;
 
  	trans =3D btrfs_join_transaction(root, 1);
  	BUG_ON(IS_ERR(trans));

--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" = in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

author
#5 lore raw
Quoted 4 lines · Konstantinos Skarlatos

Hello,
I would like to ask about the status of this feature/patch, is it accepted into btrfs code, and how can I use it?
=20

Yes, it is now in the latest 2.6.39-rc1.

Quoted 4 lines

I am interested in enabling compression in a specific folder(force-compress would be ideal) of a large btrfs volume, and disabling it for the rest.
=20

hmm, I'm making the tool's patch, and will come soon. :)

Quoted 5 lines

=20

Quoted 3 lines · liubo

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 p=

er

Quoted 1 line
Quoted 1 line

directory basis. This has been proposed previously, but VFS develop=

ers

Quoted 3 lines
Quoted 3 lines

wanted us to use generic ioctls rather than btrfs-specific ones.

According to chris's comment, there should be just one true compress=

ion

Quoted 1 line
Quoted 1 line

method(probably LZO) stored in the super. However, before this, we =

would

Quoted 1 line
Quoted 1 line

wait for that one method is stable enough to be adopted into the sup=

er.

Quoted 9 lines
Quoted 9 lines

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

Quoted 6 lines
Quoted 6 lines

it.
Otherwise, we'll use the default compress type (zlib today).

v1->v2:
Rebase the patch with the latest btrfs.

Quoted 6 lines
Quoted 6 lines
---
  fs/btrfs/ctree.h   |    1 +
  fs/btrfs/disk-io.c |    6 ++++++
  fs/btrfs/inode.c   |   32 ++++++++++++++++++++++++++++----

fs/btrfs/ioctl.c | 41 +++++++++++++++++++++++++++++++++++++---=

-

Quoted 12 lines
Quoted 12 lines
  4 files changed, 72 insertions(+), 8 deletions(-)
fs/btrfs/ctree.h +1 -0
index 8b4b9d1..b77d1a5 100644
@@ -1283,6 +1283,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)
 
Quoted 1 line

fs/btrfs/ctree.h struct btrfs_root { · line 1288

Quoted 1 line
fs/btrfs/ctree.h +0 -0
  /* some macros to generate set/get funcs for the struct fields.  T=

his

Quoted 9 lines
Quoted 9 lines
fs/btrfs/ctree.h +0 -0
   * assumes there is a lefoo_to_cpu for every type, so lets make a

simple

fs/btrfs/disk-io.c +0 -0
index 3e1ea3e..a894c12 100644
@@ -1762,6 +1762,12 @@ struct btrfs_root *open_ctree(struct
 super_block *sb,
 
Quoted 4 lines

fs/btrfs/disk-io.c struct btrfs_root *open_ctree(struct super_block *sb,

Quoted 4 lines
fs/btrfs/disk-io.c +2 -0
      btrfs_check_super_valid(fs_info, sb->s_flags&  MS_RDONLY);
 
+    /*
+     * In the long term, we'll store the compression type in the su=

per

Quoted 12 lines
Quoted 12 lines
fs/btrfs/disk-io.c +4 -0
+     * block, and it'll be used for per file compression control.
+     */
+    fs_info->compress_type =3D BTRFS_COMPRESS_ZLIB;
+
      ret =3D btrfs_parse_options(tree_root, options);
      if (ret) {
          err =3D ret;
fs/btrfs/inode.c +0 -0
index db67821..e687bb9 100644
@@ -381,7 +381,8 @@ again:
Quoted 8 lines

fs/btrfs/inode.c again:

Quoted 8 lines
fs/btrfs/inode.c +2 -1
       */
      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 =3D kzalloc(sizeof(struct page *) * nr_pages, GFP_NO=

=46S);

Quoted 27 lines
Quoted 27 lines
fs/btrfs/inode.c +2 -1
@@ -1253,7 +1254,8 @@ static int run_delalloc_range(struct inode
 *inode, struct page *locked_page,
          ret =3D 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 =3D cow_file_range(inode, locked_page, start, end,
                        page_started, nr_written, 1);

else

fs/btrfs/inode.c +0 -2
@@ -4581,8 +4583,6 @@ static struct inode *btrfs_new_inode(struct
 btrfs_trans_handle *trans,
      location->offset =3D 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 |=3D BTRFS_INODE_NODATASUM;
fs/btrfs/inode.c +0 -0
@@ -4590,6 +4590,8 @@ static struct inode *btrfs_new_inode(struct
 btrfs_trans_handle *trans,
              BTRFS_I(inode)->flags |=3D BTRFS_INODE_NODATACOW;
      }
 
Quoted 6 lines

fs/btrfs/inode.c static int btrfs_getattr(struct vfsmount *mnt=

Quoted 6 lines
fs/btrfs/inode.c +2 -0
+    btrfs_inherit_iflags(inode, dir);
+
      insert_inode_hash(inode);
      inode_tree_add(inode);
      return inode;
fs/btrfs/inode.c +0 -0
@@ -6803,6 +6805,26 @@ static int btrfs_getattr(struct vfsmount *mnt=

,

Quoted 5 lines

fs/btrfs/inode.c static int btrfs_getattr(struct vfsmount *mnt,

Quoted 5 lines
fs/btrfs/inode.c +2 -0
      return 0;
  }
 
+/*
+ * If a file is moved, it will inherit the cow and compression flag=

s

Quoted 4 lines
Quoted 4 lines

of the new
+ * directory.
+ */
+static void fixup_inode_flags(struct inode *dir, struct inode *inod=

e)

Quoted 49 lines
Quoted 49 lines
fs/btrfs/inode.c +15 -0
+{
+    struct btrfs_inode *b_dir =3D BTRFS_I(dir);
+    struct btrfs_inode *b_inode =3D BTRFS_I(inode);
+
+    if (b_dir->flags&  BTRFS_INODE_NODATACOW)
+        b_inode->flags |=3D BTRFS_INODE_NODATACOW;
+    else
+        b_inode->flags&=3D ~BTRFS_INODE_NODATACOW;
+
+    if (b_dir->flags&  BTRFS_INODE_COMPRESS)
+        b_inode->flags |=3D BTRFS_INODE_COMPRESS;
+    else
+        b_inode->flags&=3D ~BTRFS_INODE_COMPRESS;
+}
+
  static int btrfs_rename(struct inode *old_dir, struct dentry

*old_dentry,
struct inode *new_dir, struct dentry *new_dentry)
{

fs/btrfs/inode.c +2 -0
@@ -6936,6 +6958,8 @@ static int btrfs_rename(struct inode *old_dir,
 struct dentry *old_dentry,
          }
      }
 
+    fixup_inode_flags(new_dir, old_inode);
+
      ret =3D btrfs_add_link(trans, new_dir, old_inode,
                   new_dentry->d_name.name,
                   new_dentry->d_name.len, 0, index);
fs/btrfs/ioctl.c +11 -0
index 5fdb2ab..93e7f6c 100644
@@ -138,6 +138,24 @@ static int btrfs_ioctl_getflags(struct file
 *file, void __user *arg)
      return 0;
  }
 
+static int check_flags(unsigned int flags)
+{
+    if (flags&  ~(FS_IMMUTABLE_FL | FS_APPEND_FL | \
+              FS_NOATIME_FL | FS_NODUMP_FL | \
+              FS_SYNC_FL | FS_DIRSYNC_FL | \
+              FS_NOCOMP_FL | FS_COMPR_FL | \
+              FS_NOCOW_FL | FS_COW_FL))
+        return -EOPNOTSUPP;
+
+    if ((flags&  FS_NOCOMP_FL)&&  (flags&  FS_COMPR_FL))
+        return -EINVAL;
Quoted 8 lines

fs/btrfs/ioctl.c static int btrfs_ioctl_getflags(struct file *file, void __user *arg)

Quoted 8 lines
fs/btrfs/ioctl.c +7 -0
+
+    if ((flags&  FS_NOCOW_FL)&&  (flags&  FS_COW_FL))
+        return -EINVAL;
+
+    return 0;
+}
+
  static int btrfs_ioctl_setflags(struct file *file, void __user *ar=

g)

Quoted 22 lines
Quoted 22 lines
fs/btrfs/ioctl.c +0 -0
  {
      struct inode *inode =3D file->f_path.dentry->d_inode;
fs/btrfs/ioctl.c +3 -4
@@ -153,10 +171,9 @@ static int btrfs_ioctl_setflags(struct file
 *file, void __user *arg)
      if (copy_from_user(&flags, arg, sizeof(flags)))
          return -EFAULT;
 
-    if (flags&  ~(FS_IMMUTABLE_FL | FS_APPEND_FL | \
-              FS_NOATIME_FL | FS_NODUMP_FL | \
-              FS_SYNC_FL | FS_DIRSYNC_FL))
-        return -EOPNOTSUPP;
+    ret =3D check_flags(flags);
+    if (ret)
+        return ret;
 
      if (!is_owner_or_cap(inode))
          return -EACCES;
fs/btrfs/ioctl.c +0 -0
@@ -201,6 +218,22 @@ static int btrfs_ioctl_setflags(struct file
 *file, void __user *arg)
      else
          ip->flags&=3D ~BTRFS_INODE_DIRSYNC;
 
Quoted 4 lines
Quoted 4 lines
fs/btrfs/ioctl.c +2 -0
+    /*
+     * The COMPRESS flag can only be changed by users, while the

NOCOMPRESS
+ * flag may be changed automatically if compression code won't =

make

Quoted 14 lines
Quoted 14 lines
fs/btrfs/ioctl.c +13 -0
+     * things smaller.
+     */
+    if (flags&  FS_NOCOMP_FL) {
+        ip->flags&=3D ~BTRFS_INODE_COMPRESS;
+        ip->flags |=3D BTRFS_INODE_NOCOMPRESS;
+    } else if (flags&  FS_COMPR_FL) {
+        ip->flags |=3D BTRFS_INODE_COMPRESS;
+        ip->flags&=3D ~BTRFS_INODE_NOCOMPRESS;
+    }
+    if (flags&  FS_NOCOW_FL)
+        ip->flags |=3D BTRFS_INODE_NODATACOW;
+    else if (flags&  FS_COW_FL)
+        ip->flags&=3D ~BTRFS_INODE_NODATACOW;
Quoted 4 lines
Quoted 2 lines
      trans =3D btrfs_join_transaction(root, 1);
      BUG_ON(IS_ERR(trans));

=20
=20

--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" = in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#6 lore raw
Quoted 6 lines · liubo
Quoted 4 lines · Konstantinos Skarlatos

Hello,
I would like to ask about the status of this feature/patch, is it accepted into btrfs code, and how can I use it?

Quoted 9 lines

Yes, it is now in the latest 2.6.39-rc1.

Quoted 4 lines

I am interested in enabling compression in a specific folder(force-compress would be ideal) of a large btrfs volume, and disabling it for the rest.

hmm, I'm making the tool's patch, and will come soon. :)

What's wrong with this?

# chattr -c -R /btrfs/folder

(But force-compress is not implemented in the kernel)