[2/2,RFC] btrfs: start transaction in btrfs_ioctl_setflags()
diff mbox series

Message ID 20190417153706.29942-3-anand.jain@oracle.com
State New
Headers show
Series
  • fix duplicate code in btrfs_ioctl_setflags
Related show

Commit Message

Anand Jain April 17, 2019, 3:37 p.m. UTC
When inode attribute flags is set through FS_IOC_SETFLAGS ioctl, there is
a bit of duplicate codes, the following things happens twice -
start/end_transaction, inode_inc_iversion(), current_time update to
inode->i_ctime, and btrfs_update_inode(). These are updated both at
btrfs_ioctl_setflags() and btrfs_set_props() as well. (RFC: So inode
version and the generation number should have increased by +2, but I
don't see that in the test case below ran without this patch)

This patch merges these two duplicate codes at btrfs_ioctl_setflags().

$ cat a
mkfs.btrfs -fq /dev/sdb || exit
mount /dev/sdb /btrfs
touch /btrfs/file1
sync
echo before:
btrfs in dump-super /dev/sdb | grep ^generation
btrfs in dump-tree /dev/sdb | grep -A4 "257 XATTR_ITEM"
btrfs in dump-tree /dev/sdb | grep -A4 "257 INODE_ITEM 0) item"
echo
echo "chattr +Ac /btrfs/file1"
chattr +Ac /btrfs/file1
sync
echo after:
btrfs in dump-super /dev/sdb | grep ^generation
btrfs in dump-tree /dev/sdb | grep -A4 "257 XATTR_ITEM"
btrfs in dump-tree /dev/sdb | grep -A4 "257 INODE_ITEM 0) item"

$ umount /btrfs; ./a
before:
generation		6
	item 4 key (257 INODE_ITEM 0) itemoff 15881 itemsize 160
		generation 6 transid 6 size 0 nbytes 0
		block group 0 mode 100644 links 1 uid 0 gid 0 rdev 0
		sequence 19 flags 0x0(none)

chattr +Ac /btrfs/file1
after:
generation		7
	item 6 key (257 XATTR_ITEM 550297449) itemoff 15815 itemsize 51
		location key (0 UNKNOWN.0 0) type XATTR
		transid 7 data_len 4 name_len 17
		name: btrfs.compression
		data zlib
	item 4 key (257 INODE_ITEM 0) itemoff 15881 itemsize 160
		generation 6 transid 7 size 0 nbytes 0
		block group 0 mode 100644 links 1 uid 0 gid 0 rdev 0
		sequence 21 flags 0xa00(NOATIME|COMPRESS)

Signed-off-by: Anand Jain <anand.jain@oracle.com>
---
 fs/btrfs/ioctl.c | 38 ++++++++++++++++++--------------------
 fs/btrfs/props.c |  6 +++---
 fs/btrfs/props.h |  3 +++
 3 files changed, 24 insertions(+), 23 deletions(-)

Comments

David Sterba April 18, 2019, 1:23 p.m. UTC | #1
On Wed, Apr 17, 2019 at 11:37:06PM +0800, Anand Jain wrote:
> When inode attribute flags is set through FS_IOC_SETFLAGS ioctl, there is
> a bit of duplicate codes, the following things happens twice -
> start/end_transaction, inode_inc_iversion(), current_time update to
> inode->i_ctime, and btrfs_update_inode(). These are updated both at
> btrfs_ioctl_setflags() and btrfs_set_props() as well. (RFC: So inode
> version and the generation number should have increased by +2, but I
> don't see that in the test case below ran without this patch)
> 
> This patch merges these two duplicate codes at btrfs_ioctl_setflags().
> 
> $ cat a
> mkfs.btrfs -fq /dev/sdb || exit
> mount /dev/sdb /btrfs
> touch /btrfs/file1
> sync
> echo before:
> btrfs in dump-super /dev/sdb | grep ^generation
> btrfs in dump-tree /dev/sdb | grep -A4 "257 XATTR_ITEM"
> btrfs in dump-tree /dev/sdb | grep -A4 "257 INODE_ITEM 0) item"
> echo
> echo "chattr +Ac /btrfs/file1"
> chattr +Ac /btrfs/file1
> sync
> echo after:
> btrfs in dump-super /dev/sdb | grep ^generation
> btrfs in dump-tree /dev/sdb | grep -A4 "257 XATTR_ITEM"
> btrfs in dump-tree /dev/sdb | grep -A4 "257 INODE_ITEM 0) item"
> 
> $ umount /btrfs; ./a
> before:
> generation		6
> 	item 4 key (257 INODE_ITEM 0) itemoff 15881 itemsize 160
> 		generation 6 transid 6 size 0 nbytes 0
> 		block group 0 mode 100644 links 1 uid 0 gid 0 rdev 0
> 		sequence 19 flags 0x0(none)
> 
> chattr +Ac /btrfs/file1
> after:
> generation		7
> 	item 6 key (257 XATTR_ITEM 550297449) itemoff 15815 itemsize 51
> 		location key (0 UNKNOWN.0 0) type XATTR
> 		transid 7 data_len 4 name_len 17
> 		name: btrfs.compression
> 		data zlib
> 	item 4 key (257 INODE_ITEM 0) itemoff 15881 itemsize 160
> 		generation 6 transid 7 size 0 nbytes 0
> 		block group 0 mode 100644 links 1 uid 0 gid 0 rdev 0
> 		sequence 21 flags 0xa00(NOATIME|COMPRESS)
> 
> Signed-off-by: Anand Jain <anand.jain@oracle.com>
> ---
>  fs/btrfs/ioctl.c | 38 ++++++++++++++++++--------------------
>  fs/btrfs/props.c |  6 +++---
>  fs/btrfs/props.h |  3 +++
>  3 files changed, 24 insertions(+), 23 deletions(-)
> 
> diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
> index 63e6e2f5b659..82772523bb87 100644
> --- a/fs/btrfs/ioctl.c
> +++ b/fs/btrfs/ioctl.c
> @@ -192,6 +192,7 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
>  	u64 old_flags;
>  	unsigned int old_i_flags;
>  	umode_t mode;
> +	const char *comp = NULL;
>  
>  	if (!inode_owner_or_capable(inode))
>  		return -EPERM;
> @@ -283,14 +284,7 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
>  	if (fsflags & FS_NOCOMP_FL) {
>  		binode->flags &= ~BTRFS_INODE_COMPRESS;
>  		binode->flags |= BTRFS_INODE_NOCOMPRESS;
> -
> -		/* set no-compression no need to validate prop here */
> -		ret = btrfs_set_prop_trans(inode, "btrfs.compression", NULL,
> -					   0, 0);
> -		if (ret && ret != -ENODATA)
> -			goto out_drop;
>  	} else if (fsflags & FS_COMPR_FL) {
> -		const char *comp;
>  
>  		if (IS_SWAPFILE(inode)) {
>  			ret = -ETXTBSY;
> @@ -300,36 +294,40 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
>  		binode->flags |= BTRFS_INODE_COMPRESS;
>  		binode->flags &= ~BTRFS_INODE_NOCOMPRESS;
>  
> -		/* compress_type is already validated during mount options */
>  		comp = btrfs_compress_type2str(fs_info->compress_type);
>  		if (!comp || comp[0] == 0)
>  			comp = btrfs_compress_type2str(BTRFS_COMPRESS_ZLIB);
> -
> -		ret = btrfs_set_prop_trans(inode, "btrfs.compression", comp,
> -					   strlen(comp), 0);
> -		if (ret)
> -			goto out_drop;
> -
>  	} else {
> -		/* reset prop, no need of validate prop here */
> -		ret = btrfs_set_prop_trans(inode, "btrfs.compression", NULL,
> -					   0, 0);
> -		if (ret && ret != -ENODATA)
> -			goto out_drop;
>  		binode->flags &= ~(BTRFS_INODE_COMPRESS | BTRFS_INODE_NOCOMPRESS);
>  	}
>  
> -	trans = btrfs_start_transaction(root, 1);
> +	trans = btrfs_start_transaction(root, 3);

This should reflect if the properties are actually changed or not, so
there's not unnecessary reservation made.

>  	if (IS_ERR(trans)) {
>  		ret = PTR_ERR(trans);
>  		goto out_drop;
>  	}
>  
> +	if (comp) {
> +		ret = btrfs_set_prop(trans, inode, "btrfs.compression", comp,
> +				     strlen(comp), 0);
> +		if (ret)
> +			goto out_abort;

Transaction abort should be done at the place where they happen and not
aggregated.

I see now that the validation is not necessary here.

> +		set_bit(BTRFS_INODE_COPY_EVERYTHING, &BTRFS_I(inode)->runtime_flags);
> +	} else {
> +		ret = btrfs_set_prop(trans, inode, "btrfs.compression", NULL,
> +				     0, 0);
> +		if (ret && ret != -ENODATA)
> +			goto out_abort;

Same.

> +	}
> +
>  	btrfs_sync_inode_flags_to_i_flags(inode);
>  	inode_inc_iversion(inode);
>  	inode->i_ctime = current_time(inode);
>  	ret = btrfs_update_inode(trans, root, inode);
>  
> + out_abort:
> +	if (ret)
> +		btrfs_abort_transaction(trans, ret);
>  	btrfs_end_transaction(trans);
>   out_drop:
>  	if (ret) {
> diff --git a/fs/btrfs/props.c b/fs/btrfs/props.c
> index e356dd2a0f73..aedf5a7d69c9 100644
> --- a/fs/btrfs/props.c
> +++ b/fs/btrfs/props.c
> @@ -72,9 +72,9 @@ int btrfs_validate_prop(const char *name, const char *value, size_t value_len)
>  	return handler->validate(value, value_len);
>  }
>  
> -static int btrfs_set_prop(struct btrfs_trans_handle *trans, struct inode *inode,
> -			  const char *name, const char *value, size_t value_len,
> -			  int flags)
> +int btrfs_set_prop(struct btrfs_trans_handle *trans, struct inode *inode,
> +		   const char *name, const char *value, size_t value_len,
> +		   int flags)

Exporting a fuction should be in another patch.

>  {
>  	const struct prop_handler *handler;
>  	int ret;
> diff --git a/fs/btrfs/props.h b/fs/btrfs/props.h
> index 01d2c1899bc7..30b99348977d 100644
> --- a/fs/btrfs/props.h
> +++ b/fs/btrfs/props.h
> @@ -12,6 +12,9 @@ void __init btrfs_props_init(void);
>  
>  int btrfs_set_prop_trans(struct inode *inode, const char *name,
>  			 const char *value, size_t value_len, int flags);
> +int btrfs_set_prop(struct btrfs_trans_handle *trans, struct inode *inode,
> +		   const char *name, const char *value, size_t value_len,
> +		   int flags);
>  int btrfs_validate_prop(const char *name, const char *value, size_t value_len);
>  
>  int btrfs_load_inode_props(struct inode *inode, struct btrfs_path *path);
> -- 
> 2.17.1
Anand Jain April 18, 2019, 2:27 p.m. UTC | #2
Thanks for the comments.. more below.

On 18/4/19 9:23 PM, David Sterba wrote:
> On Wed, Apr 17, 2019 at 11:37:06PM +0800, Anand Jain wrote:
>> When inode attribute flags is set through FS_IOC_SETFLAGS ioctl, there is
>> a bit of duplicate codes, the following things happens twice -
>> start/end_transaction, inode_inc_iversion(), current_time update to
>> inode->i_ctime, and btrfs_update_inode(). These are updated both at
>> btrfs_ioctl_setflags() and btrfs_set_props() as well. (RFC: So inode
>> version and the generation number should have increased by +2, but I
>> don't see that in the test case below ran without this patch)

Looks like we don't commit transaction on the end transaction. So its
just about optimizing the duplicate code.

>> This patch merges these two duplicate codes at btrfs_ioctl_setflags().
>>
>> $ cat a
>> mkfs.btrfs -fq /dev/sdb || exit
>> mount /dev/sdb /btrfs
>> touch /btrfs/file1
>> sync
>> echo before:
>> btrfs in dump-super /dev/sdb | grep ^generation
>> btrfs in dump-tree /dev/sdb | grep -A4 "257 XATTR_ITEM"
>> btrfs in dump-tree /dev/sdb | grep -A4 "257 INODE_ITEM 0) item"
>> echo
>> echo "chattr +Ac /btrfs/file1"
>> chattr +Ac /btrfs/file1
>> sync
>> echo after:
>> btrfs in dump-super /dev/sdb | grep ^generation
>> btrfs in dump-tree /dev/sdb | grep -A4 "257 XATTR_ITEM"
>> btrfs in dump-tree /dev/sdb | grep -A4 "257 INODE_ITEM 0) item"
>>
>> $ umount /btrfs; ./a
>> before:
>> generation		6
>> 	item 4 key (257 INODE_ITEM 0) itemoff 15881 itemsize 160
>> 		generation 6 transid 6 size 0 nbytes 0
>> 		block group 0 mode 100644 links 1 uid 0 gid 0 rdev 0
>> 		sequence 19 flags 0x0(none)
>>
>> chattr +Ac /btrfs/file1
>> after:
>> generation		7
>> 	item 6 key (257 XATTR_ITEM 550297449) itemoff 15815 itemsize 51
>> 		location key (0 UNKNOWN.0 0) type XATTR
>> 		transid 7 data_len 4 name_len 17
>> 		name: btrfs.compression
>> 		data zlib
>> 	item 4 key (257 INODE_ITEM 0) itemoff 15881 itemsize 160
>> 		generation 6 transid 7 size 0 nbytes 0
>> 		block group 0 mode 100644 links 1 uid 0 gid 0 rdev 0
>> 		sequence 21 flags 0xa00(NOATIME|COMPRESS)
>>
>> Signed-off-by: Anand Jain <anand.jain@oracle.com>
>> ---
>>   fs/btrfs/ioctl.c | 38 ++++++++++++++++++--------------------
>>   fs/btrfs/props.c |  6 +++---
>>   fs/btrfs/props.h |  3 +++
>>   3 files changed, 24 insertions(+), 23 deletions(-)
>>
>> diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
>> index 63e6e2f5b659..82772523bb87 100644
>> --- a/fs/btrfs/ioctl.c
>> +++ b/fs/btrfs/ioctl.c
>> @@ -192,6 +192,7 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
>>   	u64 old_flags;
>>   	unsigned int old_i_flags;
>>   	umode_t mode;
>> +	const char *comp = NULL;
>>   
>>   	if (!inode_owner_or_capable(inode))
>>   		return -EPERM;
>> @@ -283,14 +284,7 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
>>   	if (fsflags & FS_NOCOMP_FL) {
>>   		binode->flags &= ~BTRFS_INODE_COMPRESS;
>>   		binode->flags |= BTRFS_INODE_NOCOMPRESS;
>> -
>> -		/* set no-compression no need to validate prop here */
>> -		ret = btrfs_set_prop_trans(inode, "btrfs.compression", NULL,
>> -					   0, 0);
>> -		if (ret && ret != -ENODATA)
>> -			goto out_drop;
>>   	} else if (fsflags & FS_COMPR_FL) {
>> -		const char *comp;
>>   
>>   		if (IS_SWAPFILE(inode)) {
>>   			ret = -ETXTBSY;
>> @@ -300,36 +294,40 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
>>   		binode->flags |= BTRFS_INODE_COMPRESS;
>>   		binode->flags &= ~BTRFS_INODE_NOCOMPRESS;
>>   
>> -		/* compress_type is already validated during mount options */
>>   		comp = btrfs_compress_type2str(fs_info->compress_type);
>>   		if (!comp || comp[0] == 0)
>>   			comp = btrfs_compress_type2str(BTRFS_COMPRESS_ZLIB);
>> -
>> -		ret = btrfs_set_prop_trans(inode, "btrfs.compression", comp,
>> -					   strlen(comp), 0);
>> -		if (ret)
>> -			goto out_drop;
>> -
>>   	} else {
>> -		/* reset prop, no need of validate prop here */
>> -		ret = btrfs_set_prop_trans(inode, "btrfs.compression", NULL,
>> -					   0, 0);
>> -		if (ret && ret != -ENODATA)
>> -			goto out_drop;
>>   		binode->flags &= ~(BTRFS_INODE_COMPRESS | BTRFS_INODE_NOCOMPRESS);
>>   	}
>>   
>> -	trans = btrfs_start_transaction(root, 1);
>> +	trans = btrfs_start_transaction(root, 3);
> 
> This should reflect if the properties are actually changed or not, so
> there's not unnecessary reservation made.

  Here we assume reset a flag, if its unset.
  So to preserve a flag which is already set, the cli
  internally is doing some kind of read modify write.
  So we over write the compression property with the
  same value all the time. Can this optimization go into
  a new patch, as its been like that in the original code
  as well.


>>   	if (IS_ERR(trans)) {
>>   		ret = PTR_ERR(trans);
>>   		goto out_drop;
>>   	}
>>   
>> +	if (comp) {
>> +		ret = btrfs_set_prop(trans, inode, "btrfs.compression", comp,
>> +				     strlen(comp), 0);
>> +		if (ret)
>> +			goto out_abort;
> 
> Transaction abort should be done at the place where they happen and not
> aggregated.

  oh yes. Will do.

> I see now that the validation is not necessary here.
> 
>> +		set_bit(BTRFS_INODE_COPY_EVERYTHING, &BTRFS_I(inode)->runtime_flags);
>> +	} else {
>> +		ret = btrfs_set_prop(trans, inode, "btrfs.compression", NULL,
>> +				     0, 0);
>> +		if (ret && ret != -ENODATA)
>> +			goto out_abort;
> 
> Same.

yep thanks.

>> +	}
>> +
>>   	btrfs_sync_inode_flags_to_i_flags(inode);
>>   	inode_inc_iversion(inode);
>>   	inode->i_ctime = current_time(inode);
>>   	ret = btrfs_update_inode(trans, root, inode);
>>   
>> + out_abort:
>> +	if (ret)
>> +		btrfs_abort_transaction(trans, ret);
>>   	btrfs_end_transaction(trans);
>>    out_drop:
>>   	if (ret) {
>> diff --git a/fs/btrfs/props.c b/fs/btrfs/props.c
>> index e356dd2a0f73..aedf5a7d69c9 100644
>> --- a/fs/btrfs/props.c
>> +++ b/fs/btrfs/props.c
>> @@ -72,9 +72,9 @@ int btrfs_validate_prop(const char *name, const char *value, size_t value_len)
>>   	return handler->validate(value, value_len);
>>   }
>>   
>> -static int btrfs_set_prop(struct btrfs_trans_handle *trans, struct inode *inode,
>> -			  const char *name, const char *value, size_t value_len,
>> -			  int flags)
>> +int btrfs_set_prop(struct btrfs_trans_handle *trans, struct inode *inode,
>> +		   const char *name, const char *value, size_t value_len,
>> +		   int flags)
> 
> Exporting a fuction should be in another patch.

ok.

Thanks, Anand

>>   {
>>   	const struct prop_handler *handler;
>>   	int ret;
>> diff --git a/fs/btrfs/props.h b/fs/btrfs/props.h
>> index 01d2c1899bc7..30b99348977d 100644
>> --- a/fs/btrfs/props.h
>> +++ b/fs/btrfs/props.h
>> @@ -12,6 +12,9 @@ void __init btrfs_props_init(void);
>>   
>>   int btrfs_set_prop_trans(struct inode *inode, const char *name,
>>   			 const char *value, size_t value_len, int flags);
>> +int btrfs_set_prop(struct btrfs_trans_handle *trans, struct inode *inode,
>> +		   const char *name, const char *value, size_t value_len,
>> +		   int flags);
>>   int btrfs_validate_prop(const char *name, const char *value, size_t value_len);
>>   
>>   int btrfs_load_inode_props(struct inode *inode, struct btrfs_path *path);
>> -- 
>> 2.17.1

Patch
diff mbox series

diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 63e6e2f5b659..82772523bb87 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -192,6 +192,7 @@  static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
 	u64 old_flags;
 	unsigned int old_i_flags;
 	umode_t mode;
+	const char *comp = NULL;
 
 	if (!inode_owner_or_capable(inode))
 		return -EPERM;
@@ -283,14 +284,7 @@  static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
 	if (fsflags & FS_NOCOMP_FL) {
 		binode->flags &= ~BTRFS_INODE_COMPRESS;
 		binode->flags |= BTRFS_INODE_NOCOMPRESS;
-
-		/* set no-compression no need to validate prop here */
-		ret = btrfs_set_prop_trans(inode, "btrfs.compression", NULL,
-					   0, 0);
-		if (ret && ret != -ENODATA)
-			goto out_drop;
 	} else if (fsflags & FS_COMPR_FL) {
-		const char *comp;
 
 		if (IS_SWAPFILE(inode)) {
 			ret = -ETXTBSY;
@@ -300,36 +294,40 @@  static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
 		binode->flags |= BTRFS_INODE_COMPRESS;
 		binode->flags &= ~BTRFS_INODE_NOCOMPRESS;
 
-		/* compress_type is already validated during mount options */
 		comp = btrfs_compress_type2str(fs_info->compress_type);
 		if (!comp || comp[0] == 0)
 			comp = btrfs_compress_type2str(BTRFS_COMPRESS_ZLIB);
-
-		ret = btrfs_set_prop_trans(inode, "btrfs.compression", comp,
-					   strlen(comp), 0);
-		if (ret)
-			goto out_drop;
-
 	} else {
-		/* reset prop, no need of validate prop here */
-		ret = btrfs_set_prop_trans(inode, "btrfs.compression", NULL,
-					   0, 0);
-		if (ret && ret != -ENODATA)
-			goto out_drop;
 		binode->flags &= ~(BTRFS_INODE_COMPRESS | BTRFS_INODE_NOCOMPRESS);
 	}
 
-	trans = btrfs_start_transaction(root, 1);
+	trans = btrfs_start_transaction(root, 3);
 	if (IS_ERR(trans)) {
 		ret = PTR_ERR(trans);
 		goto out_drop;
 	}
 
+	if (comp) {
+		ret = btrfs_set_prop(trans, inode, "btrfs.compression", comp,
+				     strlen(comp), 0);
+		if (ret)
+			goto out_abort;
+		set_bit(BTRFS_INODE_COPY_EVERYTHING, &BTRFS_I(inode)->runtime_flags);
+	} else {
+		ret = btrfs_set_prop(trans, inode, "btrfs.compression", NULL,
+				     0, 0);
+		if (ret && ret != -ENODATA)
+			goto out_abort;
+	}
+
 	btrfs_sync_inode_flags_to_i_flags(inode);
 	inode_inc_iversion(inode);
 	inode->i_ctime = current_time(inode);
 	ret = btrfs_update_inode(trans, root, inode);
 
+ out_abort:
+	if (ret)
+		btrfs_abort_transaction(trans, ret);
 	btrfs_end_transaction(trans);
  out_drop:
 	if (ret) {
diff --git a/fs/btrfs/props.c b/fs/btrfs/props.c
index e356dd2a0f73..aedf5a7d69c9 100644
--- a/fs/btrfs/props.c
+++ b/fs/btrfs/props.c
@@ -72,9 +72,9 @@  int btrfs_validate_prop(const char *name, const char *value, size_t value_len)
 	return handler->validate(value, value_len);
 }
 
-static int btrfs_set_prop(struct btrfs_trans_handle *trans, struct inode *inode,
-			  const char *name, const char *value, size_t value_len,
-			  int flags)
+int btrfs_set_prop(struct btrfs_trans_handle *trans, struct inode *inode,
+		   const char *name, const char *value, size_t value_len,
+		   int flags)
 {
 	const struct prop_handler *handler;
 	int ret;
diff --git a/fs/btrfs/props.h b/fs/btrfs/props.h
index 01d2c1899bc7..30b99348977d 100644
--- a/fs/btrfs/props.h
+++ b/fs/btrfs/props.h
@@ -12,6 +12,9 @@  void __init btrfs_props_init(void);
 
 int btrfs_set_prop_trans(struct inode *inode, const char *name,
 			 const char *value, size_t value_len, int flags);
+int btrfs_set_prop(struct btrfs_trans_handle *trans, struct inode *inode,
+		   const char *name, const char *value, size_t value_len,
+		   int flags);
 int btrfs_validate_prop(const char *name, const char *value, size_t value_len);
 
 int btrfs_load_inode_props(struct inode *inode, struct btrfs_path *path);