summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2006-03-29 19:02:15 -0500
committerSteven Whitehouse <swhiteho@redhat.com>2006-03-29 19:02:15 -0500
commite90deff5336ac500c65f873484c326cfa8a9d379 (patch)
tree7a9b0325148e72542b36fb8dd3dfc749ae1cf696
parentd0dc80dbafb5c10ad2084831a61bbf945484a139 (diff)
downloadlinux-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.c23
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)