diff options
author | Steven Whitehouse <swhiteho@redhat.com> | 2006-03-29 19:02:15 -0500 |
---|---|---|
committer | Steven Whitehouse <swhiteho@redhat.com> | 2006-03-29 19:02:15 -0500 |
commit | e90deff5336ac500c65f873484c326cfa8a9d379 (patch) | |
tree | 7a9b0325148e72542b36fb8dd3dfc749ae1cf696 | |
parent | d0dc80dbafb5c10ad2084831a61bbf945484a139 (diff) | |
download | linux-e90deff5336ac500c65f873484c326cfa8a9d379.tar.bz2 |
[GFS2] Fix bug in directory expansion code
We didn't properly check that leaf splitting was allowed. We do
now.
Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
-rw-r--r-- | fs/gfs2/dir.c | 23 |
1 files changed, 14 insertions, 9 deletions
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index ba3438553f33..9f17e7d05af1 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c @@ -940,10 +940,15 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name) /* Get the old leaf block */ error = get_leaf(dip, leaf_no, &obh); if (error) - goto fail; + return error; - gfs2_trans_add_bh(dip->i_gl, obh, 1); oleaf = (struct gfs2_leaf *)obh->b_data; + if (dip->i_di.di_depth == be16_to_cpu(oleaf->lf_depth)) { + brelse(obh); + return 1; /* can't split */ + } + + gfs2_trans_add_bh(dip->i_gl, obh, 1); nleaf = new_leaf(inode, &nbh, be16_to_cpu(oleaf->lf_depth) + 1); if (!nleaf) { @@ -956,6 +961,7 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name) len = 1 << (dip->i_di.di_depth - be16_to_cpu(oleaf->lf_depth)); half_len = len >> 1; if (!half_len) { + printk(KERN_WARNING "di_depth %u lf_depth %u index %u\n", dip->i_di.di_depth, be16_to_cpu(oleaf->lf_depth), index); gfs2_consist_inode(dip); error = -EIO; goto fail_brelse; @@ -1038,13 +1044,11 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name) return error; - fail_lpfree: +fail_lpfree: kfree(lp); - fail_brelse: +fail_brelse: brelse(obh); - - fail: brelse(nbh); return error; } @@ -1570,16 +1574,17 @@ int gfs2_dir_add(struct inode *inode, const struct qstr *name, error = dir_split_leaf(inode, name); if (error == 0) continue; - if (error != -ENOSPC) + if (error < 0) break; if (ip->i_di.di_depth < GFS2_DIR_MAX_DEPTH) { error = dir_double_exhash(ip); if (error) break; error = dir_split_leaf(inode, name); - if (error) + if (error < 0) break; - continue; + if (error == 0) + continue; } error = dir_new_leaf(inode, name); if (!error) |