From c04c3bb8b599d64b68366e8392f795e2929f4378 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 22 Apr 2013 10:51:32 -0700 Subject: [PATCH] 3.0-stable patches added patches: btrfs-make-sure-nbytes-are-right-after-log-replay.patch --- ...re-nbytes-are-right-after-log-replay.patch | 129 ++++++++++++++++++ queue-3.0/series | 1 + 2 files changed, 130 insertions(+) create mode 100644 queue-3.0/btrfs-make-sure-nbytes-are-right-after-log-replay.patch diff --git a/queue-3.0/btrfs-make-sure-nbytes-are-right-after-log-replay.patch b/queue-3.0/btrfs-make-sure-nbytes-are-right-after-log-replay.patch new file mode 100644 index 00000000000..22b20a8889e --- /dev/null +++ b/queue-3.0/btrfs-make-sure-nbytes-are-right-after-log-replay.patch @@ -0,0 +1,129 @@ +From 4bc4bee4595662d8bff92180d5c32e3313a704b0 Mon Sep 17 00:00:00 2001 +From: Josef Bacik +Date: Fri, 5 Apr 2013 20:50:09 +0000 +Subject: Btrfs: make sure nbytes are right after log replay + +From: Josef Bacik + +commit 4bc4bee4595662d8bff92180d5c32e3313a704b0 upstream. + +While trying to track down a tree log replay bug I noticed that fsck was always +complaining about nbytes not being right for our fsynced file. That is because +the new fsync stuff doesn't wait for ordered extents to complete, so the inodes +nbytes are not necessarily updated properly when we log it. So to fix this we +need to set nbytes to whatever it is on the inode that is on disk, so when we +replay the extents we can just add the bytes that are being added as we replay +the extent. This makes it work for the case that we have the wrong nbytes or +the case that we logged everything and nbytes is actually correct. With this +I'm no longer getting nbytes errors out of btrfsck. + +Signed-off-by: Josef Bacik +Signed-off-by: Chris Mason +Signed-off-by: Lingzhu Xiang +Reviewed-by: CAI Qian +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/tree-log.c | 48 ++++++++++++++++++++++++++++++++++++++++++------ + 1 file changed, 42 insertions(+), 6 deletions(-) + +--- a/fs/btrfs/tree-log.c ++++ b/fs/btrfs/tree-log.c +@@ -315,6 +315,7 @@ static noinline int overwrite_item(struc + unsigned long src_ptr; + unsigned long dst_ptr; + int overwrite_root = 0; ++ bool inode_item = key->type == BTRFS_INODE_ITEM_KEY; + + if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID) + overwrite_root = 1; +@@ -324,6 +325,9 @@ static noinline int overwrite_item(struc + + /* look for the key in the destination tree */ + ret = btrfs_search_slot(NULL, root, key, path, 0, 0); ++ if (ret < 0) ++ return ret; ++ + if (ret == 0) { + char *src_copy; + char *dst_copy; +@@ -365,6 +369,30 @@ static noinline int overwrite_item(struc + return 0; + } + ++ /* ++ * We need to load the old nbytes into the inode so when we ++ * replay the extents we've logged we get the right nbytes. ++ */ ++ if (inode_item) { ++ struct btrfs_inode_item *item; ++ u64 nbytes; ++ ++ item = btrfs_item_ptr(path->nodes[0], path->slots[0], ++ struct btrfs_inode_item); ++ nbytes = btrfs_inode_nbytes(path->nodes[0], item); ++ item = btrfs_item_ptr(eb, slot, ++ struct btrfs_inode_item); ++ btrfs_set_inode_nbytes(eb, item, nbytes); ++ } ++ } else if (inode_item) { ++ struct btrfs_inode_item *item; ++ ++ /* ++ * New inode, set nbytes to 0 so that the nbytes comes out ++ * properly when we replay the extents. ++ */ ++ item = btrfs_item_ptr(eb, slot, struct btrfs_inode_item); ++ btrfs_set_inode_nbytes(eb, item, 0); + } + insert: + btrfs_release_path(path); +@@ -487,7 +515,7 @@ static noinline int replay_one_extent(st + u64 extent_end; + u64 alloc_hint; + u64 start = key->offset; +- u64 saved_nbytes; ++ u64 nbytes = 0; + struct btrfs_file_extent_item *item; + struct inode *inode = NULL; + unsigned long size; +@@ -497,10 +525,19 @@ static noinline int replay_one_extent(st + found_type = btrfs_file_extent_type(eb, item); + + if (found_type == BTRFS_FILE_EXTENT_REG || +- found_type == BTRFS_FILE_EXTENT_PREALLOC) +- extent_end = start + btrfs_file_extent_num_bytes(eb, item); +- else if (found_type == BTRFS_FILE_EXTENT_INLINE) { ++ found_type == BTRFS_FILE_EXTENT_PREALLOC) { ++ nbytes = btrfs_file_extent_num_bytes(eb, item); ++ extent_end = start + nbytes; ++ ++ /* ++ * We don't add to the inodes nbytes if we are prealloc or a ++ * hole. ++ */ ++ if (btrfs_file_extent_disk_bytenr(eb, item) == 0) ++ nbytes = 0; ++ } else if (found_type == BTRFS_FILE_EXTENT_INLINE) { + size = btrfs_file_extent_inline_len(eb, item); ++ nbytes = btrfs_file_extent_ram_bytes(eb, item); + extent_end = (start + size + mask) & ~mask; + } else { + ret = 0; +@@ -549,7 +586,6 @@ static noinline int replay_one_extent(st + } + btrfs_release_path(path); + +- saved_nbytes = inode_get_bytes(inode); + /* drop any overlapping extents */ + ret = btrfs_drop_extents(trans, inode, start, extent_end, + &alloc_hint, 1); +@@ -637,7 +673,7 @@ static noinline int replay_one_extent(st + BUG_ON(ret); + } + +- inode_set_bytes(inode, saved_nbytes); ++ inode_add_bytes(inode, nbytes); + btrfs_update_inode(trans, root, inode); + out: + if (inode) diff --git a/queue-3.0/series b/queue-3.0/series index 2101bc5f0ce..7170d63b191 100644 --- a/queue-3.0/series +++ b/queue-3.0/series @@ -21,3 +21,4 @@ vm-convert-snd_pcm_lib_mmap_iomem-to-vm_iomap_memory-helper.patch vm-convert-fb_mmap-to-vm_iomap_memory-helper.patch vm-convert-hpet-mmap-to-vm_iomap_memory-helper.patch vm-convert-mtdchar-mmap-to-vm_iomap_memory-helper.patch +btrfs-make-sure-nbytes-are-right-after-log-replay.patch -- 2.47.3