From: Jan Kara <jack@suse.cz>
To: Namjae Jeon <namjae.jeon@samsung.com>
Cc: Jan Kara <jack@suse.cz>, linux-fsdevel@vger.kernel.org
Subject: Re: [PATCH] udf: fix lookup performance issue when SLUB_DEBUG is enable
Date: Wed, 12 Nov 2014 13:41:23 +0100 [thread overview]
Message-ID: <20141112124123.GG4951@quack.suse.cz> (raw)
In-Reply-To: <009b01cffe6a$52e52090$f8af61b0$@samsung.com>
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@samsung.com>
> Signed-off-by: Vivek Trivedi <t.vivek@samsung.com>
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@suse.cz>
SUSE Labs, CR
prev parent reply other threads:[~2014-11-12 12:41 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-11-12 11:18 [PATCH] udf: fix lookup performance issue when SLUB_DEBUG is enable Namjae Jeon
2014-11-12 12:41 ` Jan Kara [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=20141112124123.GG4951@quack.suse.cz \
--to=jack@suse.cz \
--cc=linux-fsdevel@vger.kernel.org \
--cc=namjae.jeon@samsung.com \
/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