diff options
-rw-r--r-- | fs/gfs2/export.c | 36 | ||||
-rw-r--r-- | fs/gfs2/rgrp.c | 42 | ||||
-rw-r--r-- | fs/gfs2/rgrp.h | 4 | ||||
-rw-r--r-- | fs/gfs2/super.c | 4 |
4 files changed, 51 insertions, 35 deletions
diff --git a/fs/gfs2/export.c b/fs/gfs2/export.c index 9200ef221716..d15876e9aa26 100644 --- a/fs/gfs2/export.c +++ b/fs/gfs2/export.c | |||
@@ -143,17 +143,14 @@ static struct dentry *gfs2_get_parent(struct dentry *child) | |||
143 | } | 143 | } |
144 | 144 | ||
145 | static struct dentry *gfs2_get_dentry(struct super_block *sb, | 145 | static struct dentry *gfs2_get_dentry(struct super_block *sb, |
146 | struct gfs2_inum_host *inum) | 146 | struct gfs2_inum_host *inum) |
147 | { | 147 | { |
148 | struct gfs2_sbd *sdp = sb->s_fs_info; | 148 | struct gfs2_sbd *sdp = sb->s_fs_info; |
149 | struct gfs2_holder i_gh, ri_gh, rgd_gh; | 149 | struct gfs2_holder i_gh; |
150 | struct gfs2_rgrpd *rgd; | ||
151 | struct inode *inode; | 150 | struct inode *inode; |
152 | struct dentry *dentry; | 151 | struct dentry *dentry; |
153 | int error; | 152 | int error; |
154 | 153 | ||
155 | /* System files? */ | ||
156 | |||
157 | inode = gfs2_ilookup(sb, inum->no_addr); | 154 | inode = gfs2_ilookup(sb, inum->no_addr); |
158 | if (inode) { | 155 | if (inode) { |
159 | if (GFS2_I(inode)->i_no_formal_ino != inum->no_formal_ino) { | 156 | if (GFS2_I(inode)->i_no_formal_ino != inum->no_formal_ino) { |
@@ -168,29 +165,11 @@ static struct dentry *gfs2_get_dentry(struct super_block *sb, | |||
168 | if (error) | 165 | if (error) |
169 | return ERR_PTR(error); | 166 | return ERR_PTR(error); |
170 | 167 | ||
171 | error = gfs2_rindex_hold(sdp, &ri_gh); | 168 | error = gfs2_check_blk_type(sdp, inum->no_addr, GFS2_BLKST_DINODE); |
172 | if (error) | 169 | if (error) |
173 | goto fail; | 170 | goto fail; |
174 | 171 | ||
175 | error = -EINVAL; | 172 | inode = gfs2_inode_lookup(sb, DT_UNKNOWN, inum->no_addr, 0, 0); |
176 | rgd = gfs2_blk2rgrpd(sdp, inum->no_addr); | ||
177 | if (!rgd) | ||
178 | goto fail_rindex; | ||
179 | |||
180 | error = gfs2_glock_nq_init(rgd->rd_gl, LM_ST_SHARED, 0, &rgd_gh); | ||
181 | if (error) | ||
182 | goto fail_rindex; | ||
183 | |||
184 | error = -ESTALE; | ||
185 | if (gfs2_get_block_type(rgd, inum->no_addr) != GFS2_BLKST_DINODE) | ||
186 | goto fail_rgd; | ||
187 | |||
188 | gfs2_glock_dq_uninit(&rgd_gh); | ||
189 | gfs2_glock_dq_uninit(&ri_gh); | ||
190 | |||
191 | inode = gfs2_inode_lookup(sb, DT_UNKNOWN, | ||
192 | inum->no_addr, | ||
193 | 0, 0); | ||
194 | if (IS_ERR(inode)) { | 173 | if (IS_ERR(inode)) { |
195 | error = PTR_ERR(inode); | 174 | error = PTR_ERR(inode); |
196 | goto fail; | 175 | goto fail; |
@@ -224,13 +203,6 @@ out_inode: | |||
224 | if (!IS_ERR(dentry)) | 203 | if (!IS_ERR(dentry)) |
225 | dentry->d_op = &gfs2_dops; | 204 | dentry->d_op = &gfs2_dops; |
226 | return dentry; | 205 | return dentry; |
227 | |||
228 | fail_rgd: | ||
229 | gfs2_glock_dq_uninit(&rgd_gh); | ||
230 | |||
231 | fail_rindex: | ||
232 | gfs2_glock_dq_uninit(&ri_gh); | ||
233 | |||
234 | fail: | 206 | fail: |
235 | gfs2_glock_dq_uninit(&i_gh); | 207 | gfs2_glock_dq_uninit(&i_gh); |
236 | return ERR_PTR(error); | 208 | return ERR_PTR(error); |
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index 388a61d12fc8..caaa665d4033 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c | |||
@@ -1256,7 +1256,7 @@ void gfs2_inplace_release(struct gfs2_inode *ip) | |||
1256 | * Returns: The block type (GFS2_BLKST_*) | 1256 | * Returns: The block type (GFS2_BLKST_*) |
1257 | */ | 1257 | */ |
1258 | 1258 | ||
1259 | unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, u64 block) | 1259 | static unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, u64 block) |
1260 | { | 1260 | { |
1261 | struct gfs2_bitmap *bi = NULL; | 1261 | struct gfs2_bitmap *bi = NULL; |
1262 | u32 length, rgrp_block, buf_block; | 1262 | u32 length, rgrp_block, buf_block; |
@@ -1694,6 +1694,46 @@ void gfs2_free_di(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip) | |||
1694 | } | 1694 | } |
1695 | 1695 | ||
1696 | /** | 1696 | /** |
1697 | * gfs2_check_blk_type - Check the type of a block | ||
1698 | * @sdp: The superblock | ||
1699 | * @no_addr: The block number to check | ||
1700 | * @type: The block type we are looking for | ||
1701 | * | ||
1702 | * Returns: 0 if the block type matches the expected type | ||
1703 | * -ESTALE if it doesn't match | ||
1704 | * or -ve errno if something went wrong while checking | ||
1705 | */ | ||
1706 | |||
1707 | int gfs2_check_blk_type(struct gfs2_sbd *sdp, u64 no_addr, unsigned int type) | ||
1708 | { | ||
1709 | struct gfs2_rgrpd *rgd; | ||
1710 | struct gfs2_holder ri_gh, rgd_gh; | ||
1711 | int error; | ||
1712 | |||
1713 | error = gfs2_rindex_hold(sdp, &ri_gh); | ||
1714 | if (error) | ||
1715 | goto fail; | ||
1716 | |||
1717 | error = -EINVAL; | ||
1718 | rgd = gfs2_blk2rgrpd(sdp, no_addr); | ||
1719 | if (!rgd) | ||
1720 | goto fail_rindex; | ||
1721 | |||
1722 | error = gfs2_glock_nq_init(rgd->rd_gl, LM_ST_SHARED, 0, &rgd_gh); | ||
1723 | if (error) | ||
1724 | goto fail_rindex; | ||
1725 | |||
1726 | if (gfs2_get_block_type(rgd, no_addr) != type) | ||
1727 | error = -ESTALE; | ||
1728 | |||
1729 | gfs2_glock_dq_uninit(&rgd_gh); | ||
1730 | fail_rindex: | ||
1731 | gfs2_glock_dq_uninit(&ri_gh); | ||
1732 | fail: | ||
1733 | return error; | ||
1734 | } | ||
1735 | |||
1736 | /** | ||
1697 | * gfs2_rlist_add - add a RG to a list of RGs | 1737 | * gfs2_rlist_add - add a RG to a list of RGs |
1698 | * @sdp: the filesystem | 1738 | * @sdp: the filesystem |
1699 | * @rlist: the list of resource groups | 1739 | * @rlist: the list of resource groups |
diff --git a/fs/gfs2/rgrp.h b/fs/gfs2/rgrp.h index a8dedd78245b..b4106ddaaa98 100644 --- a/fs/gfs2/rgrp.h +++ b/fs/gfs2/rgrp.h | |||
@@ -44,8 +44,6 @@ gfs2_inplace_reserve_i((ip), __FILE__, __LINE__) | |||
44 | 44 | ||
45 | extern void gfs2_inplace_release(struct gfs2_inode *ip); | 45 | extern void gfs2_inplace_release(struct gfs2_inode *ip); |
46 | 46 | ||
47 | extern unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, u64 block); | ||
48 | |||
49 | extern int gfs2_alloc_block(struct gfs2_inode *ip, u64 *bn, unsigned int *n); | 47 | extern int gfs2_alloc_block(struct gfs2_inode *ip, u64 *bn, unsigned int *n); |
50 | extern int gfs2_alloc_di(struct gfs2_inode *ip, u64 *bn, u64 *generation); | 48 | extern int gfs2_alloc_di(struct gfs2_inode *ip, u64 *bn, u64 *generation); |
51 | 49 | ||
@@ -53,6 +51,8 @@ extern void gfs2_free_data(struct gfs2_inode *ip, u64 bstart, u32 blen); | |||
53 | extern void gfs2_free_meta(struct gfs2_inode *ip, u64 bstart, u32 blen); | 51 | extern void gfs2_free_meta(struct gfs2_inode *ip, u64 bstart, u32 blen); |
54 | extern void gfs2_free_di(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip); | 52 | extern void gfs2_free_di(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip); |
55 | extern void gfs2_unlink_di(struct inode *inode); | 53 | extern void gfs2_unlink_di(struct inode *inode); |
54 | extern int gfs2_check_blk_type(struct gfs2_sbd *sdp, u64 no_addr, | ||
55 | unsigned int type); | ||
56 | 56 | ||
57 | struct gfs2_rgrp_list { | 57 | struct gfs2_rgrp_list { |
58 | unsigned int rl_rgrps; | 58 | unsigned int rl_rgrps; |
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index d95cf777d244..0ec3ec672de1 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c | |||
@@ -1286,6 +1286,10 @@ static void gfs2_delete_inode(struct inode *inode) | |||
1286 | goto out; | 1286 | goto out; |
1287 | } | 1287 | } |
1288 | 1288 | ||
1289 | error = gfs2_check_blk_type(sdp, ip->i_no_addr, GFS2_BLKST_UNLINKED); | ||
1290 | if (error) | ||
1291 | goto out_truncate; | ||
1292 | |||
1289 | gfs2_glock_dq_wait(&ip->i_iopen_gh); | 1293 | gfs2_glock_dq_wait(&ip->i_iopen_gh); |
1290 | gfs2_holder_reinit(LM_ST_EXCLUSIVE, LM_FLAG_TRY_1CB | GL_NOCACHE, &ip->i_iopen_gh); | 1294 | gfs2_holder_reinit(LM_ST_EXCLUSIVE, LM_FLAG_TRY_1CB | GL_NOCACHE, &ip->i_iopen_gh); |
1291 | error = gfs2_glock_nq(&ip->i_iopen_gh); | 1295 | error = gfs2_glock_nq(&ip->i_iopen_gh); |