[GFS2] kernel changes to support new gfs2_grow command

2007-07-10 Thread Linux Kernel Mailing List
Gitweb: 
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=7ae8fa8451dfb3879ecbc04f2760a707dc65b988
Commit: 7ae8fa8451dfb3879ecbc04f2760a707dc65b988
Parent: 3168b0780d06ace875696f8a648d04d6089654e5
Author: Robert Peterson <[EMAIL PROTECTED]>
AuthorDate: Wed May 9 09:37:57 2007 -0500
Committer:  Steven Whitehouse <[EMAIL PROTECTED]>
CommitDate: Mon Jul 9 08:22:12 2007 +0100

[GFS2] kernel changes to support new gfs2_grow command

This is another revision of my gfs2 kernel patch that allows
gfs2_grow to function properly.

Steve Whitehouse expressed some concerns about the previous
patch and I restructured it based on his comments.
The previous patch was doing the statfs_change at file close time,
under its own transaction.  The current patch does the statfs_change
inside the gfs2_commit_write function, which keeps it under the
umbrella of the inode transaction.

I can't call ri_update to re-read the rindex file during the
transaction because the transaction may have outstanding unwritten
buffers attached to the rgrps that would be otherwise blown away.
So instead, I created a new function, gfs2_ri_total, that will
re-read the rindex file just to total the file system space
for the sake of the statfs_change.  The ri_update will happen
later, when gfs2 realizes the version number has changed, as it
happened before my patch.

Since the statfs_change is happening at write_commit time and there
may be multiple writes to the rindex file for one grow operation.
So one consequence of this restructuring is that instead of getting
one kernel message to indicate the change, you may see several.
For example, before when you did a gfs2_grow, you'd get a single
message like:

GFS2: File system extended by 247876 blocks (968MB)

Now you get something like:

GFS2: File system extended by 207896 blocks (812MB)
GFS2: File system extended by 39980 blocks (156MB)

This version has also been successfully run against the hours-long
"gfs2_fsck_hellfire" test that does several gfs2_grow and gfs2_fsck
while interjecting file system damage.  It does this repeatedly
under a variety Resource Group conditions.

Signed-off-By: Bob Peterson <[EMAIL PROTECTED]>
Signed-off-by: Steven Whitehouse <[EMAIL PROTECTED]>
---
 fs/gfs2/ops_address.c |   29 ++-
 fs/gfs2/ops_address.h |5 +++-
 fs/gfs2/rgrp.c|   60 -
 3 files changed, 86 insertions(+), 8 deletions(-)

diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c
index 30c1562..846c0ff 100644
--- a/fs/gfs2/ops_address.c
+++ b/fs/gfs2/ops_address.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
- * Copyright (C) 2004-2006 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc.  All rights reserved.
  *
  * This copyrighted material is made available to anyone wishing to use,
  * modify, copy, or redistribute it subject to the terms and conditions
@@ -450,6 +450,30 @@ out_uninit:
 }
 
 /**
+ * adjust_fs_space - Adjusts the free space available due to gfs2_grow
+ * @inode: the rindex inode
+ */
+static void adjust_fs_space(struct inode *inode)
+{
+   struct gfs2_sbd *sdp = inode->i_sb->s_fs_info;
+   struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master;
+   struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local;
+   u64 fs_total, new_free;
+
+   /* Total up the file system space, according to the latest rindex. */
+   fs_total = gfs2_ri_total(sdp);
+
+   spin_lock(&sdp->sd_statfs_spin);
+   if (fs_total > (m_sc->sc_total + l_sc->sc_total))
+   new_free = fs_total - (m_sc->sc_total + l_sc->sc_total);
+   else
+   new_free = 0;
+   spin_unlock(&sdp->sd_statfs_spin);
+   fs_warn(sdp, "File system extended by %llu blocks.\n", new_free);
+   gfs2_statfs_change(sdp, new_free, new_free, 0);
+}
+
+/**
  * gfs2_commit_write - Commit write to a file
  * @file: The file to write to
  * @page: The page containing the data
@@ -511,6 +535,9 @@ static int gfs2_commit_write(struct file *file, struct page 
*page,
di->di_size = cpu_to_be64(inode->i_size);
}
 
+   if (inode == sdp->sd_rindex)
+   adjust_fs_space(inode);
+
brelse(dibh);
gfs2_trans_end(sdp);
if (al->al_requested) {
diff --git a/fs/gfs2/ops_address.h b/fs/gfs2/ops_address.h
index 35aaee4..56c30da 100644
--- a/fs/gfs2/ops_address.h
+++ b/fs/gfs2/ops_address.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
- * Copyright (C) 2004-2006 Red Hat, Inc.  All rights reserved.
+ * Copyri

[GFS2] Kernel changes to support new gfs2_grow command (part 2)

2007-07-10 Thread Linux Kernel Mailing List
Gitweb: 
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=6c53267f05dc6689ff662efeec426d25d2c0ab84
Commit: 6c53267f05dc6689ff662efeec426d25d2c0ab84
Parent: 7ae8fa8451dfb3879ecbc04f2760a707dc65b988
Author: Robert Peterson <[EMAIL PROTECTED]>
AuthorDate: Thu May 10 16:54:38 2007 -0500
Committer:  Steven Whitehouse <[EMAIL PROTECTED]>
CommitDate: Mon Jul 9 08:22:14 2007 +0100

[GFS2] Kernel changes to support new gfs2_grow command (part 2)

To avoid code redundancy, I separated out the operational "guts" into
a new function called read_rindex_entry.  Then I made two functions:
the closer-to-original gfs2_ri_update (without the special condition
checks) and gfs2_ri_update_special that's designed with that condition
in mind.  (I don't like the name, but if you have a suggestion, I'm
all ears).

Oh, and there's an added benefit:  we don't need all the ugly gotos
anymore.  ;)

This patch has been tested with gfs2_fsck_hellfire (which runs for
three and a half hours, btw).

Signed-off-By: Bob Peterson <[EMAIL PROTECTED]>
Signed-off-by: Steven Whitehouse <[EMAIL PROTECTED]>
---
 fs/gfs2/ops_address.c |3 +-
 fs/gfs2/rgrp.c|  139 -
 2 files changed, 93 insertions(+), 49 deletions(-)

diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c
index 846c0ff..e0b4e8c 100644
--- a/fs/gfs2/ops_address.c
+++ b/fs/gfs2/ops_address.c
@@ -469,7 +469,8 @@ static void adjust_fs_space(struct inode *inode)
else
new_free = 0;
spin_unlock(&sdp->sd_statfs_spin);
-   fs_warn(sdp, "File system extended by %llu blocks.\n", new_free);
+   fs_warn(sdp, "File system extended by %llu blocks.\n",
+   (unsigned long long)new_free);
gfs2_statfs_change(sdp, new_free, new_free, 0);
 }
 
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index e857f40..48a6461 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -463,9 +463,62 @@ u64 gfs2_ri_total(struct gfs2_sbd *sdp)
 }
 
 /**
- * gfs2_ri_update - Pull in a new resource index from the disk
+ * read_rindex_entry - Pull in a new resource index entry from the disk
  * @gl: The glock covering the rindex inode
  *
+ * Returns: 0 on success, error code otherwise
+ */
+
+static int read_rindex_entry(struct gfs2_inode *ip,
+struct file_ra_state *ra_state)
+{
+   struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
+   loff_t pos = sdp->sd_rgrps * sizeof(struct gfs2_rindex);
+   char buf[sizeof(struct gfs2_rindex)];
+   int error;
+   struct gfs2_rgrpd *rgd;
+
+   error = gfs2_internal_read(ip, ra_state, buf, &pos,
+  sizeof(struct gfs2_rindex));
+   if (!error)
+   return 0;
+   if (error != sizeof(struct gfs2_rindex)) {
+   if (error > 0)
+   error = -EIO;
+   return error;
+   }
+
+   rgd = kzalloc(sizeof(struct gfs2_rgrpd), GFP_NOFS);
+   error = -ENOMEM;
+   if (!rgd)
+   return error;
+
+   mutex_init(&rgd->rd_mutex);
+   lops_init_le(&rgd->rd_le, &gfs2_rg_lops);
+   rgd->rd_sbd = sdp;
+
+   list_add_tail(&rgd->rd_list, &sdp->sd_rindex_list);
+   list_add_tail(&rgd->rd_list_mru, &sdp->sd_rindex_mru_list);
+
+   gfs2_rindex_in(&rgd->rd_ri, buf);
+   error = compute_bitstructs(rgd);
+   if (error)
+   return error;
+
+   error = gfs2_glock_get(sdp, rgd->rd_ri.ri_addr,
+  &gfs2_rgrp_glops, CREATE, &rgd->rd_gl);
+   if (error)
+   return error;
+
+   rgd->rd_gl->gl_object = rgd;
+   rgd->rd_rg_vn = rgd->rd_gl->gl_vn - 1;
+   return error;
+}
+
+/**
+ * gfs2_ri_update - Pull in a new resource index from the disk
+ * @ip: pointer to the rindex inode
+ *
  * Returns: 0 on successful update, error code otherwise
  */
 
@@ -473,18 +526,11 @@ static int gfs2_ri_update(struct gfs2_inode *ip)
 {
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct inode *inode = &ip->i_inode;
-   struct gfs2_rgrpd *rgd;
-   char buf[sizeof(struct gfs2_rindex)];
struct file_ra_state ra_state;
u64 junk = ip->i_di.di_size;
int error;
 
-   /* If someone is holding the rindex file with a glock, they must
-  be updating it, in which case we may have partial entries.
-  In this case, we ignore the partials. */
-   if (!gfs2_glock_is_held_excl(ip->i_gl) &&
-   !gfs2_glock_is_held_shrd(ip->i_gl) &&
-   do_div(junk, sizeof(struct gfs2_rindex))) {
+   if (do_div(junk, sizeof(struct gfs2_rindex))) {
gfs2_consist