FAQ Search Today's Posts Mark Forums Read
» Video Reviews

» Linux Archive

Linux-archive is a website aiming to archive linux email lists and to make them easily accessible for linux users/developers.


» Sponsor

» Partners

» Sponsor

Go Back   Linux Archive > Redhat > Cluster Development

 
 
LinkBack Thread Tools
 
Old 07-28-2010, 04:56 PM
Steven Whitehouse
 
Default GFS2: Use kmalloc when possible for ->readdir() (try #2)

If we don't need a huge amount of memory in ->readdir() then
we can use kmalloc rather than vmalloc to allocate it. This
should cut down on the greater overheads associated with
vmalloc for smaller directories.

We may be able to eliminate vmalloc entirely at some stage,
but this is easy to do right away.

Also using GFP_NOFS to avoid any issues wrt to deleting inodes
while under a glock, and suggestion from Linus to factor out
the alloc/dealloc.

I've given this a test with a variety of different sized
directories and it seems to work ok.

Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Nick Piggin <npiggin@suse.de>
Cc: Prarit Bhargava <prarit@redhat.com>
Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>

diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c
index 401deaf..b9dd88a 100644
--- a/fs/gfs2/dir.c
+++ b/fs/gfs2/dir.c
@@ -1238,6 +1238,25 @@ static int do_filldir_main(struct gfs2_inode *dip, u64 *offset,
return 0;
}

+static void *gfs2_alloc_sort_buffer(unsigned size)
+{
+ void *ptr = NULL;
+
+ if (size < KMALLOC_MAX_SIZE)
+ ptr = kmalloc(size, GFP_NOFS | __GFP_NOWARN);
+ if (!ptr)
+ ptr = __vmalloc(size, GFP_NOFS, PAGE_KERNEL);
+ return ptr;
+}
+
+static void gfs2_free_sort_buffer(void *ptr)
+{
+ if (is_vmalloc_addr(ptr))
+ vfree(ptr);
+ else
+ kfree(ptr);
+}
+
static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque,
filldir_t filldir, int *copied, unsigned *depth,
u64 leaf_no)
@@ -1278,7 +1297,7 @@ static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque,
* 99 is the maximum number of entries that can fit in a single
* leaf block.
*/
- larr = vmalloc((leaves + entries + 99) * sizeof(void *));
+ larr = gfs2_alloc_sort_buffer((leaves + entries + 99) * sizeof(void *));
if (!larr)
goto out;
darr = (const struct gfs2_dirent **)(larr + leaves);
@@ -1289,7 +1308,7 @@ static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque,
do {
error = get_leaf(ip, lfn, &bh);
if (error)
- goto out_kfree;
+ goto out_free;
lf = (struct gfs2_leaf *)bh->b_data;
lfn = be64_to_cpu(lf->lf_next);
if (lf->lf_entries) {
@@ -1298,7 +1317,7 @@ static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque,
gfs2_dirent_gather, NULL, &g);
error = PTR_ERR(dent);
if (IS_ERR(dent))
- goto out_kfree;
+ goto out_free;
if (entries2 != g.offset) {
fs_warn(sdp, "Number of entries corrupt in dir "
"leaf %llu, entries2 (%u) != "
@@ -1307,7 +1326,7 @@ static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque,
entries2, g.offset);

error = -EIO;
- goto out_kfree;
+ goto out_free;
}
error = 0;
larr[leaf++] = bh;
@@ -1319,10 +1338,10 @@ static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque,
BUG_ON(entries2 != entries);
error = do_filldir_main(ip, offset, opaque, filldir, darr,
entries, copied);
-out_kfree:
+out_free:
for(i = 0; i < leaf; i++)
brelse(larr[i]);
- vfree(larr);
+ gfs2_free_sort_buffer(larr);
out:
return error;
}
 
Old 07-28-2010, 05:13 PM
Andrew Morton
 
Default GFS2: Use kmalloc when possible for ->readdir() (try #2)

On Wed, 28 Jul 2010 17:56:23 +0100 Steven Whitehouse <swhiteho@redhat.com> wrote:

> +static void *gfs2_alloc_sort_buffer(unsigned size)
> +{
> + void *ptr = NULL;
> +
> + if (size < KMALLOC_MAX_SIZE)
> + ptr = kmalloc(size, GFP_NOFS | __GFP_NOWARN);
> + if (!ptr)
> + ptr = __vmalloc(size, GFP_NOFS, PAGE_KERNEL);
> + return ptr;
> +}
> +
> +static void gfs2_free_sort_buffer(void *ptr)
> +{
> + if (is_vmalloc_addr(ptr))
> + vfree(ptr);
> + else
> + kfree(ptr);
> +}

This got kicked around a bit in May (Subject: mm: generic adaptive
large memory allocation APIs). That patch tried kmalloc(), then
alloc_pages(), then vmalloc(). Nothing got merged though.

I wasn't terribly excited about it because of vague fears that it would
just incite people to spend even less effort thinking about how large
their individual allocations are.

apparmor has a private kvfree/kvmalloc. Probably there are other
versions floating around the tree as well.
 
Old 07-28-2010, 05:51 PM
Steven Whitehouse
 
Default GFS2: Use kmalloc when possible for ->readdir() (try #2)

Hi,

On Wed, 2010-07-28 at 10:13 -0700, Andrew Morton wrote:
> On Wed, 28 Jul 2010 17:56:23 +0100 Steven Whitehouse <swhiteho@redhat.com> wrote:
>
> > +static void *gfs2_alloc_sort_buffer(unsigned size)
> > +{
> > + void *ptr = NULL;
> > +
> > + if (size < KMALLOC_MAX_SIZE)
> > + ptr = kmalloc(size, GFP_NOFS | __GFP_NOWARN);
> > + if (!ptr)
> > + ptr = __vmalloc(size, GFP_NOFS, PAGE_KERNEL);
> > + return ptr;
> > +}
> > +
> > +static void gfs2_free_sort_buffer(void *ptr)
> > +{
> > + if (is_vmalloc_addr(ptr))
> > + vfree(ptr);
> > + else
> > + kfree(ptr);
> > +}
>
> This got kicked around a bit in May (Subject: mm: generic adaptive
> large memory allocation APIs). That patch tried kmalloc(), then
> alloc_pages(), then vmalloc(). Nothing got merged though.
>
> I wasn't terribly excited about it because of vague fears that it would
> just incite people to spend even less effort thinking about how large
> their individual allocations are.
>
> apparmor has a private kvfree/kvmalloc. Probably there are other
> versions floating around the tree as well.
>

I did wonder about that too, but bearing in mind that the longer term
plan is to eliminate the vmalloc call, I wasn't sure it was worth doing,

Steve.
 

Thread Tools




All times are GMT. The time now is 09:10 AM.

VBulletin, Copyright ©2000 - 2014, Jelsoft Enterprises Ltd.
Content Relevant URLs by vBSEO ©2007, Crawlability, Inc.
Copyright 2007 - 2008, www.linux-archive.org