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 02-23-2011, 08:11 PM
Bob Peterson
 
Default GFS2: unlink performance patch

Hi,

This patch is a performance improvement to GFS2's unlink code.
Rather than update the quota file and statfs file for every
single block that's stripped off in unlink function do_strip,
this patch keeps track and updates them once for every layer
that's stripped. This is done entirely inside the existing
transaction, so there should be no risk of corruption.
The other functions that deallocate blocks will be unaffected
because they are using wrapper functions that do the same
thing that they do today.

I tested this code on my roth cluster by creating 200
files in a directory, each of which is 100MB, then on
four nodes, I simultaneously deleted the files, thus competing
for GFS2 resources (but different files). The commands
I used were:

[root@roth-01]# time for i in `seq 1 4 200` ; do rm /mnt/gfs2/bigdir/gfs2.$i; done
[root@roth-02]# time for i in `seq 2 4 200` ; do rm /mnt/gfs2/bigdir/gfs2.$i; done
[root@roth-03]# time for i in `seq 3 4 200` ; do rm /mnt/gfs2/bigdir/gfs2.$i; done
[root@roth-05]# time for i in `seq 4 4 200` ; do rm /mnt/gfs2/bigdir/gfs2.$i; done

The performance increase was significant:

roth-01 roth-02 roth-03 roth-05
--------- --------- --------- ---------
old: real 0m34.027 0m25.021s 0m23.906s 0m35.646s
new: real 0m22.379s 0m24.362s 0m24.133s 0m18.562s

Total time spent deleting:
old: 118.6s
new: 89.4

For this particular case, this showed a 25% performance increase for
GFS2 unlinks.

Regards,

Bob Peterson
Red Hat File Systems

Signed-off-by: Bob Peterson <rpeterso@redhat.com>

--
fs/gfs2/bmap.c | 20 +++++++++++++++-----
fs/gfs2/rgrp.c | 34 +++++++++++++++++++++++++++++++---
fs/gfs2/rgrp.h | 2 ++
3 files changed, 48 insertions(+), 8 deletions(-)

diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index 3c4039d..ef3dc4b 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -21,6 +21,7 @@
#include "meta_io.h"
#include "quota.h"
#include "rgrp.h"
+#include "super.h"
#include "trans.h"
#include "dir.h"
#include "util.h"
@@ -757,7 +758,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct gfs2_rgrp_list rlist;
u64 bn, bstart;
- u32 blen;
+ u32 blen, btotal;
__be64 *p;
unsigned int rg_blocks = 0;
int metadata;
@@ -839,6 +840,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,

bstart = 0;
blen = 0;
+ btotal = 0;

for (p = top; p < bottom; p++) {
if (!*p)
@@ -851,9 +853,11 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
else {
if (bstart) {
if (metadata)
- gfs2_free_meta(ip, bstart, blen);
+ __gfs2_free_meta(ip, bstart, blen);
else
- gfs2_free_data(ip, bstart, blen);
+ __gfs2_free_data(ip, bstart, blen);
+
+ btotal += blen;
}

bstart = bn;
@@ -865,11 +869,17 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
}
if (bstart) {
if (metadata)
- gfs2_free_meta(ip, bstart, blen);
+ __gfs2_free_meta(ip, bstart, blen);
else
- gfs2_free_data(ip, bstart, blen);
+ __gfs2_free_data(ip, bstart, blen);
+
+ btotal += blen;
}

+ gfs2_statfs_change(sdp, 0, +btotal, 0);
+ gfs2_quota_change(ip, -(s64)btotal, ip->i_inode.i_uid,
+ ip->i_inode.i_gid);
+
ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;

gfs2_dinode_out(ip, dibh->b_data);
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index 7293ea2..cf930cd 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -1602,7 +1602,7 @@ rgrp_error:
*
*/

-void gfs2_free_data(struct gfs2_inode *ip, u64 bstart, u32 blen)
+void __gfs2_free_data(struct gfs2_inode *ip, u64 bstart, u32 blen)
{
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct gfs2_rgrpd *rgd;
@@ -1617,7 +1617,21 @@ void gfs2_free_data(struct gfs2_inode *ip, u64 bstart, u32 blen)
gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);

gfs2_trans_add_rg(rgd);
+}

+/**
+ * gfs2_free_data - free a contiguous run of data block(s)
+ * @ip: the inode these blocks are being freed from
+ * @bstart: first block of a run of contiguous blocks
+ * @blen: the length of the block run
+ *
+ */
+
+void gfs2_free_data(struct gfs2_inode *ip, u64 bstart, u32 blen)
+{
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
+
+ __gfs2_free_data(ip, bstart, blen);
gfs2_statfs_change(sdp, 0, +blen, 0);
gfs2_quota_change(ip, -(s64)blen, ip->i_inode.i_uid, ip->i_inode.i_gid);
}
@@ -1630,7 +1644,7 @@ void gfs2_free_data(struct gfs2_inode *ip, u64 bstart, u32 blen)
*
*/

-void gfs2_free_meta(struct gfs2_inode *ip, u64 bstart, u32 blen)
+void __gfs2_free_meta(struct gfs2_inode *ip, u64 bstart, u32 blen)
{
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct gfs2_rgrpd *rgd;
@@ -1645,10 +1659,24 @@ void gfs2_free_meta(struct gfs2_inode *ip, u64 bstart, u32 blen)
gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);

gfs2_trans_add_rg(rgd);
+ gfs2_meta_wipe(ip, bstart, blen);
+}

+/**
+ * gfs2_free_meta - free a contiguous run of data block(s)
+ * @ip: the inode these blocks are being freed from
+ * @bstart: first block of a run of contiguous blocks
+ * @blen: the length of the block run
+ *
+ */
+
+void gfs2_free_meta(struct gfs2_inode *ip, u64 bstart, u32 blen)
+{
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
+
+ __gfs2_free_meta(ip, bstart, blen);
gfs2_statfs_change(sdp, 0, +blen, 0);
gfs2_quota_change(ip, -(s64)blen, ip->i_inode.i_uid, ip->i_inode.i_gid);
- gfs2_meta_wipe(ip, bstart, blen);
}

void gfs2_unlink_di(struct inode *inode)
diff --git a/fs/gfs2/rgrp.h b/fs/gfs2/rgrp.h
index 50c2bb0..a80e303 100644
--- a/fs/gfs2/rgrp.h
+++ b/fs/gfs2/rgrp.h
@@ -52,7 +52,9 @@ extern int gfs2_ri_update(struct gfs2_inode *ip);
extern int gfs2_alloc_block(struct gfs2_inode *ip, u64 *bn, unsigned int *n);
extern int gfs2_alloc_di(struct gfs2_inode *ip, u64 *bn, u64 *generation);

+extern void __gfs2_free_data(struct gfs2_inode *ip, u64 bstart, u32 blen);
extern void gfs2_free_data(struct gfs2_inode *ip, u64 bstart, u32 blen);
+extern void __gfs2_free_meta(struct gfs2_inode *ip, u64 bstart, u32 blen);
extern void gfs2_free_meta(struct gfs2_inode *ip, u64 bstart, u32 blen);
extern void gfs2_free_di(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip);
extern void gfs2_unlink_di(struct inode *inode);
 
Old 02-24-2011, 11:38 AM
Steven Whitehouse
 
Default GFS2: unlink performance patch

Hi,

This looks like a really nice speed up. Many thanks for sorting this
out. I've applied it to the -nmw tree,

Steve.

On Wed, 2011-02-23 at 16:11 -0500, Bob Peterson wrote:
> Hi,
>
> This patch is a performance improvement to GFS2's unlink code.
> Rather than update the quota file and statfs file for every
> single block that's stripped off in unlink function do_strip,
> this patch keeps track and updates them once for every layer
> that's stripped. This is done entirely inside the existing
> transaction, so there should be no risk of corruption.
> The other functions that deallocate blocks will be unaffected
> because they are using wrapper functions that do the same
> thing that they do today.
>
> I tested this code on my roth cluster by creating 200
> files in a directory, each of which is 100MB, then on
> four nodes, I simultaneously deleted the files, thus competing
> for GFS2 resources (but different files). The commands
> I used were:
>
> [root@roth-01]# time for i in `seq 1 4 200` ; do rm /mnt/gfs2/bigdir/gfs2.$i; done
> [root@roth-02]# time for i in `seq 2 4 200` ; do rm /mnt/gfs2/bigdir/gfs2.$i; done
> [root@roth-03]# time for i in `seq 3 4 200` ; do rm /mnt/gfs2/bigdir/gfs2.$i; done
> [root@roth-05]# time for i in `seq 4 4 200` ; do rm /mnt/gfs2/bigdir/gfs2.$i; done
>
> The performance increase was significant:
>
> roth-01 roth-02 roth-03 roth-05
> --------- --------- --------- ---------
> old: real 0m34.027 0m25.021s 0m23.906s 0m35.646s
> new: real 0m22.379s 0m24.362s 0m24.133s 0m18.562s
>
> Total time spent deleting:
> old: 118.6s
> new: 89.4
>
> For this particular case, this showed a 25% performance increase for
> GFS2 unlinks.
>
> Regards,
>
> Bob Peterson
> Red Hat File Systems
>
> Signed-off-by: Bob Peterson <rpeterso@redhat.com>
>
> --
> fs/gfs2/bmap.c | 20 +++++++++++++++-----
> fs/gfs2/rgrp.c | 34 +++++++++++++++++++++++++++++++---
> fs/gfs2/rgrp.h | 2 ++
> 3 files changed, 48 insertions(+), 8 deletions(-)
>
> diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
> index 3c4039d..ef3dc4b 100644
> --- a/fs/gfs2/bmap.c
> +++ b/fs/gfs2/bmap.c
> @@ -21,6 +21,7 @@
> #include "meta_io.h"
> #include "quota.h"
> #include "rgrp.h"
> +#include "super.h"
> #include "trans.h"
> #include "dir.h"
> #include "util.h"
> @@ -757,7 +758,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
> struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
> struct gfs2_rgrp_list rlist;
> u64 bn, bstart;
> - u32 blen;
> + u32 blen, btotal;
> __be64 *p;
> unsigned int rg_blocks = 0;
> int metadata;
> @@ -839,6 +840,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
>
> bstart = 0;
> blen = 0;
> + btotal = 0;
>
> for (p = top; p < bottom; p++) {
> if (!*p)
> @@ -851,9 +853,11 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
> else {
> if (bstart) {
> if (metadata)
> - gfs2_free_meta(ip, bstart, blen);
> + __gfs2_free_meta(ip, bstart, blen);
> else
> - gfs2_free_data(ip, bstart, blen);
> + __gfs2_free_data(ip, bstart, blen);
> +
> + btotal += blen;
> }
>
> bstart = bn;
> @@ -865,11 +869,17 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
> }
> if (bstart) {
> if (metadata)
> - gfs2_free_meta(ip, bstart, blen);
> + __gfs2_free_meta(ip, bstart, blen);
> else
> - gfs2_free_data(ip, bstart, blen);
> + __gfs2_free_data(ip, bstart, blen);
> +
> + btotal += blen;
> }
>
> + gfs2_statfs_change(sdp, 0, +btotal, 0);
> + gfs2_quota_change(ip, -(s64)btotal, ip->i_inode.i_uid,
> + ip->i_inode.i_gid);
> +
> ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
>
> gfs2_dinode_out(ip, dibh->b_data);
> diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
> index 7293ea2..cf930cd 100644
> --- a/fs/gfs2/rgrp.c
> +++ b/fs/gfs2/rgrp.c
> @@ -1602,7 +1602,7 @@ rgrp_error:
> *
> */
>
> -void gfs2_free_data(struct gfs2_inode *ip, u64 bstart, u32 blen)
> +void __gfs2_free_data(struct gfs2_inode *ip, u64 bstart, u32 blen)
> {
> struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
> struct gfs2_rgrpd *rgd;
> @@ -1617,7 +1617,21 @@ void gfs2_free_data(struct gfs2_inode *ip, u64 bstart, u32 blen)
> gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);
>
> gfs2_trans_add_rg(rgd);
> +}
>
> +/**
> + * gfs2_free_data - free a contiguous run of data block(s)
> + * @ip: the inode these blocks are being freed from
> + * @bstart: first block of a run of contiguous blocks
> + * @blen: the length of the block run
> + *
> + */
> +
> +void gfs2_free_data(struct gfs2_inode *ip, u64 bstart, u32 blen)
> +{
> + struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
> +
> + __gfs2_free_data(ip, bstart, blen);
> gfs2_statfs_change(sdp, 0, +blen, 0);
> gfs2_quota_change(ip, -(s64)blen, ip->i_inode.i_uid, ip->i_inode.i_gid);
> }
> @@ -1630,7 +1644,7 @@ void gfs2_free_data(struct gfs2_inode *ip, u64 bstart, u32 blen)
> *
> */
>
> -void gfs2_free_meta(struct gfs2_inode *ip, u64 bstart, u32 blen)
> +void __gfs2_free_meta(struct gfs2_inode *ip, u64 bstart, u32 blen)
> {
> struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
> struct gfs2_rgrpd *rgd;
> @@ -1645,10 +1659,24 @@ void gfs2_free_meta(struct gfs2_inode *ip, u64 bstart, u32 blen)
> gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);
>
> gfs2_trans_add_rg(rgd);
> + gfs2_meta_wipe(ip, bstart, blen);
> +}
>
> +/**
> + * gfs2_free_meta - free a contiguous run of data block(s)
> + * @ip: the inode these blocks are being freed from
> + * @bstart: first block of a run of contiguous blocks
> + * @blen: the length of the block run
> + *
> + */
> +
> +void gfs2_free_meta(struct gfs2_inode *ip, u64 bstart, u32 blen)
> +{
> + struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
> +
> + __gfs2_free_meta(ip, bstart, blen);
> gfs2_statfs_change(sdp, 0, +blen, 0);
> gfs2_quota_change(ip, -(s64)blen, ip->i_inode.i_uid, ip->i_inode.i_gid);
> - gfs2_meta_wipe(ip, bstart, blen);
> }
>
> void gfs2_unlink_di(struct inode *inode)
> diff --git a/fs/gfs2/rgrp.h b/fs/gfs2/rgrp.h
> index 50c2bb0..a80e303 100644
> --- a/fs/gfs2/rgrp.h
> +++ b/fs/gfs2/rgrp.h
> @@ -52,7 +52,9 @@ extern int gfs2_ri_update(struct gfs2_inode *ip);
> extern int gfs2_alloc_block(struct gfs2_inode *ip, u64 *bn, unsigned int *n);
> extern int gfs2_alloc_di(struct gfs2_inode *ip, u64 *bn, u64 *generation);
>
> +extern void __gfs2_free_data(struct gfs2_inode *ip, u64 bstart, u32 blen);
> extern void gfs2_free_data(struct gfs2_inode *ip, u64 bstart, u32 blen);
> +extern void __gfs2_free_meta(struct gfs2_inode *ip, u64 bstart, u32 blen);
> extern void gfs2_free_meta(struct gfs2_inode *ip, u64 bstart, u32 blen);
> extern void gfs2_free_di(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip);
> extern void gfs2_unlink_di(struct inode *inode);
 

Thread Tools




All times are GMT. The time now is 10:22 PM.

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