linux-btrfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Anand Jain <anand.jain@oracle.com>
To: dsterba@suse.cz, linux-btrfs@vger.kernel.org
Subject: Re: [PATCH 2/2 RFC] btrfs: start transaction in btrfs_ioctl_setflags()
Date: Thu, 18 Apr 2019 22:27:49 +0800	[thread overview]
Message-ID: <d4070d00-429a-704a-7960-e56fb7d0ba72@oracle.com> (raw)
In-Reply-To: <20190418132358.GM20156@twin.jikos.cz>


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

      reply	other threads:[~2019-04-18 14:28 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-04-17 15:37 [PATCH 0/2 RFC] fix duplicate code in btrfs_ioctl_setflags Anand Jain
2019-04-17 15:37 ` [PATCH 1/2 RFC] btrfs: refactor btrfs_set_props to validate externally Anand Jain
2019-04-17 15:37 ` [PATCH 2/2 RFC] btrfs: start transaction in btrfs_ioctl_setflags() Anand Jain
2019-04-18 13:23   ` David Sterba
2019-04-18 14:27     ` Anand Jain [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=d4070d00-429a-704a-7960-e56fb7d0ba72@oracle.com \
    --to=anand.jain@oracle.com \
    --cc=dsterba@suse.cz \
    --cc=linux-btrfs@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).