aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonathan E Brassow <jbrassow@redhat.com>2011-10-31 16:21:24 -0400
committerAlasdair G Kergon <agk@redhat.com>2011-10-31 16:21:24 -0400
commit5a25f0eb707bbb4a5aaaf19c933605a6dbaf77a5 (patch)
tree62f9af5013d252b0fdff5449b3adcaeadfff31aa
parentb89544575d0096735edc9b0ad187e635487905ad (diff)
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: Jonathan Brassow <jbrassow@redhat.com> Signed-off-by: Alasdair G Kergon <agk@redhat.com>
-rw-r--r--drivers/md/dm-log-userspace-base.c35
-rw-r--r--include/linux/dm-log-userspace.h18
2 files changed, 45 insertions, 8 deletions
diff --git a/drivers/md/dm-log-userspace-base.c b/drivers/md/dm-log-userspace-base.c
index 3c27978890b7..8db3862dade5 100644
--- a/drivers/md/dm-log-userspace-base.c
+++ b/drivers/md/dm-log-userspace-base.c
@@ -30,6 +30,7 @@ struct flush_entry {
30 30
31struct log_c { 31struct log_c {
32 struct dm_target *ti; 32 struct dm_target *ti;
33 struct dm_dev *log_dev;
33 uint32_t region_size; 34 uint32_t region_size;
34 region_t region_count; 35 region_t region_count;
35 uint64_t luid; 36 uint64_t luid;
@@ -161,13 +162,15 @@ static int userspace_ctr(struct dm_dirty_log *log, struct dm_target *ti,
161 struct log_c *lc = NULL; 162 struct log_c *lc = NULL;
162 uint64_t rdata; 163 uint64_t rdata;
163 size_t rdata_size = sizeof(rdata); 164 size_t rdata_size = sizeof(rdata);
165 char *devices_rdata = NULL;
166 size_t devices_rdata_size = DM_NAME_LEN;
164 167
165 if (argc < 3) { 168 if (argc < 3) {
166 DMWARN("Too few arguments to userspace dirty log"); 169 DMWARN("Too few arguments to userspace dirty log");
167 return -EINVAL; 170 return -EINVAL;
168 } 171 }
169 172
170 lc = kmalloc(sizeof(*lc), GFP_KERNEL); 173 lc = kzalloc(sizeof(*lc), GFP_KERNEL);
171 if (!lc) { 174 if (!lc) {
172 DMWARN("Unable to allocate userspace log context."); 175 DMWARN("Unable to allocate userspace log context.");
173 return -ENOMEM; 176 return -ENOMEM;
@@ -195,9 +198,19 @@ static int userspace_ctr(struct dm_dirty_log *log, struct dm_target *ti,
195 return str_size; 198 return str_size;
196 } 199 }
197 200
198 /* Send table string */ 201 devices_rdata = kzalloc(devices_rdata_size, GFP_KERNEL);
202 if (!devices_rdata) {
203 DMERR("Failed to allocate memory for device information");
204 r = -ENOMEM;
205 goto out;
206 }
207
208 /*
209 * Send table string and get back any opened device.
210 */
199 r = dm_consult_userspace(lc->uuid, lc->luid, DM_ULOG_CTR, 211 r = dm_consult_userspace(lc->uuid, lc->luid, DM_ULOG_CTR,
200 ctr_str, str_size, NULL, NULL); 212 ctr_str, str_size,
213 devices_rdata, &devices_rdata_size);
201 214
202 if (r < 0) { 215 if (r < 0) {
203 if (r == -ESRCH) 216 if (r == -ESRCH)
@@ -220,7 +233,20 @@ static int userspace_ctr(struct dm_dirty_log *log, struct dm_target *ti,
220 lc->region_size = (uint32_t)rdata; 233 lc->region_size = (uint32_t)rdata;
221 lc->region_count = dm_sector_div_up(ti->len, lc->region_size); 234 lc->region_count = dm_sector_div_up(ti->len, lc->region_size);
222 235
236 if (devices_rdata_size) {
237 if (devices_rdata[devices_rdata_size - 1] != '\0') {
238 DMERR("DM_ULOG_CTR device return string not properly terminated");
239 r = -EINVAL;
240 goto out;
241 }
242 r = dm_get_device(ti, devices_rdata,
243 dm_table_get_mode(ti->table), &lc->log_dev);
244 if (r)
245 DMERR("Failed to register %s with device-mapper",
246 devices_rdata);
247 }
223out: 248out:
249 kfree(devices_rdata);
224 if (r) { 250 if (r) {
225 kfree(lc); 251 kfree(lc);
226 kfree(ctr_str); 252 kfree(ctr_str);
@@ -241,6 +267,9 @@ static void userspace_dtr(struct dm_dirty_log *log)
241 NULL, 0, 267 NULL, 0,
242 NULL, NULL); 268 NULL, NULL);
243 269
270 if (lc->log_dev)
271 dm_put_device(lc->ti, lc->log_dev);
272
244 kfree(lc->usr_argv_str); 273 kfree(lc->usr_argv_str);
245 kfree(lc); 274 kfree(lc);
246 275
diff --git a/include/linux/dm-log-userspace.h b/include/linux/dm-log-userspace.h
index eeace7d3ff15..0678c2adc421 100644
--- a/include/linux/dm-log-userspace.h
+++ b/include/linux/dm-log-userspace.h
@@ -52,15 +52,20 @@
52 * Payload-to-userspace: 52 * Payload-to-userspace:
53 * A single string containing all the argv arguments separated by ' 's 53 * A single string containing all the argv arguments separated by ' 's
54 * Payload-to-kernel: 54 * Payload-to-kernel:
55 * None. ('data_size' in the dm_ulog_request struct should be 0.) 55 * A NUL-terminated string that is the name of the device that is used
56 * as the backing store for the log data. 'dm_get_device' will be called
57 * on this device. ('dm_put_device' will be called on this device
58 * automatically after calling DM_ULOG_DTR.) If there is no device needed
59 * for log data, 'data_size' in the dm_ulog_request struct should be 0.
56 * 60 *
57 * The UUID contained in the dm_ulog_request structure is the reference that 61 * The UUID contained in the dm_ulog_request structure is the reference that
58 * will be used by all request types to a specific log. The constructor must 62 * will be used by all request types to a specific log. The constructor must
59 * record this assotiation with instance created. 63 * record this association with the instance created.
60 * 64 *
61 * When the request has been processed, user-space must return the 65 * When the request has been processed, user-space must return the
62 * dm_ulog_request to the kernel - setting the 'error' field and 66 * dm_ulog_request to the kernel - setting the 'error' field, filling the
63 * 'data_size' appropriately. 67 * data field with the log device if necessary, and setting 'data_size'
68 * appropriately.
64 */ 69 */
65#define DM_ULOG_CTR 1 70#define DM_ULOG_CTR 1
66 71
@@ -377,8 +382,11 @@
377 * dm_ulog_request or a change in the way requests are 382 * dm_ulog_request or a change in the way requests are
378 * issued/handled. Changes are outlined here: 383 * issued/handled. Changes are outlined here:
379 * version 1: Initial implementation 384 * version 1: Initial implementation
385 * version 2: DM_ULOG_CTR allowed to return a string containing a
386 * device name that is to be registered with DM via
387 * 'dm_get_device'.
380 */ 388 */
381#define DM_ULOG_REQUEST_VERSION 1 389#define DM_ULOG_REQUEST_VERSION 2
382 390
383struct dm_ulog_request { 391struct dm_ulog_request {
384 /* 392 /*