From: Greg Kroah-Hartman Date: Mon, 22 Apr 2013 17:52:12 +0000 (-0700) Subject: 3.8-stable patches X-Git-Tag: v3.8.9~4 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=0927f548ddef2c60d2485a9a7b5404dfb1b44e02;p=thirdparty%2Fkernel%2Fstable-queue.git 3.8-stable patches added patches: btrfs-make-sure-nbytes-are-right-after-log-replay.patch --- diff --git a/queue-3.8/btrfs-make-sure-nbytes-are-right-after-log-replay.patch b/queue-3.8/btrfs-make-sure-nbytes-are-right-after-log-replay.patch new file mode 100644 index 00000000000..28d87df3dc8 --- /dev/null +++ b/queue-3.8/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 +@@ -318,6 +318,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; +@@ -327,6 +328,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; +@@ -368,6 +372,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); +@@ -488,7 +516,7 @@ static noinline int replay_one_extent(st + u64 mask = root->sectorsize - 1; + u64 extent_end; + u64 start = key->offset; +- u64 saved_nbytes; ++ u64 nbytes = 0; + struct btrfs_file_extent_item *item; + struct inode *inode = NULL; + unsigned long size; +@@ -498,10 +526,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; +@@ -550,7 +587,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, root, inode, start, extent_end, 1); + BUG_ON(ret); +@@ -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); + ret = btrfs_update_inode(trans, root, inode); + out: + if (inode) diff --git a/queue-3.8/series b/queue-3.8/series index 14ec78a8947..75e426fd8c7 100644 --- a/queue-3.8/series +++ b/queue-3.8/series @@ -37,3 +37,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