Skip to content

Commit 38552ff

Browse files
author
Andreas Gruenbacher
committed
gfs2: Fix and clean up create / evict interaction
When gfs2_create_inode() fails after creating a new inode, it uses the GIF_FREE_VFS_INODE and GIF_ALLOC_FAILED inode flags to communicate to gfs2_evict_inode() which parts of the inode need to be deallocated and destroyed. In some error cases, the inode ends up being allocated on disk and then accidentally left behind. In others, the inode is partially constructed and then not properly destroyed. Clean this up by completely handling the inode deallocation and destruction in gfs2_evict_inode(). This means that gfs2_evict_inode() may now be faced with partially constructed inodes, so add the necessary checks to cope with that. In particular, make sure that for incompletely constructed inodes, we're not accessing the buffers backing the on-disk blocks; the contents may be undefined. Signed-off-by: Andreas Gruenbacher <[email protected]>
1 parent 3d0258b commit 38552ff

File tree

4 files changed

+54
-39
lines changed

4 files changed

+54
-39
lines changed

fs/gfs2/inode.c

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,8 @@ static int alloc_dinode(struct gfs2_inode *ip, u32 flags, unsigned *dblocks)
409409
ip->i_no_formal_ino = ip->i_generation;
410410
ip->i_inode.i_ino = ip->i_no_addr;
411411
ip->i_goal = ip->i_no_addr;
412+
if (*dblocks > 1)
413+
ip->i_eattr = ip->i_no_addr + 1;
412414

413415
out_trans_end:
414416
gfs2_trans_end(sdp);
@@ -589,6 +591,12 @@ static int gfs2_initxattrs(struct inode *inode, const struct xattr *xattr_array,
589591
* @size: The initial size of the inode (ignored for directories)
590592
* @excl: Force fail if inode exists
591593
*
594+
* FIXME: Change to allocate the disk blocks and write them out in the same
595+
* transaction. That way, we can no longer end up in a situation in which an
596+
* inode is allocated, the node crashes, and the block looks like a valid
597+
* inode. (With atomic creates in place, we will also no longer need to zero
598+
* the link count and dirty the inode here on failure.)
599+
*
592600
* Returns: 0 on success, or error code
593601
*/
594602

@@ -604,7 +612,7 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
604612
struct gfs2_inode *dip = GFS2_I(dir), *ip;
605613
struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
606614
struct gfs2_glock *io_gl;
607-
int error, free_vfs_inode = 1;
615+
int error;
608616
u32 aflags = 0;
609617
unsigned blocks = 1;
610618
struct gfs2_diradd da = { .bh = NULL, .save_loc = 1, };
@@ -742,20 +750,15 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
742750
if (error)
743751
goto fail_gunlock3;
744752

745-
if (blocks > 1) {
746-
ip->i_eattr = ip->i_no_addr + 1;
753+
if (blocks > 1)
747754
gfs2_init_xattr(ip);
748-
}
749755
init_dinode(dip, ip, symname);
750756
gfs2_trans_end(sdp);
751757

752758
glock_set_object(ip->i_gl, ip);
753759
glock_set_object(io_gl, ip);
754760
gfs2_set_iop(inode);
755761

756-
free_vfs_inode = 0; /* After this point, the inode is no longer
757-
considered free. Any failures need to undo
758-
the gfs2 structures. */
759762
if (default_acl) {
760763
error = __gfs2_set_acl(inode, default_acl, ACL_TYPE_DEFAULT);
761764
if (error)
@@ -804,10 +807,6 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
804807
fail_gunlock2:
805808
gfs2_glock_put(io_gl);
806809
fail_free_inode:
807-
if (ip->i_gl) {
808-
if (free_vfs_inode) /* else evict will do the put for us */
809-
gfs2_glock_put(ip->i_gl);
810-
}
811810
gfs2_rs_deltree(&ip->i_res);
812811
gfs2_qa_put(ip);
813812
fail_free_acls:
@@ -817,11 +816,10 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
817816
gfs2_dir_no_add(&da);
818817
gfs2_glock_dq_uninit(&d_gh);
819818
if (!IS_ERR_OR_NULL(inode)) {
819+
set_bit(GIF_ALLOC_FAILED, &ip->i_flags);
820820
clear_nlink(inode);
821-
if (!free_vfs_inode)
821+
if (ip->i_no_addr)
822822
mark_inode_dirty(inode);
823-
set_bit(free_vfs_inode ? GIF_FREE_VFS_INODE : GIF_ALLOC_FAILED,
824-
&ip->i_flags);
825823
if (inode->i_state & I_NEW)
826824
iget_failed(inode);
827825
else

fs/gfs2/meta_io.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,12 @@ void gfs2_journal_wipe(struct gfs2_inode *ip, u64 bstart, u32 blen)
442442
struct buffer_head *bh;
443443
int ty;
444444

445+
if (!ip->i_gl) {
446+
/* This can only happen during incomplete inode creation. */
447+
BUG_ON(!test_bit(GIF_ALLOC_FAILED, &ip->i_flags));
448+
return;
449+
}
450+
445451
gfs2_ail1_wipe(sdp, bstart, blen);
446452
while (blen) {
447453
ty = REMOVE_META;

fs/gfs2/super.c

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,12 @@ static void gfs2_dirty_inode(struct inode *inode, int flags)
475475
int need_endtrans = 0;
476476
int ret;
477477

478+
if (unlikely(!ip->i_gl)) {
479+
/* This can only happen during incomplete inode creation. */
480+
BUG_ON(!test_bit(GIF_ALLOC_FAILED, &ip->i_flags));
481+
return;
482+
}
483+
478484
if (unlikely(gfs2_withdrawn(sdp)))
479485
return;
480486
if (!gfs2_glock_is_locked_by_me(ip->i_gl)) {
@@ -927,8 +933,7 @@ static int gfs2_drop_inode(struct inode *inode)
927933
{
928934
struct gfs2_inode *ip = GFS2_I(inode);
929935

930-
if (!test_bit(GIF_FREE_VFS_INODE, &ip->i_flags) &&
931-
inode->i_nlink &&
936+
if (inode->i_nlink &&
932937
gfs2_holder_initialized(&ip->i_iopen_gh)) {
933938
struct gfs2_glock *gl = ip->i_iopen_gh.gh_gl;
934939
if (test_bit(GLF_DEMOTE, &gl->gl_flags))
@@ -1076,7 +1081,13 @@ static void gfs2_final_release_pages(struct gfs2_inode *ip)
10761081
struct inode *inode = &ip->i_inode;
10771082
struct gfs2_glock *gl = ip->i_gl;
10781083

1079-
truncate_inode_pages(gfs2_glock2aspace(ip->i_gl), 0);
1084+
if (unlikely(!gl)) {
1085+
/* This can only happen during incomplete inode creation. */
1086+
BUG_ON(!test_bit(GIF_ALLOC_FAILED, &ip->i_flags));
1087+
return;
1088+
}
1089+
1090+
truncate_inode_pages(gfs2_glock2aspace(gl), 0);
10801091
truncate_inode_pages(&inode->i_data, 0);
10811092

10821093
if (atomic_read(&gl->gl_revokes) == 0) {
@@ -1218,10 +1229,8 @@ static enum dinode_demise evict_should_delete(struct inode *inode,
12181229
struct gfs2_sbd *sdp = sb->s_fs_info;
12191230
int ret;
12201231

1221-
if (test_bit(GIF_ALLOC_FAILED, &ip->i_flags)) {
1222-
BUG_ON(!gfs2_glock_is_locked_by_me(ip->i_gl));
1232+
if (unlikely(test_bit(GIF_ALLOC_FAILED, &ip->i_flags)))
12231233
goto should_delete;
1224-
}
12251234

12261235
if (test_bit(GIF_DEFERRED_DELETE, &ip->i_flags))
12271236
return SHOULD_DEFER_EVICTION;
@@ -1298,9 +1307,11 @@ static int evict_unlinked_inode(struct inode *inode)
12981307
do, gfs2_create_inode can create another inode at the same block
12991308
location and try to set gl_object again. We clear gl_object here so
13001309
that subsequent inode creates don't see an old gl_object. */
1301-
glock_clear_object(ip->i_gl, ip);
1310+
if (ip->i_gl) {
1311+
glock_clear_object(ip->i_gl, ip);
1312+
gfs2_inode_remember_delete(ip->i_gl, ip->i_no_formal_ino);
1313+
}
13021314
ret = gfs2_dinode_dealloc(ip);
1303-
gfs2_inode_remember_delete(ip->i_gl, ip->i_no_formal_ino);
13041315
out:
13051316
return ret;
13061317
}
@@ -1367,12 +1378,7 @@ static void gfs2_evict_inode(struct inode *inode)
13671378
struct gfs2_holder gh;
13681379
int ret;
13691380

1370-
if (test_bit(GIF_FREE_VFS_INODE, &ip->i_flags)) {
1371-
clear_inode(inode);
1372-
return;
1373-
}
1374-
1375-
if (inode->i_nlink || sb_rdonly(sb))
1381+
if (inode->i_nlink || sb_rdonly(sb) || !ip->i_no_addr)
13761382
goto out;
13771383

13781384
gfs2_holder_mark_uninitialized(&gh);
@@ -1429,6 +1435,7 @@ static struct inode *gfs2_alloc_inode(struct super_block *sb)
14291435
ip = alloc_inode_sb(sb, gfs2_inode_cachep, GFP_KERNEL);
14301436
if (!ip)
14311437
return NULL;
1438+
ip->i_no_addr = 0;
14321439
ip->i_flags = 0;
14331440
ip->i_gl = NULL;
14341441
gfs2_holder_mark_uninitialized(&ip->i_iopen_gh);

fs/gfs2/xattr.c

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1412,11 +1412,13 @@ static int ea_dealloc_block(struct gfs2_inode *ip)
14121412
ip->i_eattr = 0;
14131413
gfs2_add_inode_blocks(&ip->i_inode, -1);
14141414

1415-
error = gfs2_meta_inode_buffer(ip, &dibh);
1416-
if (!error) {
1417-
gfs2_trans_add_meta(ip->i_gl, dibh);
1418-
gfs2_dinode_out(ip, dibh->b_data);
1419-
brelse(dibh);
1415+
if (likely(!test_bit(GIF_ALLOC_FAILED, &ip->i_flags))) {
1416+
error = gfs2_meta_inode_buffer(ip, &dibh);
1417+
if (!error) {
1418+
gfs2_trans_add_meta(ip->i_gl, dibh);
1419+
gfs2_dinode_out(ip, dibh->b_data);
1420+
brelse(dibh);
1421+
}
14201422
}
14211423

14221424
gfs2_trans_end(sdp);
@@ -1445,14 +1447,16 @@ int gfs2_ea_dealloc(struct gfs2_inode *ip)
14451447
if (error)
14461448
return error;
14471449

1448-
error = ea_foreach(ip, ea_dealloc_unstuffed, NULL);
1449-
if (error)
1450-
goto out_quota;
1451-
1452-
if (ip->i_diskflags & GFS2_DIF_EA_INDIRECT) {
1453-
error = ea_dealloc_indirect(ip);
1450+
if (likely(!test_bit(GIF_ALLOC_FAILED, &ip->i_flags))) {
1451+
error = ea_foreach(ip, ea_dealloc_unstuffed, NULL);
14541452
if (error)
14551453
goto out_quota;
1454+
1455+
if (ip->i_diskflags & GFS2_DIF_EA_INDIRECT) {
1456+
error = ea_dealloc_indirect(ip);
1457+
if (error)
1458+
goto out_quota;
1459+
}
14561460
}
14571461

14581462
error = ea_dealloc_block(ip);

0 commit comments

Comments
 (0)