Commit 5a25f0eb authored by Jonathan E Brassow's avatar Jonathan E Brassow Committed by Alasdair G Kergon

dm log userspace: add log device dependency

Allow userspace dm log implementations to register their log device so it
is no longer missing from the list of device dependencies.

When device mapper targets use a device they normally call dm_get_device
which includes it in the device list returned to userspace applications
such as LVM through the DM_TABLE_DEPS ioctl.  Userspace log devices
don't use dm_get_device as userspace opens them so they are missing from
the list of dependencies.

This patch extends the DM_ULOG_CTR operation to allow userspace to
respond with the name of the log device (if appropriate) to be
registered via 'dm_get_device'.  DM_ULOG_REQUEST_VERSION is incremented.

This is backwards compatible.  If the kernel and userspace log server
have both been updated, the new information will be passed down to the
kernel and the device will be registered.  If the kernel is new, but
the log server is old, the log server will not pass down any device
information and the kernel will simply bypass the device registration
as before.  If the kernel is old but the log server is new, the log
server will see the old version number and not pass the device info.
Signed-off-by: default avatarJonathan Brassow <jbrassow@redhat.com>
Signed-off-by: default avatarAlasdair G Kergon <agk@redhat.com>
parent b8954457
...@@ -30,6 +30,7 @@ struct flush_entry { ...@@ -30,6 +30,7 @@ struct flush_entry {
struct log_c { struct log_c {
struct dm_target *ti; struct dm_target *ti;
struct dm_dev *log_dev;
uint32_t region_size; uint32_t region_size;
region_t region_count; region_t region_count;
uint64_t luid; uint64_t luid;
...@@ -161,13 +162,15 @@ static int userspace_ctr(struct dm_dirty_log *log, struct dm_target *ti, ...@@ -161,13 +162,15 @@ static int userspace_ctr(struct dm_dirty_log *log, struct dm_target *ti,
struct log_c *lc = NULL; struct log_c *lc = NULL;
uint64_t rdata; uint64_t rdata;
size_t rdata_size = sizeof(rdata); size_t rdata_size = sizeof(rdata);
char *devices_rdata = NULL;
size_t devices_rdata_size = DM_NAME_LEN;
if (argc < 3) { if (argc < 3) {
DMWARN("Too few arguments to userspace dirty log"); DMWARN("Too few arguments to userspace dirty log");
return -EINVAL; return -EINVAL;
} }
lc = kmalloc(sizeof(*lc), GFP_KERNEL); lc = kzalloc(sizeof(*lc), GFP_KERNEL);
if (!lc) { if (!lc) {
DMWARN("Unable to allocate userspace log context."); DMWARN("Unable to allocate userspace log context.");
return -ENOMEM; return -ENOMEM;
...@@ -195,9 +198,19 @@ static int userspace_ctr(struct dm_dirty_log *log, struct dm_target *ti, ...@@ -195,9 +198,19 @@ static int userspace_ctr(struct dm_dirty_log *log, struct dm_target *ti,
return str_size; return str_size;
} }
/* Send table string */ devices_rdata = kzalloc(devices_rdata_size, GFP_KERNEL);
if (!devices_rdata) {
DMERR("Failed to allocate memory for device information");
r = -ENOMEM;
goto out;
}
/*
* Send table string and get back any opened device.
*/
r = dm_consult_userspace(lc->uuid, lc->luid, DM_ULOG_CTR, r = dm_consult_userspace(lc->uuid, lc->luid, DM_ULOG_CTR,
ctr_str, str_size, NULL, NULL); ctr_str, str_size,
devices_rdata, &devices_rdata_size);
if (r < 0) { if (r < 0) {
if (r == -ESRCH) if (r == -ESRCH)
...@@ -220,7 +233,20 @@ static int userspace_ctr(struct dm_dirty_log *log, struct dm_target *ti, ...@@ -220,7 +233,20 @@ static int userspace_ctr(struct dm_dirty_log *log, struct dm_target *ti,
lc->region_size = (uint32_t)rdata; lc->region_size = (uint32_t)rdata;
lc->region_count = dm_sector_div_up(ti->len, lc->region_size); lc->region_count = dm_sector_div_up(ti->len, lc->region_size);
if (devices_rdata_size) {
if (devices_rdata[devices_rdata_size - 1] != '\0') {
DMERR("DM_ULOG_CTR device return string not properly terminated");
r = -EINVAL;
goto out;
}
r = dm_get_device(ti, devices_rdata,
dm_table_get_mode(ti->table), &lc->log_dev);
if (r)
DMERR("Failed to register %s with device-mapper",
devices_rdata);
}
out: out:
kfree(devices_rdata);
if (r) { if (r) {
kfree(lc); kfree(lc);
kfree(ctr_str); kfree(ctr_str);
...@@ -241,6 +267,9 @@ static void userspace_dtr(struct dm_dirty_log *log) ...@@ -241,6 +267,9 @@ static void userspace_dtr(struct dm_dirty_log *log)
NULL, 0, NULL, 0,
NULL, NULL); NULL, NULL);
if (lc->log_dev)
dm_put_device(lc->ti, lc->log_dev);
kfree(lc->usr_argv_str); kfree(lc->usr_argv_str);
kfree(lc); kfree(lc);
......
...@@ -52,15 +52,20 @@ ...@@ -52,15 +52,20 @@
* Payload-to-userspace: * Payload-to-userspace:
* A single string containing all the argv arguments separated by ' 's * A single string containing all the argv arguments separated by ' 's
* Payload-to-kernel: * Payload-to-kernel:
* None. ('data_size' in the dm_ulog_request struct should be 0.) * A NUL-terminated string that is the name of the device that is used
* as the backing store for the log data. 'dm_get_device' will be called
* on this device. ('dm_put_device' will be called on this device
* automatically after calling DM_ULOG_DTR.) If there is no device needed
* for log data, 'data_size' in the dm_ulog_request struct should be 0.
* *
* The UUID contained in the dm_ulog_request structure is the reference that * The UUID contained in the dm_ulog_request structure is the reference that
* will be used by all request types to a specific log. The constructor must * will be used by all request types to a specific log. The constructor must
* record this assotiation with instance created. * record this association with the instance created.
* *
* When the request has been processed, user-space must return the * When the request has been processed, user-space must return the
* dm_ulog_request to the kernel - setting the 'error' field and * dm_ulog_request to the kernel - setting the 'error' field, filling the
* 'data_size' appropriately. * data field with the log device if necessary, and setting 'data_size'
* appropriately.
*/ */
#define DM_ULOG_CTR 1 #define DM_ULOG_CTR 1
...@@ -377,8 +382,11 @@ ...@@ -377,8 +382,11 @@
* dm_ulog_request or a change in the way requests are * dm_ulog_request or a change in the way requests are
* issued/handled. Changes are outlined here: * issued/handled. Changes are outlined here:
* version 1: Initial implementation * version 1: Initial implementation
* version 2: DM_ULOG_CTR allowed to return a string containing a
* device name that is to be registered with DM via
* 'dm_get_device'.
*/ */
#define DM_ULOG_REQUEST_VERSION 1 #define DM_ULOG_REQUEST_VERSION 2
struct dm_ulog_request { struct dm_ulog_request {
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment