diff options
Diffstat (limited to 'fs/gfs2/super.c')
-rw-r--r-- | fs/gfs2/super.c | 78 |
1 files changed, 74 insertions, 4 deletions
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index b62c8427672c..215c37bfc2a4 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c | |||
@@ -1315,6 +1315,78 @@ static int gfs2_show_options(struct seq_file *s, struct vfsmount *mnt) | |||
1315 | return 0; | 1315 | return 0; |
1316 | } | 1316 | } |
1317 | 1317 | ||
1318 | static void gfs2_final_release_pages(struct gfs2_inode *ip) | ||
1319 | { | ||
1320 | struct inode *inode = &ip->i_inode; | ||
1321 | struct gfs2_glock *gl = ip->i_gl; | ||
1322 | |||
1323 | truncate_inode_pages(gfs2_glock2aspace(ip->i_gl), 0); | ||
1324 | truncate_inode_pages(&inode->i_data, 0); | ||
1325 | |||
1326 | if (atomic_read(&gl->gl_revokes) == 0) { | ||
1327 | clear_bit(GLF_LFLUSH, &gl->gl_flags); | ||
1328 | clear_bit(GLF_DIRTY, &gl->gl_flags); | ||
1329 | } | ||
1330 | } | ||
1331 | |||
1332 | static int gfs2_dinode_dealloc(struct gfs2_inode *ip) | ||
1333 | { | ||
1334 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | ||
1335 | struct gfs2_alloc *al; | ||
1336 | struct gfs2_rgrpd *rgd; | ||
1337 | int error; | ||
1338 | |||
1339 | if (gfs2_get_inode_blocks(&ip->i_inode) != 1) { | ||
1340 | if (gfs2_consist_inode(ip)) | ||
1341 | gfs2_dinode_print(ip); | ||
1342 | return -EIO; | ||
1343 | } | ||
1344 | |||
1345 | al = gfs2_alloc_get(ip); | ||
1346 | if (!al) | ||
1347 | return -ENOMEM; | ||
1348 | |||
1349 | error = gfs2_quota_hold(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); | ||
1350 | if (error) | ||
1351 | goto out; | ||
1352 | |||
1353 | error = gfs2_rindex_hold(sdp, &al->al_ri_gh); | ||
1354 | if (error) | ||
1355 | goto out_qs; | ||
1356 | |||
1357 | rgd = gfs2_blk2rgrpd(sdp, ip->i_no_addr); | ||
1358 | if (!rgd) { | ||
1359 | gfs2_consist_inode(ip); | ||
1360 | error = -EIO; | ||
1361 | goto out_rindex_relse; | ||
1362 | } | ||
1363 | |||
1364 | error = gfs2_glock_nq_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, | ||
1365 | &al->al_rgd_gh); | ||
1366 | if (error) | ||
1367 | goto out_rindex_relse; | ||
1368 | |||
1369 | error = gfs2_trans_begin(sdp, RES_RG_BIT + RES_STATFS + RES_QUOTA, 1); | ||
1370 | if (error) | ||
1371 | goto out_rg_gunlock; | ||
1372 | |||
1373 | gfs2_free_di(rgd, ip); | ||
1374 | |||
1375 | gfs2_final_release_pages(ip); | ||
1376 | |||
1377 | gfs2_trans_end(sdp); | ||
1378 | |||
1379 | out_rg_gunlock: | ||
1380 | gfs2_glock_dq_uninit(&al->al_rgd_gh); | ||
1381 | out_rindex_relse: | ||
1382 | gfs2_glock_dq_uninit(&al->al_ri_gh); | ||
1383 | out_qs: | ||
1384 | gfs2_quota_unhold(ip); | ||
1385 | out: | ||
1386 | gfs2_alloc_put(ip); | ||
1387 | return error; | ||
1388 | } | ||
1389 | |||
1318 | /* | 1390 | /* |
1319 | * We have to (at the moment) hold the inodes main lock to cover | 1391 | * We have to (at the moment) hold the inodes main lock to cover |
1320 | * the gap between unlocking the shared lock on the iopen lock and | 1392 | * the gap between unlocking the shared lock on the iopen lock and |
@@ -1378,15 +1450,13 @@ static void gfs2_evict_inode(struct inode *inode) | |||
1378 | } | 1450 | } |
1379 | 1451 | ||
1380 | error = gfs2_dinode_dealloc(ip); | 1452 | error = gfs2_dinode_dealloc(ip); |
1381 | if (error) | 1453 | goto out_unlock; |
1382 | goto out_unlock; | ||
1383 | 1454 | ||
1384 | out_truncate: | 1455 | out_truncate: |
1385 | error = gfs2_trans_begin(sdp, 0, sdp->sd_jdesc->jd_blocks); | 1456 | error = gfs2_trans_begin(sdp, 0, sdp->sd_jdesc->jd_blocks); |
1386 | if (error) | 1457 | if (error) |
1387 | goto out_unlock; | 1458 | goto out_unlock; |
1388 | /* Needs to be done before glock release & also in a transaction */ | 1459 | gfs2_final_release_pages(ip); |
1389 | truncate_inode_pages(&inode->i_data, 0); | ||
1390 | gfs2_trans_end(sdp); | 1460 | gfs2_trans_end(sdp); |
1391 | 1461 | ||
1392 | out_unlock: | 1462 | out_unlock: |