diff options
| -rw-r--r-- | fs/btrfs/tree-log.c | 13 |
1 files changed, 13 insertions, 0 deletions
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index f06454a55e00..5256cddf3a43 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c | |||
| @@ -4544,6 +4544,19 @@ static int logged_inode_size(struct btrfs_root *log, struct btrfs_inode *inode, | |||
| 4544 | item = btrfs_item_ptr(path->nodes[0], path->slots[0], | 4544 | item = btrfs_item_ptr(path->nodes[0], path->slots[0], |
| 4545 | struct btrfs_inode_item); | 4545 | struct btrfs_inode_item); |
| 4546 | *size_ret = btrfs_inode_size(path->nodes[0], item); | 4546 | *size_ret = btrfs_inode_size(path->nodes[0], item); |
| 4547 | /* | ||
| 4548 | * If the in-memory inode's i_size is smaller then the inode | ||
| 4549 | * size stored in the btree, return the inode's i_size, so | ||
| 4550 | * that we get a correct inode size after replaying the log | ||
| 4551 | * when before a power failure we had a shrinking truncate | ||
| 4552 | * followed by addition of a new name (rename / new hard link). | ||
| 4553 | * Otherwise return the inode size from the btree, to avoid | ||
| 4554 | * data loss when replaying a log due to previously doing a | ||
| 4555 | * write that expands the inode's size and logging a new name | ||
| 4556 | * immediately after. | ||
| 4557 | */ | ||
| 4558 | if (*size_ret > inode->vfs_inode.i_size) | ||
| 4559 | *size_ret = inode->vfs_inode.i_size; | ||
| 4547 | } | 4560 | } |
| 4548 | 4561 | ||
| 4549 | btrfs_release_path(path); | 4562 | btrfs_release_path(path); |
