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 /fs/gfs2/dir.c | |
parent | d0dc80dbafb5c10ad2084831a61bbf945484a139 (diff) |
[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>
Diffstat (limited to 'fs/gfs2/dir.c')
-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) | |||
940 | /* Get the old leaf block */ | 940 | /* Get the old leaf block */ |
941 | error = get_leaf(dip, leaf_no, &obh); | 941 | error = get_leaf(dip, leaf_no, &obh); |
942 | if (error) | 942 | if (error) |
943 | goto fail; | 943 | return error; |
944 | 944 | ||
945 | gfs2_trans_add_bh(dip->i_gl, obh, 1); | ||
946 | oleaf = (struct gfs2_leaf *)obh->b_data; | 945 | oleaf = (struct gfs2_leaf *)obh->b_data; |
946 | if (dip->i_di.di_depth == be16_to_cpu(oleaf->lf_depth)) { | ||
947 | brelse(obh); | ||
948 | return 1; /* can't split */ | ||
949 | } | ||
950 | |||
951 | gfs2_trans_add_bh(dip->i_gl, obh, 1); | ||
947 | 952 | ||
948 | nleaf = new_leaf(inode, &nbh, be16_to_cpu(oleaf->lf_depth) + 1); | 953 | nleaf = new_leaf(inode, &nbh, be16_to_cpu(oleaf->lf_depth) + 1); |
949 | if (!nleaf) { | 954 | if (!nleaf) { |
@@ -956,6 +961,7 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name) | |||
956 | len = 1 << (dip->i_di.di_depth - be16_to_cpu(oleaf->lf_depth)); | 961 | len = 1 << (dip->i_di.di_depth - be16_to_cpu(oleaf->lf_depth)); |
957 | half_len = len >> 1; | 962 | half_len = len >> 1; |
958 | if (!half_len) { | 963 | if (!half_len) { |
964 | printk(KERN_WARNING "di_depth %u lf_depth %u index %u\n", dip->i_di.di_depth, be16_to_cpu(oleaf->lf_depth), index); | ||
959 | gfs2_consist_inode(dip); | 965 | gfs2_consist_inode(dip); |
960 | error = -EIO; | 966 | error = -EIO; |
961 | goto fail_brelse; | 967 | goto fail_brelse; |
@@ -1038,13 +1044,11 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name) | |||
1038 | 1044 | ||
1039 | return error; | 1045 | return error; |
1040 | 1046 | ||
1041 | fail_lpfree: | 1047 | fail_lpfree: |
1042 | kfree(lp); | 1048 | kfree(lp); |
1043 | 1049 | ||
1044 | fail_brelse: | 1050 | fail_brelse: |
1045 | brelse(obh); | 1051 | brelse(obh); |
1046 | |||
1047 | fail: | ||
1048 | brelse(nbh); | 1052 | brelse(nbh); |
1049 | return error; | 1053 | return error; |
1050 | } | 1054 | } |
@@ -1570,16 +1574,17 @@ int gfs2_dir_add(struct inode *inode, const struct qstr *name, | |||
1570 | error = dir_split_leaf(inode, name); | 1574 | error = dir_split_leaf(inode, name); |
1571 | if (error == 0) | 1575 | if (error == 0) |
1572 | continue; | 1576 | continue; |
1573 | if (error != -ENOSPC) | 1577 | if (error < 0) |
1574 | break; | 1578 | break; |
1575 | if (ip->i_di.di_depth < GFS2_DIR_MAX_DEPTH) { | 1579 | if (ip->i_di.di_depth < GFS2_DIR_MAX_DEPTH) { |
1576 | error = dir_double_exhash(ip); | 1580 | error = dir_double_exhash(ip); |
1577 | if (error) | 1581 | if (error) |
1578 | break; | 1582 | break; |
1579 | error = dir_split_leaf(inode, name); | 1583 | error = dir_split_leaf(inode, name); |
1580 | if (error) | 1584 | if (error < 0) |
1581 | break; | 1585 | break; |
1582 | continue; | 1586 | if (error == 0) |
1587 | continue; | ||
1583 | } | 1588 | } |
1584 | error = dir_new_leaf(inode, name); | 1589 | error = dir_new_leaf(inode, name); |
1585 | if (!error) | 1590 | if (!error) |