Re: [PATCH] udf: fix lookup performance issue when SLUB_DEBUG is enable

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed 12-11-14 20:18:02, Namjae Jeon wrote:
> Convert frequent small dynamic memory allocation to static allocation
> for filename.
> 
> It has been observed that there is huge performance drop in udf lookup
> performance when CONFIG_SLUB_DEBUG is enable. As per analysis with perf
> tool, most of time is spend in kmalloc and kfree in this scenario.
> Performance drop seems very severe as compared to other file system in
> similar scenario.
> 
> Consider below lookup test results on large udf mounted directory which has
> 4300 files
> 
> [Original Kernel]:
> $ mount -t udf -o ro,relatime,uid=0,gid=1010,mode=775,dmode=775,utf8 /dev/cdrom /mnt/
> $ cd /mnt/dir1
> $ time ls
> ...................
> 00222610.png  00340607.png  00442904.png  00571618.png  01105104.png
> real    4m 31.20s
> user    0m 0.05s
> sys     4m 9.48s
> 
> [After Applying Patch]
> $ mount -t udf -o ro,relatime,uid=0,gid=1010,mode=775,dmode=775,utf8 /dev/cdrom /mnt/
> $ cd /mnt/dir1
> $ time ls
> ................
> 00222610.png  00340607.png  00442904.png  00571618.png  01105104.png
> real    0m 21.11s
> user    0m 0.04s
> sys     0m 4.65s
> 
> Signed-off-by: Namjae Jeon <namjae.jeon@xxxxxxxxxxx>
> Signed-off-by: Vivek Trivedi <t.vivek@xxxxxxxxxxx>
  This is wrong. Your patch will make UDF consume 512-bytes of stack more
just in udf_get_filename(), udf_readdir() which calls this adds another 256
bytes. You cannot just waste kernel stack stack space like this or we soon
overflow it.

Frankly I don't think improving performance with SLUB_DEBUG is a sensible
goal...

								Honza

> ---
>  fs/udf/dir.c     |  9 +--------
>  fs/udf/namei.c   | 23 +++--------------------
>  fs/udf/unicode.c | 37 +++++++++++++------------------------
>  3 files changed, 17 insertions(+), 52 deletions(-)
> 
> diff --git a/fs/udf/dir.c b/fs/udf/dir.c
> index a012c51..490b9dd 100644
> --- a/fs/udf/dir.c
> +++ b/fs/udf/dir.c
> @@ -46,7 +46,7 @@ static int udf_readdir(struct file *file, struct dir_context *ctx)
>  	int block, iblock;
>  	loff_t nf_pos;
>  	int flen;
> -	unsigned char *fname = NULL;
> +	unsigned char fname[UDF_NAME_LEN];
>  	unsigned char *nameptr;
>  	uint16_t liu;
>  	uint8_t lfi;
> @@ -67,12 +67,6 @@ static int udf_readdir(struct file *file, struct dir_context *ctx)
>  	if (nf_pos >= size)
>  		goto out;
>  
> -	fname = kmalloc(UDF_NAME_LEN, GFP_NOFS);
> -	if (!fname) {
> -		ret = -ENOMEM;
> -		goto out;
> -	}
> -
>  	if (nf_pos == 0)
>  		nf_pos = udf_ext0_offset(dir);
>  
> @@ -184,7 +178,6 @@ out:
>  		brelse(fibh.ebh);
>  	brelse(fibh.sbh);
>  	brelse(epos.bh);
> -	kfree(fname);
>  
>  	return ret;
>  }
> diff --git a/fs/udf/namei.c b/fs/udf/namei.c
> index c12e260..45cbbb9 100644
> --- a/fs/udf/namei.c
> +++ b/fs/udf/namei.c
> @@ -147,7 +147,7 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir,
>  	struct fileIdentDesc *fi = NULL;
>  	loff_t f_pos;
>  	int block, flen;
> -	unsigned char *fname = NULL;
> +	unsigned char fname[UDF_NAME_LEN];
>  	unsigned char *nameptr;
>  	uint8_t lfi;
>  	uint16_t liu;
> @@ -183,10 +183,6 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir,
>  			goto out_err;
>  	}
>  
> -	fname = kmalloc(UDF_NAME_LEN, GFP_NOFS);
> -	if (!fname)
> -		goto out_err;
> -
>  	while (f_pos < size) {
>  		fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &epos, &eloc,
>  					&elen, &offset);
> @@ -245,7 +241,6 @@ out_err:
>  	brelse(fibh->sbh);
>  out_ok:
>  	brelse(epos.bh);
> -	kfree(fname);
>  
>  	return fi;
>  }
> @@ -298,7 +293,7 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
>  {
>  	struct super_block *sb = dir->i_sb;
>  	struct fileIdentDesc *fi = NULL;
> -	unsigned char *name = NULL;
> +	unsigned char name[UDF_NAME_LEN];
>  	int namelen;
>  	loff_t f_pos;
>  	loff_t size = udf_ext0_offset(dir) + dir->i_size;
> @@ -313,11 +308,6 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
>  	struct udf_inode_info *dinfo;
>  
>  	fibh->sbh = fibh->ebh = NULL;
> -	name = kmalloc(UDF_NAME_LEN, GFP_NOFS);
> -	if (!name) {
> -		*err = -ENOMEM;
> -		goto out_err;
> -	}
>  
>  	if (dentry) {
>  		if (!dentry->d_name.len) {
> @@ -532,7 +522,6 @@ out_err:
>  	brelse(fibh->sbh);
>  out_ok:
>  	brelse(epos.bh);
> -	kfree(name);
>  	return fi;
>  }
>  
> @@ -858,7 +847,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
>  	uint8_t *ea;
>  	int err;
>  	int block;
> -	unsigned char *name = NULL;
> +	unsigned char name[UDF_NAME_LEN];
>  	int namelen;
>  	struct udf_inode_info *iinfo;
>  	struct super_block *sb = dir->i_sb;
> @@ -868,11 +857,6 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
>  
>  	iinfo = UDF_I(inode);
>  	down_write(&iinfo->i_data_sem);
> -	name = kmalloc(UDF_NAME_LEN, GFP_NOFS);
> -	if (!name) {
> -		err = -ENOMEM;
> -		goto out_no_entry;
> -	}
>  
>  	inode->i_data.a_ops = &udf_symlink_aops;
>  	inode->i_op = &udf_symlink_inode_operations;
> @@ -984,7 +968,6 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
>  
>  	err = udf_add_nondir(dentry, inode);
>  out:
> -	kfree(name);
>  	return err;
>  
>  out_no_entry:
> diff --git a/fs/udf/unicode.c b/fs/udf/unicode.c
> index afd470e..3fbd900 100644
> --- a/fs/udf/unicode.c
> +++ b/fs/udf/unicode.c
> @@ -336,42 +336,31 @@ try_again:
>  int udf_get_filename(struct super_block *sb, uint8_t *sname, uint8_t *dname,
>  		     int flen)
>  {
> -	struct ustr *filename, *unifilename;
> +	struct ustr filename, unifilename;
>  	int len = 0;
>  
> -	filename = kmalloc(sizeof(struct ustr), GFP_NOFS);
> -	if (!filename)
> -		return 0;
> -
> -	unifilename = kmalloc(sizeof(struct ustr), GFP_NOFS);
> -	if (!unifilename)
> -		goto out1;
> -
> -	if (udf_build_ustr_exact(unifilename, sname, flen))
> -		goto out2;
> +	if (udf_build_ustr_exact(&unifilename, sname, flen))
> +		goto out;
>  
>  	if (UDF_QUERY_FLAG(sb, UDF_FLAG_UTF8)) {
> -		if (!udf_CS0toUTF8(filename, unifilename)) {
> +		if (!udf_CS0toUTF8(&filename, &unifilename)) {
>  			udf_debug("Failed in udf_get_filename: sname = %s\n",
>  				  sname);
> -			goto out2;
> +			goto out;
>  		}
>  	} else if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP)) {
> -		if (!udf_CS0toNLS(UDF_SB(sb)->s_nls_map, filename,
> -				  unifilename)) {
> +		if (!udf_CS0toNLS(UDF_SB(sb)->s_nls_map, &filename,
> +				  &unifilename)) {
>  			udf_debug("Failed in udf_get_filename: sname = %s\n",
>  				  sname);
> -			goto out2;
> +			goto out;
>  		}
>  	} else
> -		goto out2;
> -
> -	len = udf_translate_to_linux(dname, filename->u_name, filename->u_len,
> -				     unifilename->u_name, unifilename->u_len);
> -out2:
> -	kfree(unifilename);
> -out1:
> -	kfree(filename);
> +		goto out;
> +
> +	len = udf_translate_to_linux(dname, filename.u_name, filename.u_len,
> +				     unifilename.u_name, unifilename.u_len);
> +out:
>  	return len;
>  }
>  
> -- 
> 1.8.5.5
> 
-- 
Jan Kara <jack@xxxxxxx>
SUSE Labs, CR
--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]
  Powered by Linux