dmsetup: provide deferred remove feature This patch adds a new flag --deferred to dmsetup remove. If this flag is specified and the device is open, it is scheduled to be deleted on close. Signed-off-by: Mikulas Patocka --- libdm/ioctl/libdm-iface.c | 16 ++++++++++++++-- libdm/ioctl/libdm-targets.h | 1 + libdm/libdevmapper.h | 2 ++ libdm/misc/dm-ioctl.h | 14 ++++++++++++++ tools/dmsetup.c | 14 +++++++++++--- 5 files changed, 42 insertions(+), 5 deletions(-) Index: lvm2-copy/tools/dmsetup.c =================================================================== --- lvm2-copy.orig/tools/dmsetup.c 2013-09-16 21:15:49.000000000 +0200 +++ lvm2-copy/tools/dmsetup.c 2013-09-16 21:17:15.000000000 +0200 @@ -120,6 +120,7 @@ enum { ADD_NODE_ON_RESUME_ARG, CHECKS_ARG, COLS_ARG, + DEFERRED_ARG, EXEC_ARG, FORCE_ARG, GID_ARG, @@ -467,9 +468,10 @@ static void _display_info_long(struct dm printf("Name: %s\n", dm_task_get_name(dmt)); - printf("State: %s%s\n", + printf("State: %s%s%s\n", info->suspended ? "SUSPENDED" : "ACTIVE", - info->read_only ? " (READ-ONLY)" : ""); + info->read_only ? " (READ-ONLY)" : "", + info->deferred_remove ? " (DEFERRED REMOVE)" : ""); /* FIXME Old value is being printed when it's being changed. */ if (dm_task_get_read_ahead(dmt, &read_ahead)) @@ -1320,6 +1322,9 @@ static int _simple(int task, const char if (_switches[RETRY_ARG] && task == DM_DEVICE_REMOVE) dm_task_retry_remove(dmt); + if (_switches[DEFERRED_ARG] && (task == DM_DEVICE_REMOVE || task == DM_DEVICE_REMOVE_ALL)) + dm_task_deferred_remove(dmt); + r = dm_task_run(dmt); out: @@ -3059,7 +3064,7 @@ static struct command _commands[] = { "\t [-u|uuid ] [{--addnodeonresume|--addnodeoncreate}]\n" "\t [--notable | --table | ]", 1, 2,0, _create}, - {"remove", "[-f|--force] ", 0, -1, 1, _remove}, + {"remove", "[-f|--force] [--deferred] ", 0, -1, 1, _remove}, {"remove_all", "[-f|--force]", 0, 0, 0, _remove_all}, {"suspend", "[--noflush] ", 0, -1, 1, _suspend}, {"resume", " [{--addnodeonresume|--addnodeoncreate}]", 0, -1, 1, _resume}, @@ -3508,6 +3513,7 @@ static int _process_switches(int *argc, {"readonly", 0, &ind, READ_ONLY}, {"checks", 0, &ind, CHECKS_ARG}, {"columns", 0, &ind, COLS_ARG}, + {"deferred", 0, &ind, DEFERRED_ARG}, {"exec", 1, &ind, EXEC_ARG}, {"force", 0, &ind, FORCE_ARG}, {"gid", 1, &ind, GID_ARG}, @@ -3676,6 +3682,8 @@ static int _process_switches(int *argc, /* FIXME Accept modes as per chmod */ _int_args[MODE_ARG] = (int) strtol(optarg, NULL, 8); } + if (ind == DEFERRED_ARG) + _switches[DEFERRED_ARG]++; if (ind == EXEC_ARG) { _switches[EXEC_ARG]++; _command = optarg; Index: lvm2-copy/libdm/ioctl/libdm-iface.c =================================================================== --- lvm2-copy.orig/libdm/ioctl/libdm-iface.c 2013-09-16 21:15:49.000000000 +0200 +++ lvm2-copy/libdm/ioctl/libdm-iface.c 2013-09-16 21:17:15.000000000 +0200 @@ -653,6 +653,7 @@ int dm_task_get_info(struct dm_task *dmt info->live_table = dmt->dmi.v4->flags & DM_ACTIVE_PRESENT_FLAG ? 1 : 0; info->inactive_table = dmt->dmi.v4->flags & DM_INACTIVE_PRESENT_FLAG ? 1 : 0; + info->deferred_remove = dmt->dmi.v4->flags & DM_DEFERRED_REMOVE; info->target_count = dmt->dmi.v4->target_count; info->open_count = dmt->dmi.v4->open_count; info->event_nr = dmt->dmi.v4->event_nr; @@ -861,6 +862,13 @@ int dm_task_retry_remove(struct dm_task return 1; } +int dm_task_deferred_remove(struct dm_task *dmt) +{ + dmt->deferred_remove = 1; + + return 1; +} + int dm_task_query_inactive_table(struct dm_task *dmt) { dmt->query_inactive_table = 1; @@ -1136,6 +1144,9 @@ static struct dm_ioctl *_flatten(struct dmi->flags |= DM_READONLY_FLAG; if (dmt->skip_lockfs) dmi->flags |= DM_SKIP_LOCKFS_FLAG; + if (dmt->deferred_remove && (dmt->type == DM_DEVICE_REMOVE || dmt->type == DM_DEVICE_REMOVE_ALL)) + dmi->flags |= DM_DEFERRED_REMOVE; + if (dmt->secure_data) { if (_dm_version_minor < 20) log_verbose("Secure data flag unsupported by kernel. " @@ -1727,7 +1738,7 @@ static struct dm_ioctl *_do_dm_ioctl(str } log_debug_activation("dm %s %s%s %s%s%s %s%.0d%s%.0d%s" - "%s%c%c%s%s%s%s%s%s %.0" PRIu64 " %s [%u] (*%u)", + "%s%c%c%s%s%s%s%s%s%s %.0" PRIu64 " %s [%u] (*%u)", _cmd_data_v4[dmt->type].name, dmt->new_uuid ? "UUID " : "", dmi->name, dmi->uuid, dmt->newname ? " " : "", @@ -1743,6 +1754,7 @@ static struct dm_ioctl *_do_dm_ioctl(str dmt->read_only ? "R" : "", dmt->skip_lockfs ? "S " : "", dmt->retry_remove ? "T " : "", + dmt->deferred_remove ? "D " : "", dmt->secure_data ? "W " : "", dmt->query_inactive_table ? "I " : "", dmt->enable_checks ? "C" : "", @@ -1922,7 +1934,7 @@ repeat_ioctl: break; case DM_DEVICE_REMOVE: /* FIXME Kernel needs to fill in dmi->name */ - if (dev_name && !rely_on_udev) + if (dev_name && !rely_on_udev && !(dmi->flags & DM_DEFERRED_REMOVE)) rm_dev_node(dev_name, check_udev, rely_on_udev); break; Index: lvm2-copy/libdm/ioctl/libdm-targets.h =================================================================== --- lvm2-copy.orig/libdm/ioctl/libdm-targets.h 2013-09-16 21:15:49.000000000 +0200 +++ lvm2-copy/libdm/ioctl/libdm-targets.h 2013-09-16 21:17:15.000000000 +0200 @@ -65,6 +65,7 @@ struct dm_task { int new_uuid; int secure_data; int retry_remove; + int deferred_remove; int enable_checks; int expected_errno; Index: lvm2-copy/libdm/libdevmapper.h =================================================================== --- lvm2-copy.orig/libdm/libdevmapper.h 2013-09-16 21:15:50.000000000 +0200 +++ lvm2-copy/libdm/libdevmapper.h 2013-09-16 21:17:15.000000000 +0200 @@ -142,6 +142,7 @@ struct dm_info { int suspended; int live_table; int inactive_table; + int deferred_remove; int32_t open_count; uint32_t event_nr; uint32_t major; @@ -222,6 +223,7 @@ int dm_task_query_inactive_table(struct int dm_task_suppress_identical_reload(struct dm_task *dmt); int dm_task_secure_data(struct dm_task *dmt); int dm_task_retry_remove(struct dm_task *dmt); +int dm_task_deferred_remove(struct dm_task *dmt); /* * Enable checks for common mistakes such as issuing ioctls in an unsafe order. Index: lvm2-copy/libdm/misc/dm-ioctl.h =================================================================== --- lvm2-copy.orig/libdm/misc/dm-ioctl.h 2013-09-16 21:15:49.000000000 +0200 +++ lvm2-copy/libdm/misc/dm-ioctl.h 2013-09-16 21:17:15.000000000 +0200 @@ -343,4 +343,18 @@ enum { */ #define DM_DATA_OUT_FLAG (1 << 16) /* Out */ +/* + * Remove the device when it is closed. + * + * This flag may be set on DM_DEV_REMOVE or DM_REMOVE_ALL to indicate that + * the device should be remove on close if it is open. + * + * On return from DM_DEV_REMOVE, this flag indicates that the device was not + * removed because it was open, but it is scheduled to be removed on close. + * + * When this flag is returned in DM_DEV_STATUS or other ioctls, it indicates + * that the device is scheduled to be removed on close. + */ +#define DM_DEFERRED_REMOVE (1 << 17) /* In/Out */ + #endif /* _LINUX_DM_IOCTL_H */