aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLiu Bo <bo.li.liu@oracle.com>2013-10-28 22:45:05 -0400
committerChris Mason <chris.mason@fusionio.com>2013-11-11 22:11:00 -0500
commit6f519564d7d978c00351d9ab6abac3deeac31621 (patch)
treead6219309aee3a44248fb7f7eb9756fc76423d79
parent269d040ff2f340e1ed517dab8b66b2f133c83a77 (diff)
Btrfs: do not run snapshot-aware defragment on error
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@oracle.com> Signed-off-by: Josef Bacik <jbacik@fusionio.com> Signed-off-by: Chris Mason <chris.mason@fusionio.com>
-rw-r--r--fs/btrfs/inode.c47
1 files changed, 28 insertions, 19 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index c84adde53023..17800221978f 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -2365,10 +2365,23 @@ out_unlock:
2365 return ret; 2365 return ret;
2366} 2366}
2367 2367
2368static void free_sa_defrag_extent(struct new_sa_defrag_extent *new)
2369{
2370 struct old_sa_defrag_extent *old, *tmp;
2371
2372 if (!new)
2373 return;
2374
2375 list_for_each_entry_safe(old, tmp, &new->head, list) {
2376 list_del(&old->list);
2377 kfree(old);
2378 }
2379 kfree(new);
2380}
2381
2368static void relink_file_extents(struct new_sa_defrag_extent *new) 2382static void relink_file_extents(struct new_sa_defrag_extent *new)
2369{ 2383{
2370 struct btrfs_path *path; 2384 struct btrfs_path *path;
2371 struct old_sa_defrag_extent *old, *tmp;
2372 struct sa_defrag_extent_backref *backref; 2385 struct sa_defrag_extent_backref *backref;
2373 struct sa_defrag_extent_backref *prev = NULL; 2386 struct sa_defrag_extent_backref *prev = NULL;
2374 struct inode *inode; 2387 struct inode *inode;
@@ -2411,16 +2424,11 @@ static void relink_file_extents(struct new_sa_defrag_extent *new)
2411 kfree(prev); 2424 kfree(prev);
2412 2425
2413 btrfs_free_path(path); 2426 btrfs_free_path(path);
2414
2415 list_for_each_entry_safe(old, tmp, &new->head, list) {
2416 list_del(&old->list);
2417 kfree(old);
2418 }
2419out: 2427out:
2428 free_sa_defrag_extent(new);
2429
2420 atomic_dec(&root->fs_info->defrag_running); 2430 atomic_dec(&root->fs_info->defrag_running);
2421 wake_up(&root->fs_info->transaction_wait); 2431 wake_up(&root->fs_info->transaction_wait);
2422
2423 kfree(new);
2424} 2432}
2425 2433
2426static struct new_sa_defrag_extent * 2434static struct new_sa_defrag_extent *
@@ -2430,7 +2438,7 @@ record_old_file_extents(struct inode *inode,
2430 struct btrfs_root *root = BTRFS_I(inode)->root; 2438 struct btrfs_root *root = BTRFS_I(inode)->root;
2431 struct btrfs_path *path; 2439 struct btrfs_path *path;
2432 struct btrfs_key key; 2440 struct btrfs_key key;
2433 struct old_sa_defrag_extent *old, *tmp; 2441 struct old_sa_defrag_extent *old;
2434 struct new_sa_defrag_extent *new; 2442 struct new_sa_defrag_extent *new;
2435 int ret; 2443 int ret;
2436 2444
@@ -2478,7 +2486,7 @@ record_old_file_extents(struct inode *inode,
2478 if (slot >= btrfs_header_nritems(l)) { 2486 if (slot >= btrfs_header_nritems(l)) {
2479 ret = btrfs_next_leaf(root, path); 2487 ret = btrfs_next_leaf(root, path);
2480 if (ret < 0) 2488 if (ret < 0)
2481 goto out_free_list; 2489 goto out_free_path;
2482 else if (ret > 0) 2490 else if (ret > 0)
2483 break; 2491 break;
2484 continue; 2492 continue;
@@ -2507,7 +2515,7 @@ record_old_file_extents(struct inode *inode,
2507 2515
2508 old = kmalloc(sizeof(*old), GFP_NOFS); 2516 old = kmalloc(sizeof(*old), GFP_NOFS);
2509 if (!old) 2517 if (!old)
2510 goto out_free_list; 2518 goto out_free_path;
2511 2519
2512 offset = max(new->file_pos, key.offset); 2520 offset = max(new->file_pos, key.offset);
2513 end = min(new->file_pos + new->len, key.offset + num_bytes); 2521 end = min(new->file_pos + new->len, key.offset + num_bytes);
@@ -2529,15 +2537,10 @@ next:
2529 2537
2530 return new; 2538 return new;
2531 2539
2532out_free_list:
2533 list_for_each_entry_safe(old, tmp, &new->head, list) {
2534 list_del(&old->list);
2535 kfree(old);
2536 }
2537out_free_path: 2540out_free_path:
2538 btrfs_free_path(path); 2541 btrfs_free_path(path);
2539out_kfree: 2542out_kfree:
2540 kfree(new); 2543 free_sa_defrag_extent(new);
2541 return NULL; 2544 return NULL;
2542} 2545}
2543 2546
@@ -2708,8 +2711,14 @@ out:
2708 btrfs_remove_ordered_extent(inode, ordered_extent); 2711 btrfs_remove_ordered_extent(inode, ordered_extent);
2709 2712
2710 /* for snapshot-aware defrag */ 2713 /* for snapshot-aware defrag */
2711 if (new) 2714 if (new) {
2712 relink_file_extents(new); 2715 if (ret) {
2716 free_sa_defrag_extent(new);
2717 atomic_dec(&root->fs_info->defrag_running);
2718 } else {
2719 relink_file_extents(new);
2720 }
2721 }
2713 2722
2714 /* once for us */ 2723 /* once for us */
2715 btrfs_put_ordered_extent(ordered_extent); 2724 btrfs_put_ordered_extent(ordered_extent);