Skip to content

Commit bd67f17

Browse files
author
Andreas Gruenbacher
committed
gfs2: Fix data loss during inode evict
When gfs2_evict_inode() is called on an inode with unwritten data in the page cache, the page cache needs to be written before it can be truncated. This doesn't always happen. Fix that by changing gfs2_evict_inode() to always either call evict_linked_inode() or evict_unlinked_inode(). Inside evict_unlinked_inode(), first check if the inode is dirty. If it is, make sure the inode glock is held and write back the data and metadata. If it isn't, skip those steps. Also, make sure that gfs2_evict_inode() calls gfs2_evict_inode() and evict_unlinked_inode() only if ip->i_gl is not NULL; this avoids unnecessary complications there. Fixes xfstest generic/211. Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
1 parent 2b34a9e commit bd67f17

1 file changed

Lines changed: 28 additions & 8 deletions

File tree

fs/gfs2/super.c

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1241,6 +1241,9 @@ static enum evict_behavior evict_should_delete(struct inode *inode,
12411241
struct gfs2_sbd *sdp = sb->s_fs_info;
12421242
int ret;
12431243

1244+
if (inode->i_nlink)
1245+
return EVICT_SHOULD_SKIP_DELETE;
1246+
12441247
if (gfs2_holder_initialized(&ip->i_iopen_gh) &&
12451248
test_bit(GLF_DEFER_DELETE, &ip->i_iopen_gh.gh_gl->gl_flags))
12461249
return EVICT_SHOULD_DEFER_DELETE;
@@ -1279,13 +1282,18 @@ static enum evict_behavior evict_should_delete(struct inode *inode,
12791282
/**
12801283
* evict_unlinked_inode - delete the pieces of an unlinked evicted inode
12811284
* @inode: The inode to evict
1285+
* @gh: The glock holder structure
12821286
*/
1283-
static int evict_unlinked_inode(struct inode *inode)
1287+
static int evict_unlinked_inode(struct inode *inode, struct gfs2_holder *gh)
12841288
{
12851289
struct gfs2_inode *ip = GFS2_I(inode);
12861290
struct gfs2_glock *gl = ip->i_gl;
12871291
int ret;
12881292

1293+
/* The inode glock must be held exclusively and be instantiated. */
1294+
BUG_ON(!gfs2_holder_initialized(gh) ||
1295+
test_bit(GLF_INSTANTIATE_NEEDED, &gl->gl_flags));
1296+
12891297
if (S_ISDIR(inode->i_mode) &&
12901298
(ip->i_diskflags & GFS2_DIF_EXHASH)) {
12911299
ret = gfs2_dir_exhash_dealloc(ip);
@@ -1318,7 +1326,7 @@ static int evict_unlinked_inode(struct inode *inode)
13181326
*/
13191327

13201328
ret = gfs2_dinode_dealloc(ip);
1321-
if (!ret && gl)
1329+
if (!ret)
13221330
gfs2_inode_remember_delete(gl, ip->i_no_formal_ino);
13231331

13241332
out:
@@ -1357,26 +1365,38 @@ static int gfs2_truncate_inode_pages(struct inode *inode)
13571365
/*
13581366
* evict_linked_inode - evict an inode whose dinode has not been unlinked
13591367
* @inode: The inode to evict
1368+
* @gh: The glock holder structure
13601369
*/
1361-
static int evict_linked_inode(struct inode *inode)
1370+
static int evict_linked_inode(struct inode *inode, struct gfs2_holder *gh)
13621371
{
13631372
struct super_block *sb = inode->i_sb;
13641373
struct gfs2_sbd *sdp = sb->s_fs_info;
13651374
struct gfs2_inode *ip = GFS2_I(inode);
13661375
struct gfs2_glock *gl = ip->i_gl;
1367-
struct address_space *metamapping;
1376+
struct address_space *metamapping = gfs2_glock2aspace(gl);
13681377
int ret;
13691378

1379+
if (!(test_bit(GLF_DIRTY, &gl->gl_flags) || inode->i_flags & I_DIRTY))
1380+
goto clean;
1381+
1382+
/* The inode glock must be held exclusively and be instantiated. */
1383+
if (!gfs2_holder_initialized(gh))
1384+
ret = gfs2_glock_nq_init(gl, LM_ST_EXCLUSIVE, 0, gh);
1385+
else
1386+
ret = gfs2_instantiate(gh);
1387+
if (ret)
1388+
return ret;
1389+
13701390
gfs2_log_flush(sdp, gl, GFS2_LOG_HEAD_FLUSH_NORMAL |
13711391
GFS2_LFC_EVICT_INODE);
1372-
metamapping = gfs2_glock2aspace(gl);
13731392
if (test_bit(GLF_DIRTY, &gl->gl_flags)) {
13741393
filemap_fdatawrite(metamapping);
13751394
filemap_fdatawait(metamapping);
13761395
}
13771396
write_inode_now(inode, 1);
13781397
gfs2_ail_flush(gl, 0);
13791398

1399+
clean:
13801400
ret = gfs2_truncate_inode_pages(inode);
13811401
if (ret)
13821402
return ret;
@@ -1415,7 +1435,7 @@ static void gfs2_evict_inode(struct inode *inode)
14151435
int ret;
14161436

14171437
gfs2_holder_mark_uninitialized(&gh);
1418-
if (inode->i_nlink || sb_rdonly(sb) || !ip->i_no_addr)
1438+
if (sb_rdonly(sb) || !ip->i_no_addr || !ip->i_gl)
14191439
goto out;
14201440

14211441
/*
@@ -1440,9 +1460,9 @@ static void gfs2_evict_inode(struct inode *inode)
14401460
behavior = EVICT_SHOULD_SKIP_DELETE;
14411461
}
14421462
if (behavior == EVICT_SHOULD_DELETE)
1443-
ret = evict_unlinked_inode(inode);
1463+
ret = evict_unlinked_inode(inode, &gh);
14441464
else
1445-
ret = evict_linked_inode(inode);
1465+
ret = evict_linked_inode(inode, &gh);
14461466

14471467
if (gfs2_rs_active(&ip->i_res))
14481468
gfs2_rs_deltree(&ip->i_res);

0 commit comments

Comments
 (0)