Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 316740
b: refs/heads/master
c: 90306c4
h: refs/heads/master
v: v3
  • Loading branch information
Benjamin Marzinski authored and Steven Whitehouse committed Jun 8, 2012
1 parent de0df90 commit 777ccef
Show file tree
Hide file tree
Showing 6 changed files with 164 additions and 10 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: ba1ddcb6ca0c46edd275790d1e4e2cfd6219ce19
refs/heads/master: 90306c41dc3d8e5f12ecd0193dae99e0e7f6e896
1 change: 1 addition & 0 deletions trunk/fs/gfs2/glock.c
Original file line number Diff line number Diff line change
Expand Up @@ -769,6 +769,7 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
gl->gl_stats.stats[GFS2_LKS_DCOUNT] = 0;
gl->gl_stats.stats[GFS2_LKS_QCOUNT] = 0;
memset(&gl->gl_lksb, 0, sizeof(struct dlm_lksb));
memset(gl->gl_lvb, 0, 32 * sizeof(char));
gl->gl_lksb.sb_lvbptr = gl->gl_lvb;
gl->gl_tchange = jiffies;
gl->gl_object = NULL;
Expand Down
2 changes: 2 additions & 0 deletions trunk/fs/gfs2/incore.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ struct gfs2_rgrpd {
u64 rd_igeneration;
struct gfs2_bitmap *rd_bits;
struct gfs2_sbd *rd_sbd;
struct gfs2_rgrp_lvb *rd_rgl;
u32 rd_last_alloc;
u32 rd_flags;
#define GFS2_RDF_CHECK 0x10000000 /* check for unlinked inodes */
Expand Down Expand Up @@ -470,6 +471,7 @@ struct gfs2_args {
unsigned int ar_discard:1; /* discard requests */
unsigned int ar_errors:2; /* errors=withdraw | panic */
unsigned int ar_nobarrier:1; /* do not send barriers */
unsigned int ar_rgrplvb:1; /* use lvbs for rgrp info */
int ar_commit; /* Commit interval */
int ar_statfs_quantum; /* The fast statfs interval */
int ar_quota_quantum; /* The quota interval */
Expand Down
147 changes: 138 additions & 9 deletions trunk/fs/gfs2/rgrp.c
Original file line number Diff line number Diff line change
Expand Up @@ -660,6 +660,7 @@ static int read_rindex_entry(struct gfs2_inode *ip)
goto fail;

rgd->rd_gl->gl_object = rgd;
rgd->rd_rgl = (struct gfs2_rgrp_lvb *)rgd->rd_gl->gl_lvb;
rgd->rd_flags &= ~GFS2_RDF_UPTODATE;
if (rgd->rd_data > sdp->sd_max_rg_data)
sdp->sd_max_rg_data = rgd->rd_data;
Expand Down Expand Up @@ -769,26 +770,84 @@ static void gfs2_rgrp_out(struct gfs2_rgrpd *rgd, void *buf)
memset(&str->rg_reserved, 0, sizeof(str->rg_reserved));
}

static int gfs2_rgrp_lvb_valid(struct gfs2_rgrpd *rgd)
{
struct gfs2_rgrp_lvb *rgl = rgd->rd_rgl;
struct gfs2_rgrp *str = (struct gfs2_rgrp *)rgd->rd_bits[0].bi_bh->b_data;

if (rgl->rl_flags != str->rg_flags || rgl->rl_free != str->rg_free ||
rgl->rl_dinodes != str->rg_dinodes ||
rgl->rl_igeneration != str->rg_igeneration)
return 0;
return 1;
}

static void gfs2_rgrp_ondisk2lvb(struct gfs2_rgrp_lvb *rgl, const void *buf)
{
const struct gfs2_rgrp *str = buf;

rgl->rl_magic = cpu_to_be32(GFS2_MAGIC);
rgl->rl_flags = str->rg_flags;
rgl->rl_free = str->rg_free;
rgl->rl_dinodes = str->rg_dinodes;
rgl->rl_igeneration = str->rg_igeneration;
rgl->__pad = 0UL;
}

static void update_rgrp_lvb_unlinked(struct gfs2_rgrpd *rgd, u32 change)
{
struct gfs2_rgrp_lvb *rgl = rgd->rd_rgl;
u32 unlinked = be32_to_cpu(rgl->rl_unlinked) + change;
rgl->rl_unlinked = cpu_to_be32(unlinked);
}

static u32 count_unlinked(struct gfs2_rgrpd *rgd)
{
struct gfs2_bitmap *bi;
const u32 length = rgd->rd_length;
const u8 *buffer = NULL;
u32 i, goal, count = 0;

for (i = 0, bi = rgd->rd_bits; i < length; i++, bi++) {
goal = 0;
buffer = bi->bi_bh->b_data + bi->bi_offset;
WARN_ON(!buffer_uptodate(bi->bi_bh));
while (goal < bi->bi_len * GFS2_NBBY) {
goal = gfs2_bitfit(buffer, bi->bi_len, goal,
GFS2_BLKST_UNLINKED);
if (goal == BFITNOENT)
break;
count++;
goal++;
}
}

return count;
}


/**
* gfs2_rgrp_go_lock - Read in a RG's header and bitmaps
* @gh: The glock holder for the resource group
* gfs2_rgrp_bh_get - Read in a RG's header and bitmaps
* @rgd: the struct gfs2_rgrpd describing the RG to read in
*
* Read in all of a Resource Group's header and bitmap blocks.
* Caller must eventually call gfs2_rgrp_relse() to free the bitmaps.
*
* Returns: errno
*/

int gfs2_rgrp_go_lock(struct gfs2_holder *gh)
int gfs2_rgrp_bh_get(struct gfs2_rgrpd *rgd)
{
struct gfs2_rgrpd *rgd = gh->gh_gl->gl_object;
struct gfs2_sbd *sdp = rgd->rd_sbd;
struct gfs2_glock *gl = rgd->rd_gl;
unsigned int length = rgd->rd_length;
struct gfs2_bitmap *bi;
unsigned int x, y;
int error;

if (rgd->rd_bits[0].bi_bh != NULL)
return 0;

for (x = 0; x < length; x++) {
bi = rgd->rd_bits + x;
error = gfs2_meta_read(gl, rgd->rd_addr + x, 0, &bi->bi_bh);
Expand All @@ -815,7 +874,20 @@ int gfs2_rgrp_go_lock(struct gfs2_holder *gh)
rgd->rd_flags |= (GFS2_RDF_UPTODATE | GFS2_RDF_CHECK);
rgd->rd_free_clone = rgd->rd_free;
}

if (be32_to_cpu(GFS2_MAGIC) != rgd->rd_rgl->rl_magic) {
rgd->rd_rgl->rl_unlinked = cpu_to_be32(count_unlinked(rgd));
gfs2_rgrp_ondisk2lvb(rgd->rd_rgl,
rgd->rd_bits[0].bi_bh->b_data);
}
else if (sdp->sd_args.ar_rgrplvb) {
if (!gfs2_rgrp_lvb_valid(rgd)){
gfs2_consist_rgrpd(rgd);
error = -EIO;
goto fail;
}
if (rgd->rd_rgl->rl_unlinked == 0)
rgd->rd_flags &= ~GFS2_RDF_CHECK;
}
return 0;

fail:
Expand All @@ -829,6 +901,39 @@ int gfs2_rgrp_go_lock(struct gfs2_holder *gh)
return error;
}

int update_rgrp_lvb(struct gfs2_rgrpd *rgd)
{
u32 rl_flags;

if (rgd->rd_flags & GFS2_RDF_UPTODATE)
return 0;

if (be32_to_cpu(GFS2_MAGIC) != rgd->rd_rgl->rl_magic)
return gfs2_rgrp_bh_get(rgd);

rl_flags = be32_to_cpu(rgd->rd_rgl->rl_flags);
rl_flags &= ~GFS2_RDF_MASK;
rgd->rd_flags &= GFS2_RDF_MASK;
rgd->rd_flags |= (rl_flags | GFS2_RDF_UPTODATE | GFS2_RDF_CHECK);
if (rgd->rd_rgl->rl_unlinked == 0)
rgd->rd_flags &= ~GFS2_RDF_CHECK;
rgd->rd_free = be32_to_cpu(rgd->rd_rgl->rl_free);
rgd->rd_free_clone = rgd->rd_free;
rgd->rd_dinodes = be32_to_cpu(rgd->rd_rgl->rl_dinodes);
rgd->rd_igeneration = be64_to_cpu(rgd->rd_rgl->rl_igeneration);
return 0;
}

int gfs2_rgrp_go_lock(struct gfs2_holder *gh)
{
struct gfs2_rgrpd *rgd = gh->gh_gl->gl_object;
struct gfs2_sbd *sdp = rgd->rd_sbd;

if (gh->gh_flags & GL_SKIP && sdp->sd_args.ar_rgrplvb)
return 0;
return gfs2_rgrp_bh_get((struct gfs2_rgrpd *)gh->gh_gl->gl_object);
}

/**
* gfs2_rgrp_go_unlock - Release RG bitmaps read in with gfs2_rgrp_bh_get()
* @gh: The glock holder for the resource group
Expand All @@ -842,8 +947,10 @@ void gfs2_rgrp_go_unlock(struct gfs2_holder *gh)

for (x = 0; x < length; x++) {
struct gfs2_bitmap *bi = rgd->rd_bits + x;
brelse(bi->bi_bh);
bi->bi_bh = NULL;
if (bi->bi_bh) {
brelse(bi->bi_bh);
bi->bi_bh = NULL;
}
}

}
Expand Down Expand Up @@ -987,6 +1094,7 @@ int gfs2_fitrim(struct file *filp, void __user *argp)
rgd->rd_flags |= GFS2_RGF_TRIMMED;
gfs2_trans_add_bh(rgd->rd_gl, bh, 1);
gfs2_rgrp_out(rgd, bh->b_data);
gfs2_rgrp_ondisk2lvb(rgd->rd_rgl, bh->b_data);
gfs2_trans_end(sdp);
}
}
Expand Down Expand Up @@ -1116,6 +1224,9 @@ static int get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked)
int error, rg_locked, flags = LM_FLAG_TRY;
int loops = 0;

if (sdp->sd_args.ar_rgrplvb)
flags |= GL_SKIP;

if (ip->i_rgd && rgrp_contains_block(ip->i_rgd, ip->i_goal))
rgd = begin = ip->i_rgd;
else
Expand All @@ -1133,22 +1244,34 @@ static int get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked)
} else {
error = gfs2_glock_nq_init(rgd->rd_gl, LM_ST_EXCLUSIVE,
flags, &rs->rs_rgd_gh);
if (!error && sdp->sd_args.ar_rgrplvb) {
error = update_rgrp_lvb(rgd);
if (error) {
gfs2_glock_dq_uninit(&rs->rs_rgd_gh);
return error;
}
}
}
switch (error) {
case 0:
if (try_rgrp_fit(rgd, ip)) {
if (sdp->sd_args.ar_rgrplvb)
gfs2_rgrp_bh_get(rgd);
ip->i_rgd = rgd;
return 0;
}
if (rgd->rd_flags & GFS2_RDF_CHECK)
if (rgd->rd_flags & GFS2_RDF_CHECK) {
if (sdp->sd_args.ar_rgrplvb)
gfs2_rgrp_bh_get(rgd);
try_rgrp_unlink(rgd, last_unlinked, ip->i_no_addr);
}
if (!rg_locked)
gfs2_glock_dq_uninit(&rs->rs_rgd_gh);
/* fall through */
case GLR_TRYFAILED:
rgd = gfs2_rgrpd_get_next(rgd);
if (rgd == begin) {
flags = 0;
flags &= ~LM_FLAG_TRY;
loops++;
}
break;
Expand Down Expand Up @@ -1529,6 +1652,7 @@ int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *nblocks,

gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1);
gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);
gfs2_rgrp_ondisk2lvb(rgd->rd_rgl, rgd->rd_bits[0].bi_bh->b_data);

gfs2_statfs_change(sdp, 0, -(s64)*nblocks, dinode ? 1 : 0);
if (dinode)
Expand Down Expand Up @@ -1575,6 +1699,7 @@ void __gfs2_free_blocks(struct gfs2_inode *ip, u64 bstart, u32 blen, int meta)
rgd->rd_flags &= ~GFS2_RGF_TRIMMED;
gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1);
gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);
gfs2_rgrp_ondisk2lvb(rgd->rd_rgl, rgd->rd_bits[0].bi_bh->b_data);

/* Directories keep their data in the metadata address space */
if (meta || ip->i_depth)
Expand Down Expand Up @@ -1611,6 +1736,8 @@ void gfs2_unlink_di(struct inode *inode)
trace_gfs2_block_alloc(ip, rgd, blkno, 1, GFS2_BLKST_UNLINKED);
gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1);
gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);
gfs2_rgrp_ondisk2lvb(rgd->rd_rgl, rgd->rd_bits[0].bi_bh->b_data);
update_rgrp_lvb_unlinked(rgd, 1);
}

static void gfs2_free_uninit_di(struct gfs2_rgrpd *rgd, u64 blkno)
Expand All @@ -1630,6 +1757,8 @@ static void gfs2_free_uninit_di(struct gfs2_rgrpd *rgd, u64 blkno)

gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1);
gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);
gfs2_rgrp_ondisk2lvb(rgd->rd_rgl, rgd->rd_bits[0].bi_bh->b_data);
update_rgrp_lvb_unlinked(rgd, -1);

gfs2_statfs_change(sdp, 0, +1, -1);
}
Expand Down
12 changes: 12 additions & 0 deletions trunk/fs/gfs2/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ enum {
Opt_quota_quantum,
Opt_barrier,
Opt_nobarrier,
Opt_rgrplvb,
Opt_norgrplvb,
Opt_error,
};

Expand Down Expand Up @@ -115,6 +117,8 @@ static const match_table_t tokens = {
{Opt_quota_quantum, "quota_quantum=%d"},
{Opt_barrier, "barrier"},
{Opt_nobarrier, "nobarrier"},
{Opt_rgrplvb, "rgrplvb"},
{Opt_norgrplvb, "norgrplvb"},
{Opt_error, NULL}
};

Expand Down Expand Up @@ -267,6 +271,12 @@ int gfs2_mount_args(struct gfs2_args *args, char *options)
case Opt_nobarrier:
args->ar_nobarrier = 1;
break;
case Opt_rgrplvb:
args->ar_rgrplvb = 1;
break;
case Opt_norgrplvb:
args->ar_rgrplvb = 0;
break;
case Opt_error:
default:
printk(KERN_WARNING "GFS2: invalid mount option: %s\n", o);
Expand Down Expand Up @@ -1379,6 +1389,8 @@ static int gfs2_show_options(struct seq_file *s, struct dentry *root)
seq_printf(s, ",nobarrier");
if (test_bit(SDF_DEMOTE, &sdp->sd_flags))
seq_printf(s, ",demote_interface_used");
if (args->ar_rgrplvb)
seq_printf(s, ",rgrplvb");
return 0;
}

Expand Down
10 changes: 10 additions & 0 deletions trunk/include/linux/gfs2_ondisk.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,16 @@ struct gfs2_rindex {
#define GFS2_RGF_NOALLOC 0x00000008
#define GFS2_RGF_TRIMMED 0x00000010

struct gfs2_rgrp_lvb {
__be32 rl_magic;
__be32 rl_flags;
__be32 rl_free;
__be32 rl_dinodes;
__be64 rl_igeneration;
__be32 rl_unlinked;
__be32 __pad;
};

struct gfs2_rgrp {
struct gfs2_meta_header rg_header;

Expand Down

0 comments on commit 777ccef

Please sign in to comment.