diff options
author | Anand Jain <Anand.Jain@oracle.com> | 2015-06-17 09:10:48 -0400 |
---|---|---|
committer | David Sterba <dsterba@suse.cz> | 2015-06-19 08:03:13 -0400 |
commit | 4fde46f0cc71c7aba299ee6dfb4f017fb97b6e70 (patch) | |
tree | 31a47f030f88140fa99e8fc555a942435db3a0fd | |
parent | 2421a8cd5faaa9c2c9397123c5a297bab227d965 (diff) |
Btrfs: free the stale device
When btrfs on a device is overwritten with a new btrfs (mkfs),
the old btrfs instance in the kernel becomes stale. So with this
patch, if kernel finds device is overwritten then delete the stale
fsid/uuid.
Signed-off-by: Anand Jain <anand.jain@oracle.com>
-rw-r--r-- | fs/btrfs/volumes.c | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index b851964b7345..ea293db89cc4 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -445,6 +445,61 @@ static void pending_bios_fn(struct btrfs_work *work) | |||
445 | run_scheduled_bios(device); | 445 | run_scheduled_bios(device); |
446 | } | 446 | } |
447 | 447 | ||
448 | |||
449 | void btrfs_free_stale_device(struct btrfs_device *cur_dev) | ||
450 | { | ||
451 | struct btrfs_fs_devices *fs_devs; | ||
452 | struct btrfs_device *dev; | ||
453 | |||
454 | if (!cur_dev->name) | ||
455 | return; | ||
456 | |||
457 | list_for_each_entry(fs_devs, &fs_uuids, list) { | ||
458 | int del = 1; | ||
459 | |||
460 | if (fs_devs->opened) | ||
461 | continue; | ||
462 | if (fs_devs->seeding) | ||
463 | continue; | ||
464 | |||
465 | list_for_each_entry(dev, &fs_devs->devices, dev_list) { | ||
466 | |||
467 | if (dev == cur_dev) | ||
468 | continue; | ||
469 | if (!dev->name) | ||
470 | continue; | ||
471 | |||
472 | /* | ||
473 | * Todo: This won't be enough. What if the same device | ||
474 | * comes back (with new uuid and) with its mapper path? | ||
475 | * But for now, this does help as mostly an admin will | ||
476 | * either use mapper or non mapper path throughout. | ||
477 | */ | ||
478 | rcu_read_lock(); | ||
479 | del = strcmp(rcu_str_deref(dev->name), | ||
480 | rcu_str_deref(cur_dev->name)); | ||
481 | rcu_read_unlock(); | ||
482 | if (!del) | ||
483 | break; | ||
484 | } | ||
485 | |||
486 | if (!del) { | ||
487 | /* delete the stale device */ | ||
488 | if (fs_devs->num_devices == 1) { | ||
489 | btrfs_sysfs_remove_fsid(fs_devs); | ||
490 | list_del(&fs_devs->list); | ||
491 | free_fs_devices(fs_devs); | ||
492 | } else { | ||
493 | fs_devs->num_devices--; | ||
494 | list_del(&dev->dev_list); | ||
495 | rcu_string_free(dev->name); | ||
496 | kfree(dev); | ||
497 | } | ||
498 | break; | ||
499 | } | ||
500 | } | ||
501 | } | ||
502 | |||
448 | /* | 503 | /* |
449 | * Add new device to list of registered devices | 504 | * Add new device to list of registered devices |
450 | * | 505 | * |
@@ -560,6 +615,12 @@ static noinline int device_list_add(const char *path, | |||
560 | if (!fs_devices->opened) | 615 | if (!fs_devices->opened) |
561 | device->generation = found_transid; | 616 | device->generation = found_transid; |
562 | 617 | ||
618 | /* | ||
619 | * if there is new btrfs on an already registered device, | ||
620 | * then remove the stale device entry. | ||
621 | */ | ||
622 | btrfs_free_stale_device(device); | ||
623 | |||
563 | *fs_devices_ret = fs_devices; | 624 | *fs_devices_ret = fs_devices; |
564 | 625 | ||
565 | return ret; | 626 | return ret; |