From mboxrd@z Thu Jan 1 00:00:00 1970 From: Robert Peterson Date: Mon, 16 Apr 2007 10:37:25 -0500 Subject: [Cluster-devel] [PATCH] bz 235430: GFS2: kernel changes needed to support new gfs2_grow command Message-ID: <46239835.5070507@redhat.com> List-Id: To: cluster-devel.redhat.com MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit This patch addresses Bugzilla Bug 235430: GFS2: kernel changes needed to support new gfs2_grow command. This is against the -nmw git tree. This is what it does, in patch order: 1. First, in gfs2_statfs, it calls function check_rindex_version, which has been broken out of gfs2_rindex_hold. Without this, the "df" always gives the old statfs information until gfs2_rindex_hold is called next, which can happen, for instance, when a new file is created. 2. Function ri_update now keeps a total of the file system allocation information (Why not, as long as it's going through them all). 3. There's a new function, resync_statfs that checks for the statfs data being incorrect and adjusts it as a "local statfs change". This ensures it will get processed the next time the daemon goes to resync the statfs data. 4. As I said in point 1, the check_rindex_version has been broken out of gfs2_rindex_hold so it may be called from gfs2_statfs as well as gfs2_rindex_hold. The patch seems to work properly, at least on the few tests I did. Signed-off-by: Bob Peterson (rpeterso at redhat.com) ------ fs/gfs2/ops_super.c | 3 ++ fs/gfs2/rgrp.c | 80 ++++++++++++++++++++++++++++++++++++++++++--------- fs/gfs2/rgrp.h | 1 + 3 files changed, 70 insertions(+), 14 deletions(-) diff --git a/fs/gfs2/ops_super.c b/fs/gfs2/ops_super.c index 485ce3d..8861ae0 100644 --- a/fs/gfs2/ops_super.c +++ b/fs/gfs2/ops_super.c @@ -222,6 +222,9 @@ static int gfs2_statfs(struct dentry *dentry, struct kstatfs *buf) struct gfs2_statfs_change_host sc; int error; + error = check_rindex_version(sdp); + if (error) + return error; if (gfs2_tune_get(sdp, gt_statfs_slow)) error = gfs2_statfs_slow(sdp, &sc); else diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index 1727f50..b4c33a5 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c @@ -437,7 +437,8 @@ static int compute_bitstructs(struct gfs2_rgrpd *rgd) * Returns: 0 on successful update, error code otherwise */ -static int gfs2_ri_update(struct gfs2_inode *ip) +static int gfs2_ri_update(struct gfs2_inode *ip, + struct gfs2_statfs_change_host *sc) { struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); struct inode *inode = &ip->i_inode; @@ -454,6 +455,7 @@ static int gfs2_ri_update(struct gfs2_inode *ip) clear_rgrpdi(sdp); + memset(sc, 0, sizeof(struct gfs2_statfs_change_host)); file_ra_state_init(&ra_state, inode->i_mapping); for (sdp->sd_rgrps = 0;; sdp->sd_rgrps++) { loff_t pos = sdp->sd_rgrps * sizeof(struct gfs2_rindex); @@ -491,6 +493,10 @@ static int gfs2_ri_update(struct gfs2_inode *ip) rgd->rd_gl->gl_object = rgd; rgd->rd_rg_vn = rgd->rd_gl->gl_vn - 1; + + sc->sc_total += rgd->rd_ri.ri_data; + sc->sc_free += rgd->rd_rg.rg_free; + sc->sc_dinodes += rgd->rd_rg.rg_dinodes; } sdp->sd_rindex_vn = ip->i_gl->gl_vn; @@ -502,6 +508,61 @@ fail: } /** + * resync_statfs - Check if the statfs file has bad info and if so, adjust it + * based on what was totalled from the rindex, + * then let the daemon fix the file when it's scheduled next. + */ +static void resync_statfs(struct gfs2_sbd *sdp, + struct gfs2_statfs_change_host *sc) +{ + struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master; + struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local; + + if (sc->sc_total != m_sc->sc_total + l_sc->sc_total || + sc->sc_free != m_sc->sc_free + l_sc->sc_free || + sc->sc_dinodes != m_sc->sc_dinodes + l_sc->sc_dinodes) { + spin_lock(&sdp->sd_statfs_spin); + l_sc->sc_total = sc->sc_total - m_sc->sc_total; + l_sc->sc_free = sc->sc_free - m_sc->sc_free; + l_sc->sc_dinodes = sc->sc_dinodes - m_sc->sc_dinodes; + spin_unlock(&sdp->sd_statfs_spin); + } +} + +/** + * check_rindex_version - Check the rindex version number and resync + * if necessary. + * @sdp: The GFS2 superblock + * + * This makes sure that we're using the latest copy of the resource index + * special file, which might have been updated if someone expanded the + * filesystem (via gfs2_grow utility), which adds new resource groups. + * + */ + +int check_rindex_version(struct gfs2_sbd *sdp) +{ + struct gfs2_inode *ip = GFS2_I(sdp->sd_rindex); + struct gfs2_glock *gl = ip->i_gl; + int error = 0; + + /* Read new copy from disk if we don't have the latest */ + if (sdp->sd_rindex_vn != gl->gl_vn) { + struct gfs2_statfs_change_host sc; + + mutex_lock(&sdp->sd_rindex_mutex); + if (sdp->sd_rindex_vn != gl->gl_vn) { + error = gfs2_ri_update(ip, &sc); + } + mutex_unlock(&sdp->sd_rindex_mutex); + /* Check consistency and sync statfs. */ + resync_statfs(sdp, &sc); + } + + return error; +} + +/** * gfs2_rindex_hold - Grab a lock on the rindex * @sdp: The GFS2 superblock * @ri_gh: the glock holder @@ -526,20 +587,11 @@ int gfs2_rindex_hold(struct gfs2_sbd *sdp, struct gfs2_holder *ri_gh) int error; error = gfs2_glock_nq_init(gl, LM_ST_SHARED, 0, ri_gh); - if (error) - return error; - - /* Read new copy from disk if we don't have the latest */ - if (sdp->sd_rindex_vn != gl->gl_vn) { - mutex_lock(&sdp->sd_rindex_mutex); - if (sdp->sd_rindex_vn != gl->gl_vn) { - error = gfs2_ri_update(ip); - if (error) - gfs2_glock_dq_uninit(ri_gh); - } - mutex_unlock(&sdp->sd_rindex_mutex); + if (!error) { + error = check_rindex_version(sdp); + if (error) + gfs2_glock_dq_uninit(ri_gh); } - return error; } diff --git a/fs/gfs2/rgrp.h b/fs/gfs2/rgrp.h index b01e0cf..3978dae 100644 --- a/fs/gfs2/rgrp.h +++ b/fs/gfs2/rgrp.h @@ -21,6 +21,7 @@ struct gfs2_rgrpd *gfs2_rgrpd_get_first(struct gfs2_sbd *sdp); struct gfs2_rgrpd *gfs2_rgrpd_get_next(struct gfs2_rgrpd *rgd); void gfs2_clear_rgrpd(struct gfs2_sbd *sdp); +int check_rindex_version(struct gfs2_sbd *sdp); int gfs2_rindex_hold(struct gfs2_sbd *sdp, struct gfs2_holder *ri_gh); int gfs2_rgrp_bh_get(struct gfs2_rgrpd *rgd);