2010-07-12 14:29:09

by shenghui

[permalink] [raw]
Subject: [PATCH] check name_len before down_read xattr_sem and sb_read in ext2_xattr_get

Hi,
I walked through ext2_xattr_get, and felt that we can
do some optimization on it. For name_len check, it's done
after down xattr_sem and sb_read, both of which are time
consuming operation compared with strlen:
down_read(&EXT2_I(inode)->xattr_sem);
...
bh = sb_bread(inode->i_sb, EXT2_I(inode)->i_file_acl);
...
/* find named attribute */
name_len = strlen(name);

error = -ERANGE;
if (name_len > 255)
goto cleanup;

Most of the case, you'll get one valid block, but if the
name len > 255, then the xattr_sem down and sb_bread operation
can be seen as a waste of time. So I think we'd better do
name len check as early as possible.
Following is my patch, and it's against 2.6.35-rc4.
Please check it.

Signed-off-by: Wang Sheng-Hui <[email protected]>
---
fs/ext2/xattr.c | 12 +++++++-----
1 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c
index 7c39157..0b94d61 100644
--- a/fs/ext2/xattr.c
+++ b/fs/ext2/xattr.c
@@ -161,6 +161,13 @@ ext2_xattr_get(struct inode *inode, int name_index, const char *name,

if (name == NULL)
return -EINVAL;
+
+ /* find named attribute */
+ name_len = strlen(name);
+ error = -ERANGE;
+ if (name_len > 255)
+ goto cleanup;
+
down_read(&EXT2_I(inode)->xattr_sem);
error = -ENODATA;
if (!EXT2_I(inode)->i_file_acl)
@@ -181,12 +188,7 @@ bad_block: ext2_error(inode->i_sb, "ext2_xattr_get",
error = -EIO;
goto cleanup;
}
- /* find named attribute */
- name_len = strlen(name);

- error = -ERANGE;
- if (name_len > 255)
- goto cleanup;
entry = FIRST_ENTRY(bh);
while (!IS_LAST_ENTRY(entry)) {
struct ext2_xattr_entry *next =
--
1.7.1.1


2010-07-13 14:28:19

by shenghui

[permalink] [raw]
Subject: Re: [PATCH] check name_len before down_read xattr_sem and sb_read in ext2_xattr_get

于 2010-7-12 22:29, crosslonelyover 写道:
> Hi,
> I walked through ext2_xattr_get, and felt that we can
> do some optimization on it. For name_len check, it's done
> after down xattr_sem and sb_read, both of which are time
> consuming operation compared with strlen:
> down_read(&EXT2_I(inode)->xattr_sem);
> ...
> bh = sb_bread(inode->i_sb, EXT2_I(inode)->i_file_acl);
> ...
> /* find named attribute */
> name_len = strlen(name);
>
> error = -ERANGE;
> if (name_len> 255)
> goto cleanup;
>
> Most of the case, you'll get one valid block, but if the
> name len> 255, then the xattr_sem down and sb_bread operation
> can be seen as a waste of time. So I think we'd better do
> name len check as early as possible.
> Following is my patch, and it's against 2.6.35-rc4.
> Please check it.
>
> Signed-off-by: Wang Sheng-Hui<[email protected]>
> ---
> fs/ext2/xattr.c | 12 +++++++-----
> 1 files changed, 7 insertions(+), 5 deletions(-)
>
> diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c
> index 7c39157..0b94d61 100644
> --- a/fs/ext2/xattr.c
> +++ b/fs/ext2/xattr.c
> @@ -161,6 +161,13 @@ ext2_xattr_get(struct inode *inode, int name_index, const char *name,
>
> if (name == NULL)
> return -EINVAL;
> +
> + /* find named attribute */
> + name_len = strlen(name);
> + error = -ERANGE;
> + if (name_len> 255)
> + goto cleanup;
> +
> down_read(&EXT2_I(inode)->xattr_sem);
> error = -ENODATA;
> if (!EXT2_I(inode)->i_file_acl)
> @@ -181,12 +188,7 @@ bad_block: ext2_error(inode->i_sb, "ext2_xattr_get",
> error = -EIO;
> goto cleanup;
> }
> - /* find named attribute */
> - name_len = strlen(name);
>
> - error = -ERANGE;
> - if (name_len> 255)
> - goto cleanup;
> entry = FIRST_ENTRY(bh);
> while (!IS_LAST_ENTRY(entry)) {
> struct ext2_xattr_entry *next =
Hi, I noticed in ext2_xattr_set, name_len check is done
before
down_write(&EXT2_I(inode)->xattr_sem);
So I think ext2_xattr_get should do in the same way.

Please check this patch.

--
Thanks and Regards,
shenghui

2010-07-13 14:57:53

by Dan Carpenter

[permalink] [raw]
Subject: Re: [PATCH] check name_len before down_read xattr_sem and sb_read in ext2_xattr_get

On Mon, Jul 12, 2010 at 10:29:09PM +0800, crosslonelyover wrote:
> Hi,
> I walked through ext2_xattr_get, and felt that we can
> do some optimization on it. For name_len check, it's done
> after down xattr_sem and sb_read, both of which are time
> consuming operation compared with strlen:
> down_read(&EXT2_I(inode)->xattr_sem);
> ...
> bh = sb_bread(inode->i_sb, EXT2_I(inode)->i_file_acl);
> ...
> /* find named attribute */
> name_len = strlen(name);
>
> error = -ERANGE;
> if (name_len > 255)
> goto cleanup;
>
> Most of the case, you'll get one valid block, but if the
> name len > 255, then the xattr_sem down and sb_bread operation
> can be seen as a waste of time. So I think we'd better do
> name len check as early as possible.
> Following is my patch, and it's against 2.6.35-rc4.
> Please check it.
>
> Signed-off-by: Wang Sheng-Hui <[email protected]>
> ---
> fs/ext2/xattr.c | 12 +++++++-----
> 1 files changed, 7 insertions(+), 5 deletions(-)

For what it's worth, this change looks OK to me.

Reviewed-by: Dan Carpenter <[email protected]>

regards,
dan carpenter



2010-07-21 17:44:58

by Jan Kara

[permalink] [raw]
Subject: Re: [PATCH] check name_len before down_read xattr_sem and sb_read in ext2_xattr_get

> Hi,
> I walked through ext2_xattr_get, and felt that we can
> do some optimization on it. For name_len check, it's done
> after down xattr_sem and sb_read, both of which are time
> consuming operation compared with strlen:
> down_read(&EXT2_I(inode)->xattr_sem);
> ...
> bh = sb_bread(inode->i_sb, EXT2_I(inode)->i_file_acl);
> ...
> /* find named attribute */
> name_len = strlen(name);
>
> error = -ERANGE;
> if (name_len > 255)
> goto cleanup;
>
> Most of the case, you'll get one valid block, but if the
> name len > 255, then the xattr_sem down and sb_bread operation
> can be seen as a waste of time. So I think we'd better do
> name len check as early as possible.
> Following is my patch, and it's against 2.6.35-rc4.
> Please check it.
>
> Signed-off-by: Wang Sheng-Hui <[email protected]>
> ---
> fs/ext2/xattr.c | 12 +++++++-----
> 1 files changed, 7 insertions(+), 5 deletions(-)
>
> diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c
> index 7c39157..0b94d61 100644
> --- a/fs/ext2/xattr.c
> +++ b/fs/ext2/xattr.c
> @@ -161,6 +161,13 @@ ext2_xattr_get(struct inode *inode, int name_index, const char *name,
>
> if (name == NULL)
> return -EINVAL;
> +
> + /* find named attribute */
> + name_len = strlen(name);
> + error = -ERANGE;
> + if (name_len > 255)
> + goto cleanup;
But you cannot go to cleanup here because you don't hold xattr_sem...

Honza
> +
> down_read(&EXT2_I(inode)->xattr_sem);
> error = -ENODATA;
> if (!EXT2_I(inode)->i_file_acl)
--
Jan Kara <[email protected]>
SuSE CR Labs

2010-07-22 00:03:20

by shenghui

[permalink] [raw]
Subject: Re: [PATCH] check name_len before down_read xattr_sem and sb_read in ext2_xattr_get

2010/7/22 Jan Kara <[email protected]>:
>> Hi,
>>        I walked through ext2_xattr_get, and felt that we can
>> do some optimization on it. For name_len check, it's done
>> after down xattr_sem and sb_read, both of which are time
>> consuming operation compared with strlen:
>>          down_read(&EXT2_I(inode)->xattr_sem);
>>  ...
>>          bh = sb_bread(inode->i_sb, EXT2_I(inode)->i_file_acl);
>>  ...
>>          /* find named attribute */
>>          name_len = strlen(name);
>>
>>          error = -ERANGE;
>>          if (name_len > 255)
>>                  goto cleanup;
>>
>>        Most of the case, you'll get one valid block, but if the
>> name len > 255, then the xattr_sem down and sb_bread operation
>> can be seen as a waste of time. So I think we'd better do
>> name len check as early as possible.
>>        Following is my patch, and it's against 2.6.35-rc4.
>> Please check it.
>>
>> Signed-off-by: Wang Sheng-Hui <[email protected]>
>> ---
>>  fs/ext2/xattr.c |   12 +++++++-----
>>  1 files changed, 7 insertions(+), 5 deletions(-)
>>
>> diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c
>> index 7c39157..0b94d61 100644
>> --- a/fs/ext2/xattr.c
>> +++ b/fs/ext2/xattr.c
>> @@ -161,6 +161,13 @@ ext2_xattr_get(struct inode *inode, int name_index, const char *name,
>>
>>       if (name == NULL)
>>               return -EINVAL;
>> +
>> +     /* find named attribute */
>> +     name_len = strlen(name);
>> +     error = -ERANGE;
>> +     if (name_len > 255)
>> +             goto cleanup;
>  But you cannot go to cleanup here because you don't hold xattr_sem...
>

Sorry, I'm a little confused by your words.
The patch just checks name_len, and it
doesn't need xattr_sem.



--


Thanks and Best Regards,
shenghui

2010-07-23 08:38:27

by Jan Kara

[permalink] [raw]
Subject: Re: [PATCH] check name_len before down_read xattr_sem and sb_read in ext2_xattr_get

On Thu 22-07-10 08:03:18, shenghui wrote:
> 2010/7/22 Jan Kara <[email protected]>:
> >> Hi,
> >> ? ? ? ?I walked through ext2_xattr_get, and felt that we can
> >> do some optimization on it. For name_len check, it's done
> >> after down xattr_sem and sb_read, both of which are time
> >> consuming operation compared with strlen:
> >> ? ? ? ? ?down_read(&EXT2_I(inode)->xattr_sem);
> >> ?...
> >> ? ? ? ? ?bh = sb_bread(inode->i_sb, EXT2_I(inode)->i_file_acl);
> >> ?...
> >> ? ? ? ? ?/* find named attribute */
> >> ? ? ? ? ?name_len = strlen(name);
> >>
> >> ? ? ? ? ?error = -ERANGE;
> >> ? ? ? ? ?if (name_len > 255)
> >> ? ? ? ? ? ? ? ? ?goto cleanup;
> >>
> >> ? ? ? ?Most of the case, you'll get one valid block, but if the
> >> name len > 255, then the xattr_sem down and sb_bread operation
> >> can be seen as a waste of time. So I think we'd better do
> >> name len check as early as possible.
> >> ? ? ? ?Following is my patch, and it's against 2.6.35-rc4.
> >> Please check it.
> >>
> >> Signed-off-by: Wang Sheng-Hui <[email protected]>
> >> ---
> >> ?fs/ext2/xattr.c | ? 12 +++++++-----
> >> ?1 files changed, 7 insertions(+), 5 deletions(-)
> >>
> >> diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c
> >> index 7c39157..0b94d61 100644
> >> --- a/fs/ext2/xattr.c
> >> +++ b/fs/ext2/xattr.c
> >> @@ -161,6 +161,13 @@ ext2_xattr_get(struct inode *inode, int name_index, const char *name,
> >>
> >> ? ? ? if (name == NULL)
> >> ? ? ? ? ? ? ? return -EINVAL;
> >> +
> >> + ? ? /* find named attribute */
> >> + ? ? name_len = strlen(name);
> >> + ? ? error = -ERANGE;
> >> + ? ? if (name_len > 255)
> >> + ? ? ? ? ? ? goto cleanup;
> > ?But you cannot go to cleanup here because you don't hold xattr_sem...
> >
>
> Sorry, I'm a little confused by your words.
> The patch just checks name_len, and it
> doesn't need xattr_sem.
Checking of name_len is fine as you did it. But I wanted to point out
that if name_len is greater than 255, you then go to 'cleanup' label which
tries to do up_read(&EXT2_I(inode)->xattr_sem). But that's a bug because
after you moved the code, we don't hold xattr_sem at the moment we check
name_len.

Honza
--
Jan Kara <[email protected]>
SUSE Labs, CR

2010-07-23 12:46:57

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [PATCH] check name_len before down_read xattr_sem and sb_read in ext2_xattr_get

On Fri, Jul 23, 2010 at 10:37:59AM +0200, Jan Kara wrote:
> Checking of name_len is fine as you did it. But I wanted to point out
> that if name_len is greater than 255, you then go to 'cleanup' label which
> tries to do up_read(&EXT2_I(inode)->xattr_sem). But that's a bug because
> after you moved the code, we don't hold xattr_sem at the moment we check
> name_len.

Yup, you could just return -ERANGE right there.

The simpler fix though might be to just delete the check altogether.
Neither ext3 nor ext4 checks for the length of the xattr name in their
_xattr_get() function. Instead they'll just do the search, and then
return -ENODATA. That seems legit; there can be no entries larger
than 255, so saying the extended attribute doesn't exist is quite
correct. There is a check in the _xattr_set() functions for both ext3
and ext4, which is quite correct and proper.

Does that mean we'll end up doing a search before returning an error
--- yes, but I don't think that matters. Why should we care about
optimizing an error case? It's not like this is going to be in a
timing sensitive part of an application.... (of course the same
consideration could apply to your patch as well).

- Ted

2010-07-25 13:12:08

by shenghui

[permalink] [raw]
Subject: Re: [PATCH] check name_len before down_read xattr_sem and sb_read in ext2_xattr_get

Thanks for your instructions and explanation!


--


Thanks and Best Regards,
shenghui