aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/volumes.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/volumes.c')
-rw-r--r--fs/btrfs/volumes.c83
1 files changed, 83 insertions, 0 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 4066803fe765..75bdea6bf188 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -3559,10 +3559,76 @@ out:
3559 btrfs_free_path(path); 3559 btrfs_free_path(path);
3560 if (ret) 3560 if (ret)
3561 pr_warn("btrfs: btrfs_uuid_scan_kthread failed %d\n", ret); 3561 pr_warn("btrfs: btrfs_uuid_scan_kthread failed %d\n", ret);
3562 else
3563 fs_info->update_uuid_tree_gen = 1;
3562 up(&fs_info->uuid_tree_rescan_sem); 3564 up(&fs_info->uuid_tree_rescan_sem);
3563 return 0; 3565 return 0;
3564} 3566}
3565 3567
3568/*
3569 * Callback for btrfs_uuid_tree_iterate().
3570 * returns:
3571 * 0 check succeeded, the entry is not outdated.
3572 * < 0 if an error occured.
3573 * > 0 if the check failed, which means the caller shall remove the entry.
3574 */
3575static int btrfs_check_uuid_tree_entry(struct btrfs_fs_info *fs_info,
3576 u8 *uuid, u8 type, u64 subid)
3577{
3578 struct btrfs_key key;
3579 int ret = 0;
3580 struct btrfs_root *subvol_root;
3581
3582 if (type != BTRFS_UUID_KEY_SUBVOL &&
3583 type != BTRFS_UUID_KEY_RECEIVED_SUBVOL)
3584 goto out;
3585
3586 key.objectid = subid;
3587 key.type = BTRFS_ROOT_ITEM_KEY;
3588 key.offset = (u64)-1;
3589 subvol_root = btrfs_read_fs_root_no_name(fs_info, &key);
3590 if (IS_ERR(subvol_root)) {
3591 ret = PTR_ERR(subvol_root);
3592 if (ret == -ENOENT)
3593 ret = 1;
3594 goto out;
3595 }
3596
3597 switch (type) {
3598 case BTRFS_UUID_KEY_SUBVOL:
3599 if (memcmp(uuid, subvol_root->root_item.uuid, BTRFS_UUID_SIZE))
3600 ret = 1;
3601 break;
3602 case BTRFS_UUID_KEY_RECEIVED_SUBVOL:
3603 if (memcmp(uuid, subvol_root->root_item.received_uuid,
3604 BTRFS_UUID_SIZE))
3605 ret = 1;
3606 break;
3607 }
3608
3609out:
3610 return ret;
3611}
3612
3613static int btrfs_uuid_rescan_kthread(void *data)
3614{
3615 struct btrfs_fs_info *fs_info = (struct btrfs_fs_info *)data;
3616 int ret;
3617
3618 /*
3619 * 1st step is to iterate through the existing UUID tree and
3620 * to delete all entries that contain outdated data.
3621 * 2nd step is to add all missing entries to the UUID tree.
3622 */
3623 ret = btrfs_uuid_tree_iterate(fs_info, btrfs_check_uuid_tree_entry);
3624 if (ret < 0) {
3625 pr_warn("btrfs: iterating uuid_tree failed %d\n", ret);
3626 up(&fs_info->uuid_tree_rescan_sem);
3627 return ret;
3628 }
3629 return btrfs_uuid_scan_kthread(data);
3630}
3631
3566int btrfs_create_uuid_tree(struct btrfs_fs_info *fs_info) 3632int btrfs_create_uuid_tree(struct btrfs_fs_info *fs_info)
3567{ 3633{
3568 struct btrfs_trans_handle *trans; 3634 struct btrfs_trans_handle *trans;
@@ -3596,6 +3662,7 @@ int btrfs_create_uuid_tree(struct btrfs_fs_info *fs_info)
3596 down(&fs_info->uuid_tree_rescan_sem); 3662 down(&fs_info->uuid_tree_rescan_sem);
3597 task = kthread_run(btrfs_uuid_scan_kthread, fs_info, "btrfs-uuid"); 3663 task = kthread_run(btrfs_uuid_scan_kthread, fs_info, "btrfs-uuid");
3598 if (IS_ERR(task)) { 3664 if (IS_ERR(task)) {
3665 /* fs_info->update_uuid_tree_gen remains 0 in all error case */
3599 pr_warn("btrfs: failed to start uuid_scan task\n"); 3666 pr_warn("btrfs: failed to start uuid_scan task\n");
3600 up(&fs_info->uuid_tree_rescan_sem); 3667 up(&fs_info->uuid_tree_rescan_sem);
3601 return PTR_ERR(task); 3668 return PTR_ERR(task);
@@ -3604,6 +3671,22 @@ int btrfs_create_uuid_tree(struct btrfs_fs_info *fs_info)
3604 return 0; 3671 return 0;
3605} 3672}
3606 3673
3674int btrfs_check_uuid_tree(struct btrfs_fs_info *fs_info)
3675{
3676 struct task_struct *task;
3677
3678 down(&fs_info->uuid_tree_rescan_sem);
3679 task = kthread_run(btrfs_uuid_rescan_kthread, fs_info, "btrfs-uuid");
3680 if (IS_ERR(task)) {
3681 /* fs_info->update_uuid_tree_gen remains 0 in all error case */
3682 pr_warn("btrfs: failed to start uuid_rescan task\n");
3683 up(&fs_info->uuid_tree_rescan_sem);
3684 return PTR_ERR(task);
3685 }
3686
3687 return 0;
3688}
3689
3607/* 3690/*
3608 * shrinking a device means finding all of the device extents past 3691 * shrinking a device means finding all of the device extents past
3609 * the new size, and then following the back refs to the chunks. 3692 * the new size, and then following the back refs to the chunks.