diff options
Diffstat (limited to 'fs/gfs2/super.c')
-rw-r--r-- | fs/gfs2/super.c | 36 |
1 files changed, 30 insertions, 6 deletions
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index ed540e7018be..fb0edf735483 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c | |||
@@ -757,13 +757,17 @@ static int gfs2_write_inode(struct inode *inode, struct writeback_control *wbc) | |||
757 | struct timespec atime; | 757 | struct timespec atime; |
758 | struct gfs2_dinode *di; | 758 | struct gfs2_dinode *di; |
759 | int ret = -EAGAIN; | 759 | int ret = -EAGAIN; |
760 | int unlock_required = 0; | ||
760 | 761 | ||
761 | /* Skip timestamp update, if this is from a memalloc */ | 762 | /* Skip timestamp update, if this is from a memalloc */ |
762 | if (current->flags & PF_MEMALLOC) | 763 | if (current->flags & PF_MEMALLOC) |
763 | goto do_flush; | 764 | goto do_flush; |
764 | ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); | 765 | if (!gfs2_glock_is_locked_by_me(ip->i_gl)) { |
765 | if (ret) | 766 | ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); |
766 | goto do_flush; | 767 | if (ret) |
768 | goto do_flush; | ||
769 | unlock_required = 1; | ||
770 | } | ||
767 | ret = gfs2_trans_begin(sdp, RES_DINODE, 0); | 771 | ret = gfs2_trans_begin(sdp, RES_DINODE, 0); |
768 | if (ret) | 772 | if (ret) |
769 | goto do_unlock; | 773 | goto do_unlock; |
@@ -780,7 +784,8 @@ static int gfs2_write_inode(struct inode *inode, struct writeback_control *wbc) | |||
780 | } | 784 | } |
781 | gfs2_trans_end(sdp); | 785 | gfs2_trans_end(sdp); |
782 | do_unlock: | 786 | do_unlock: |
783 | gfs2_glock_dq_uninit(&gh); | 787 | if (unlock_required) |
788 | gfs2_glock_dq_uninit(&gh); | ||
784 | do_flush: | 789 | do_flush: |
785 | if (wbc->sync_mode == WB_SYNC_ALL) | 790 | if (wbc->sync_mode == WB_SYNC_ALL) |
786 | gfs2_log_flush(GFS2_SB(inode), ip->i_gl); | 791 | gfs2_log_flush(GFS2_SB(inode), ip->i_gl); |
@@ -1427,7 +1432,20 @@ out: | |||
1427 | return error; | 1432 | return error; |
1428 | } | 1433 | } |
1429 | 1434 | ||
1430 | /* | 1435 | /** |
1436 | * gfs2_evict_inode - Remove an inode from cache | ||
1437 | * @inode: The inode to evict | ||
1438 | * | ||
1439 | * There are three cases to consider: | ||
1440 | * 1. i_nlink == 0, we are final opener (and must deallocate) | ||
1441 | * 2. i_nlink == 0, we are not the final opener (and cannot deallocate) | ||
1442 | * 3. i_nlink > 0 | ||
1443 | * | ||
1444 | * If the fs is read only, then we have to treat all cases as per #3 | ||
1445 | * since we are unable to do any deallocation. The inode will be | ||
1446 | * deallocated by the next read/write node to attempt an allocation | ||
1447 | * in the same resource group | ||
1448 | * | ||
1431 | * We have to (at the moment) hold the inodes main lock to cover | 1449 | * We have to (at the moment) hold the inodes main lock to cover |
1432 | * the gap between unlocking the shared lock on the iopen lock and | 1450 | * the gap between unlocking the shared lock on the iopen lock and |
1433 | * taking the exclusive lock. I'd rather do a shared -> exclusive | 1451 | * taking the exclusive lock. I'd rather do a shared -> exclusive |
@@ -1470,6 +1488,8 @@ static void gfs2_evict_inode(struct inode *inode) | |||
1470 | if (error) | 1488 | if (error) |
1471 | goto out_truncate; | 1489 | goto out_truncate; |
1472 | 1490 | ||
1491 | /* Case 1 starts here */ | ||
1492 | |||
1473 | if (S_ISDIR(inode->i_mode) && | 1493 | if (S_ISDIR(inode->i_mode) && |
1474 | (ip->i_diskflags & GFS2_DIF_EXHASH)) { | 1494 | (ip->i_diskflags & GFS2_DIF_EXHASH)) { |
1475 | error = gfs2_dir_exhash_dealloc(ip); | 1495 | error = gfs2_dir_exhash_dealloc(ip); |
@@ -1493,13 +1513,16 @@ static void gfs2_evict_inode(struct inode *inode) | |||
1493 | goto out_unlock; | 1513 | goto out_unlock; |
1494 | 1514 | ||
1495 | out_truncate: | 1515 | out_truncate: |
1516 | /* Case 2 starts here */ | ||
1496 | error = gfs2_trans_begin(sdp, 0, sdp->sd_jdesc->jd_blocks); | 1517 | error = gfs2_trans_begin(sdp, 0, sdp->sd_jdesc->jd_blocks); |
1497 | if (error) | 1518 | if (error) |
1498 | goto out_unlock; | 1519 | goto out_unlock; |
1499 | gfs2_final_release_pages(ip); | 1520 | /* Needs to be done before glock release & also in a transaction */ |
1521 | truncate_inode_pages(&inode->i_data, 0); | ||
1500 | gfs2_trans_end(sdp); | 1522 | gfs2_trans_end(sdp); |
1501 | 1523 | ||
1502 | out_unlock: | 1524 | out_unlock: |
1525 | /* Error path for case 1 */ | ||
1503 | if (test_bit(HIF_HOLDER, &ip->i_iopen_gh.gh_iflags)) | 1526 | if (test_bit(HIF_HOLDER, &ip->i_iopen_gh.gh_iflags)) |
1504 | gfs2_glock_dq(&ip->i_iopen_gh); | 1527 | gfs2_glock_dq(&ip->i_iopen_gh); |
1505 | gfs2_holder_uninit(&ip->i_iopen_gh); | 1528 | gfs2_holder_uninit(&ip->i_iopen_gh); |
@@ -1507,6 +1530,7 @@ out_unlock: | |||
1507 | if (error && error != GLR_TRYFAILED && error != -EROFS) | 1530 | if (error && error != GLR_TRYFAILED && error != -EROFS) |
1508 | fs_warn(sdp, "gfs2_evict_inode: %d\n", error); | 1531 | fs_warn(sdp, "gfs2_evict_inode: %d\n", error); |
1509 | out: | 1532 | out: |
1533 | /* Case 3 starts here */ | ||
1510 | truncate_inode_pages(&inode->i_data, 0); | 1534 | truncate_inode_pages(&inode->i_data, 0); |
1511 | end_writeback(inode); | 1535 | end_writeback(inode); |
1512 | 1536 | ||