diff options
author | Chris Mason <chris.mason@oracle.com> | 2009-03-24 10:24:13 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2009-03-24 16:14:51 -0400 |
commit | a74ac3220774d33db967088906dc3351829e2d3a (patch) | |
tree | 292fe0b88a5917d3b282b6a1cdfca170f9405132 | |
parent | a4b6e07d1a8a9b907e82b9acbf51a026fbb9301c (diff) |
Btrfs: Make sure i_nlink doesn't hit zero too soon during log replay
During log replay, inodes are copied from the log to the main filesystem
btrees. Sometimes they have a zero link count in the log but they actually
gain links during the replay or have some in the main btree.
This patch updates the link count to be at least one after copying the
inode out of the log. This makes sure the inode is deleted during an
iput while the rest of the replay code is still working on it.
The log replay has fixup code to make sure that link counts are correct
at the end of the replay, so we could use any non-zero number here and
it would work fine.
Signed-off-by: Chris Mason <chris.mason@oracle.com>
-rw-r--r-- | fs/btrfs/tree-log.c | 11 |
1 files changed, 11 insertions, 0 deletions
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index a93934fc93bd..405439ca4c45 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c | |||
@@ -1532,6 +1532,17 @@ static int replay_one_buffer(struct btrfs_root *log, struct extent_buffer *eb, | |||
1532 | root, inode, inode->i_size, | 1532 | root, inode, inode->i_size, |
1533 | BTRFS_EXTENT_DATA_KEY); | 1533 | BTRFS_EXTENT_DATA_KEY); |
1534 | BUG_ON(ret); | 1534 | BUG_ON(ret); |
1535 | |||
1536 | /* if the nlink count is zero here, the iput | ||
1537 | * will free the inode. We bump it to make | ||
1538 | * sure it doesn't get freed until the link | ||
1539 | * count fixup is done | ||
1540 | */ | ||
1541 | if (inode->i_nlink == 0) { | ||
1542 | btrfs_inc_nlink(inode); | ||
1543 | btrfs_update_inode(wc->trans, | ||
1544 | root, inode); | ||
1545 | } | ||
1535 | iput(inode); | 1546 | iput(inode); |
1536 | } | 1547 | } |
1537 | ret = link_to_fixup_dir(wc->trans, root, | 1548 | ret = link_to_fixup_dir(wc->trans, root, |