[3.11.y.z extended stable] Patch "Btrfs: do not run snapshot-aware defragment on error" has been added to staging queue

Luis Henriques luis.henriques at canonical.com
Thu Jan 9 12:02:20 UTC 2014


This is a note to let you know that I have just added a patch titled

    Btrfs: do not run snapshot-aware defragment on error

to the linux-3.11.y-queue branch of the 3.11.y.z extended stable tree 
which can be found at:

 http://kernel.ubuntu.com/git?p=ubuntu/linux.git;a=shortlog;h=refs/heads/linux-3.11.y-queue

If you, or anyone else, feels it should not be added to this tree, please 
reply to this email.

For more information about the 3.11.y.z tree, see
https://wiki.ubuntu.com/Kernel/Dev/ExtendedStable

Thanks.
-Luis

------

>From 64264f460a16de18b6bc8b6fd25510c8ca44c0a1 Mon Sep 17 00:00:00 2001
From: Liu Bo <bo.li.liu at oracle.com>
Date: Tue, 29 Oct 2013 10:45:05 +0800
Subject: Btrfs: do not run snapshot-aware defragment on error

commit 6f519564d7d978c00351d9ab6abac3deeac31621 upstream.

If something wrong happens in write endio, running snapshot-aware defragment
can end up with undefined results, maybe a crash, so we should avoid it.

In order to share similar code, this also adds a helper to free the struct for
snapshot-aware defrag.

Signed-off-by: Liu Bo <bo.li.liu at oracle.com>
Signed-off-by: Josef Bacik <jbacik at fusionio.com>
Signed-off-by: Chris Mason <chris.mason at fusionio.com>
Cc: David Sterba <dsterba at suse.cz>
Signed-off-by: Luis Henriques <luis.henriques at canonical.com>
---
 fs/btrfs/inode.c | 47 ++++++++++++++++++++++++++++-------------------
 1 file changed, 28 insertions(+), 19 deletions(-)

diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 8220491..5a4bc34 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -2452,10 +2452,23 @@ out_unlock:
 	return ret;
 }

+static void free_sa_defrag_extent(struct new_sa_defrag_extent *new)
+{
+	struct old_sa_defrag_extent *old, *tmp;
+
+	if (!new)
+		return;
+
+	list_for_each_entry_safe(old, tmp, &new->head, list) {
+		list_del(&old->list);
+		kfree(old);
+	}
+	kfree(new);
+}
+
 static void relink_file_extents(struct new_sa_defrag_extent *new)
 {
 	struct btrfs_path *path;
-	struct old_sa_defrag_extent *old, *tmp;
 	struct sa_defrag_extent_backref *backref;
 	struct sa_defrag_extent_backref *prev = NULL;
 	struct inode *inode;
@@ -2498,16 +2511,11 @@ static void relink_file_extents(struct new_sa_defrag_extent *new)
 	kfree(prev);

 	btrfs_free_path(path);
-
-	list_for_each_entry_safe(old, tmp, &new->head, list) {
-		list_del(&old->list);
-		kfree(old);
-	}
 out:
+	free_sa_defrag_extent(new);
+
 	atomic_dec(&root->fs_info->defrag_running);
 	wake_up(&root->fs_info->transaction_wait);
-
-	kfree(new);
 }

 static struct new_sa_defrag_extent *
@@ -2517,7 +2525,7 @@ record_old_file_extents(struct inode *inode,
 	struct btrfs_root *root = BTRFS_I(inode)->root;
 	struct btrfs_path *path;
 	struct btrfs_key key;
-	struct old_sa_defrag_extent *old, *tmp;
+	struct old_sa_defrag_extent *old;
 	struct new_sa_defrag_extent *new;
 	int ret;

@@ -2565,7 +2573,7 @@ record_old_file_extents(struct inode *inode,
 		if (slot >= btrfs_header_nritems(l)) {
 			ret = btrfs_next_leaf(root, path);
 			if (ret < 0)
-				goto out_free_list;
+				goto out_free_path;
 			else if (ret > 0)
 				break;
 			continue;
@@ -2594,7 +2602,7 @@ record_old_file_extents(struct inode *inode,

 		old = kmalloc(sizeof(*old), GFP_NOFS);
 		if (!old)
-			goto out_free_list;
+			goto out_free_path;

 		offset = max(new->file_pos, key.offset);
 		end = min(new->file_pos + new->len, key.offset + num_bytes);
@@ -2616,15 +2624,10 @@ next:

 	return new;

-out_free_list:
-	list_for_each_entry_safe(old, tmp, &new->head, list) {
-		list_del(&old->list);
-		kfree(old);
-	}
 out_free_path:
 	btrfs_free_path(path);
 out_kfree:
-	kfree(new);
+	free_sa_defrag_extent(new);
 	return NULL;
 }

@@ -2776,8 +2779,14 @@ out:
 	btrfs_remove_ordered_extent(inode, ordered_extent);

 	/* for snapshot-aware defrag */
-	if (new)
-		relink_file_extents(new);
+	if (new) {
+		if (ret) {
+			free_sa_defrag_extent(new);
+			atomic_dec(&root->fs_info->defrag_running);
+		} else {
+			relink_file_extents(new);
+		}
+	}

 	/* once for us */
 	btrfs_put_ordered_extent(ordered_extent);
--
1.8.3.2





More information about the kernel-team mailing list