Skip to content

Commit 2c63986

Browse files
author
Andreas Gruenbacher
committed
gfs2: deallocate inodes in gfs2_create_inode
When creating and destroying inodes, we are relying on the inode hash table to make sure that for a given inode number, only a single inode will exist. We then link that inode to its inode and iopen glock and let those glocks point back at the inode. However, when iget_failed() is called, the inode is removed from the inode hash table before gfs_evict_inode() is called, and uniqueness is no longer guaranteed. Commit f1046a472b70 ("gfs2: gl_object races fix") was trying to work around that problem by detaching the inode glock from the inode before calling iget_failed(), but that broke the inode deallocation code in gfs_evict_inode(). To fix that, deallocate partially created inodes in gfs2_create_inode() instead of relying on gfs_evict_inode() for doing that. This means that gfs2_evict_inode() and its helper functions will no longer see partially created inodes, and so some simplifications are possible there. Fixes: 9ffa188 ("gfs2: gl_object races fix") Signed-off-by: Andreas Gruenbacher <[email protected]>
1 parent 0cc617a commit 2c63986

File tree

2 files changed

+20
-13
lines changed

2 files changed

+20
-13
lines changed

fs/gfs2/inode.c

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -697,10 +697,11 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
697697
struct gfs2_inode *dip = GFS2_I(dir), *ip;
698698
struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
699699
struct gfs2_glock *io_gl;
700-
int error;
700+
int error, dealloc_error;
701701
u32 aflags = 0;
702702
unsigned blocks = 1;
703703
struct gfs2_diradd da = { .bh = NULL, .save_loc = 1, };
704+
bool xattr_initialized = false;
704705

705706
if (!name->len || name->len > GFS2_FNAMESIZE)
706707
return -ENAMETOOLONG;
@@ -813,11 +814,11 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
813814

814815
error = gfs2_glock_get(sdp, ip->i_no_addr, &gfs2_inode_glops, CREATE, &ip->i_gl);
815816
if (error)
816-
goto fail_free_inode;
817+
goto fail_dealloc_inode;
817818

818819
error = gfs2_glock_get(sdp, ip->i_no_addr, &gfs2_iopen_glops, CREATE, &io_gl);
819820
if (error)
820-
goto fail_free_inode;
821+
goto fail_dealloc_inode;
821822
gfs2_cancel_delete_work(io_gl);
822823
io_gl->gl_no_formal_ino = ip->i_no_formal_ino;
823824

@@ -842,8 +843,10 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
842843
if (error)
843844
goto fail_gunlock3;
844845

845-
if (blocks > 1)
846+
if (blocks > 1) {
846847
gfs2_init_xattr(ip);
848+
xattr_initialized = true;
849+
}
847850
init_dinode(dip, ip, symname);
848851
gfs2_trans_end(sdp);
849852

@@ -898,6 +901,18 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
898901
gfs2_glock_dq_uninit(&ip->i_iopen_gh);
899902
fail_gunlock2:
900903
gfs2_glock_put(io_gl);
904+
fail_dealloc_inode:
905+
set_bit(GIF_ALLOC_FAILED, &ip->i_flags);
906+
dealloc_error = 0;
907+
if (ip->i_eattr)
908+
dealloc_error = gfs2_ea_dealloc(ip, xattr_initialized);
909+
clear_nlink(inode);
910+
mark_inode_dirty(inode);
911+
if (!dealloc_error)
912+
dealloc_error = gfs2_dinode_dealloc(ip);
913+
if (dealloc_error)
914+
fs_warn(sdp, "%s: %d\n", __func__, dealloc_error);
915+
ip->i_no_addr = 0;
901916
fail_free_inode:
902917
if (ip->i_gl) {
903918
gfs2_glock_put(ip->i_gl);
@@ -912,10 +927,6 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
912927
gfs2_dir_no_add(&da);
913928
gfs2_glock_dq_uninit(&d_gh);
914929
if (!IS_ERR_OR_NULL(inode)) {
915-
set_bit(GIF_ALLOC_FAILED, &ip->i_flags);
916-
clear_nlink(inode);
917-
if (ip->i_no_addr)
918-
mark_inode_dirty(inode);
919930
if (inode->i_state & I_NEW)
920931
iget_failed(inode);
921932
else

fs/gfs2/super.c

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1258,9 +1258,6 @@ static enum evict_behavior evict_should_delete(struct inode *inode,
12581258
struct gfs2_sbd *sdp = sb->s_fs_info;
12591259
int ret;
12601260

1261-
if (unlikely(test_bit(GIF_ALLOC_FAILED, &ip->i_flags)))
1262-
goto should_delete;
1263-
12641261
if (gfs2_holder_initialized(&ip->i_iopen_gh) &&
12651262
test_bit(GLF_DEFER_DELETE, &ip->i_iopen_gh.gh_gl->gl_flags))
12661263
return EVICT_SHOULD_DEFER_DELETE;
@@ -1290,7 +1287,6 @@ static enum evict_behavior evict_should_delete(struct inode *inode,
12901287
if (inode->i_nlink)
12911288
return EVICT_SHOULD_SKIP_DELETE;
12921289

1293-
should_delete:
12941290
if (gfs2_holder_initialized(&ip->i_iopen_gh) &&
12951291
test_bit(HIF_HOLDER, &ip->i_iopen_gh.gh_iflags))
12961292
return gfs2_upgrade_iopen_glock(inode);
@@ -1314,7 +1310,7 @@ static int evict_unlinked_inode(struct inode *inode)
13141310
}
13151311

13161312
if (ip->i_eattr) {
1317-
ret = gfs2_ea_dealloc(ip, !test_bit(GIF_ALLOC_FAILED, &ip->i_flags));
1313+
ret = gfs2_ea_dealloc(ip, true);
13181314
if (ret)
13191315
goto out;
13201316
}

0 commit comments

Comments
 (0)