diff --git a/test/shell/writecache-large.sh b/test/shell/writecache-large.sh index fc8f379cf..9a5a9f1dd 100644 --- a/test/shell/writecache-large.sh +++ b/test/shell/writecache-large.sh @@ -149,5 +149,34 @@ lvchange -an $vg/$lv2 lvremove $vg/$lv1 lvremove $vg/$lv2 +# Repeat similar using uncache + +lvcreate -n $lv1 -L 560M -an $vg "$dev1" +lvcreate -n $lv2 -L 500M -an $vg "$dev2" + +lvchange -ay $vg/$lv1 +lvconvert --yes --type writecache --cachevol $lv2 $vg/$lv1 + +_add_new_data_to_mnt +_add_more_data_to_mnt +dd if=/dev/zero of=$mnt/big1 bs=1M count=100 oflag=sync + +umount $mnt +lvchange -an $vg/$lv1 + +lvconvert --uncache $vg/$lv1 + +check lv_field $vg/$lv1 segtype linear +not lvs $vg/$lv2 + +lvchange -ay $vg/$lv1 +mount "$DM_DEV_DIR/$vg/$lv1" $mnt + +_verify_data_on_mnt +_verify_more_data_on_mnt + +umount $mnt +lvchange -an $vg/$lv1 + vgremove -ff $vg diff --git a/test/shell/writecache-split.sh b/test/shell/writecache-split.sh index e615e2a13..d1b14bfd3 100644 --- a/test/shell/writecache-split.sh +++ b/test/shell/writecache-split.sh @@ -171,5 +171,51 @@ lvconvert -y --type writecache --cachevol $lv2 $vg/$lv1 fail vgsplit $vg $vg1 "$dev2" fail vgsplit $vg $vg1 "$dev3" lvremove $vg/$lv1 +vgremove $vg + +# +# uncache +# +vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3" "$dev4" + +# while inactive + +lvcreate -n $lv1 -l 16 -an $vg "$dev1" "$dev4" +lvcreate -n $lv2 -l 4 -an $vg "$dev2" + +lvconvert -y --type writecache --cachevol $lv2 $vg/$lv1 + +lvchange -ay $vg/$lv1 +mkfs_mount_umount $lv1 +lvchange -an $vg/$lv1 + +lvconvert --uncache $vg/$lv1 +lvs -o segtype $vg/$lv1 | grep linear +not lvs $vg/$lv2 + +lvchange -ay $vg/$lv1 +mount_umount $lv1 +lvchange -an $vg/$lv1 +lvremove -y $vg/$lv1 + +# while active + +lvcreate -n $lv1 -l 16 -an $vg "$dev1" "$dev4" +lvcreate -n $lv2 -l 4 -an $vg "$dev2" + +lvconvert -y --type writecache --cachevol $lv2 $vg/$lv1 + +lvchange -ay $vg/$lv1 +mkfs_mount_umount $lv1 + +lvconvert --uncache $vg/$lv1 +lvs -o segtype $vg/$lv1 | grep linear +not lvs $vg/$lv2 + +lvchange -an $vg/$lv1 +lvchange -ay $vg/$lv1 +mount_umount $lv1 +lvchange -an $vg/$lv1 +lvremove -y $vg/$lv1 vgremove -ff $vg diff --git a/tools/lvconvert.c b/tools/lvconvert.c index 7d5a541d0..432396567 100644 --- a/tools/lvconvert.c +++ b/tools/lvconvert.c @@ -3662,6 +3662,7 @@ struct lvconvert_result { unsigned need_polling:1; unsigned wait_cleaner_writecache:1; unsigned active_begin:1; + unsigned remove_cache:1; struct dm_list poll_idls; }; @@ -4966,8 +4967,18 @@ static int _lvconvert_split_cache_single(struct cmd_context *cmd, return ECMD_FAILED; if (cmd->command->command_enum == lvconvert_split_and_remove_cache_CMD) { - if (lvremove_single(cmd, lv_fast, NULL) != ECMD_PROCESSED) - return ECMD_FAILED; + struct lvconvert_result *lr = (struct lvconvert_result *) handle->custom_handle; + /* + * If detach is ongoing, then the remove needs to wait + * until _lvconvert_detach_writecache_when_clean(), + * after the detach has finished. When lr->remove_cache + * has been set, when_clean() knows it should remove + * lv_fast at the end. + */ + if (!lr->wait_cleaner_writecache) { + if (lvremove_single(cmd, lv_fast, NULL) != ECMD_PROCESSED) + return ECMD_FAILED; + } } ret = 1; } else if (lv_is_cache(lv_main) && lv_is_cache_vol(lv_fast)) { @@ -5637,6 +5648,10 @@ static int _lvconvert_detach_writecache(struct cmd_context *cmd, lr->wait_cleaner_writecache = 1; lr->active_begin = active_begin; + /* The command wants to remove the cache after detaching. */ + if (cmd->command->command_enum == lvconvert_split_and_remove_cache_CMD) + lr->remove_cache = 1; + dm_list_add(&lr->poll_idls, &idl->list); return 1; } @@ -5679,6 +5694,7 @@ static int _lvconvert_detach_writecache_when_clean(struct cmd_context *cmd, struct poll_operation_id *id; struct volume_group *vg; struct logical_volume *lv; + struct logical_volume *lv_fast; uint32_t lockd_state, error_flags; uint64_t dirty; int ret; @@ -5759,6 +5775,8 @@ static int _lvconvert_detach_writecache_when_clean(struct cmd_context *cmd, log_print("Detaching writecache completed cleaning."); + lv_fast = first_seg(lv)->writecache; + /* * When the cleaner has finished, we can detach with noflush since * the cleaner has done the flushing. @@ -5770,6 +5788,17 @@ static int _lvconvert_detach_writecache_when_clean(struct cmd_context *cmd, goto out_release; } + /* + * The detach was started by an uncache command that wants to remove + * the cachevol after detaching. + */ + if (lr->remove_cache) { + if (lvremove_single(cmd, lv_fast, NULL) != ECMD_PROCESSED) { + log_error("Removing the writecache cachevol failed."); + ret = 0; + } + } + ret = 1; backup(vg);