Commit 84c89557a302e18414a011cc52b1abd034860743

Authored by Peter Jones
Committed by Alasdair G Kergon
1 parent d9bf0b508d

dm ioctl: allow rename to fill empty uuid

Allow the uuid of a mapped device to be set after device creation.
Previously the uuid (which is optional) could only be set by
DM_DEV_CREATE.  If no uuid was supplied it could not be set later.

Sometimes it's necessary to create the device before the uuid is known,
and in such cases the uuid must be filled in after the creation.

This patch extends DM_DEV_RENAME to accept a uuid accompanied by
a new flag DM_UUID_FLAG.  This can only be done once and if no
uuid was previously supplied.  It cannot be used to change an
existing uuid.

DM_VERSION_MINOR is also bumped to 19 to indicate this interface
extension is available.

Signed-off-by: Peter Jones <pjones@redhat.com>
Signed-off-by: Jonathan Brassow <jbrassow@redhat.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>

Showing 2 changed files with 87 additions and 28 deletions Side-by-side Diff

drivers/md/dm-ioctl.c
... ... @@ -295,19 +295,55 @@
295 295 DMWARN("remove_all left %d open device(s)", dev_skipped);
296 296 }
297 297  
  298 +/*
  299 + * Set the uuid of a hash_cell that isn't already set.
  300 + */
  301 +static void __set_cell_uuid(struct hash_cell *hc, char *new_uuid)
  302 +{
  303 + mutex_lock(&dm_hash_cells_mutex);
  304 + hc->uuid = new_uuid;
  305 + mutex_unlock(&dm_hash_cells_mutex);
  306 +
  307 + list_add(&hc->uuid_list, _uuid_buckets + hash_str(new_uuid));
  308 +}
  309 +
  310 +/*
  311 + * Changes the name of a hash_cell and returns the old name for
  312 + * the caller to free.
  313 + */
  314 +static char *__change_cell_name(struct hash_cell *hc, char *new_name)
  315 +{
  316 + char *old_name;
  317 +
  318 + /*
  319 + * Rename and move the name cell.
  320 + */
  321 + list_del(&hc->name_list);
  322 + old_name = hc->name;
  323 +
  324 + mutex_lock(&dm_hash_cells_mutex);
  325 + hc->name = new_name;
  326 + mutex_unlock(&dm_hash_cells_mutex);
  327 +
  328 + list_add(&hc->name_list, _name_buckets + hash_str(new_name));
  329 +
  330 + return old_name;
  331 +}
  332 +
298 333 static struct mapped_device *dm_hash_rename(struct dm_ioctl *param,
299 334 const char *new)
300 335 {
301   - char *new_name, *old_name;
  336 + char *new_data, *old_name = NULL;
302 337 struct hash_cell *hc;
303 338 struct dm_table *table;
304 339 struct mapped_device *md;
  340 + unsigned change_uuid = (param->flags & DM_UUID_FLAG) ? 1 : 0;
305 341  
306 342 /*
307 343 * duplicate new.
308 344 */
309   - new_name = kstrdup(new, GFP_KERNEL);
310   - if (!new_name)
  345 + new_data = kstrdup(new, GFP_KERNEL);
  346 + if (!new_data)
311 347 return ERR_PTR(-ENOMEM);
312 348  
313 349 down_write(&_hash_lock);
314 350  
315 351  
... ... @@ -315,13 +351,19 @@
315 351 /*
316 352 * Is new free ?
317 353 */
318   - hc = __get_name_cell(new);
  354 + if (change_uuid)
  355 + hc = __get_uuid_cell(new);
  356 + else
  357 + hc = __get_name_cell(new);
  358 +
319 359 if (hc) {
320   - DMWARN("asked to rename to an already-existing name %s -> %s",
  360 + DMWARN("Unable to change %s on mapped device %s to one that "
  361 + "already exists: %s",
  362 + change_uuid ? "uuid" : "name",
321 363 param->name, new);
322 364 dm_put(hc->md);
323 365 up_write(&_hash_lock);
324   - kfree(new_name);
  366 + kfree(new_data);
325 367 return ERR_PTR(-EBUSY);
326 368 }
327 369  
328 370  
329 371  
330 372  
331 373  
... ... @@ -330,23 +372,31 @@
330 372 */
331 373 hc = __get_name_cell(param->name);
332 374 if (!hc) {
333   - DMWARN("asked to rename a non-existent device %s -> %s",
334   - param->name, new);
  375 + DMWARN("Unable to rename non-existent device, %s to %s%s",
  376 + param->name, change_uuid ? "uuid " : "", new);
335 377 up_write(&_hash_lock);
336   - kfree(new_name);
  378 + kfree(new_data);
337 379 return ERR_PTR(-ENXIO);
338 380 }
339 381  
340 382 /*
341   - * rename and move the name cell.
  383 + * Does this device already have a uuid?
342 384 */
343   - list_del(&hc->name_list);
344   - old_name = hc->name;
345   - mutex_lock(&dm_hash_cells_mutex);
346   - hc->name = new_name;
347   - mutex_unlock(&dm_hash_cells_mutex);
348   - list_add(&hc->name_list, _name_buckets + hash_str(new_name));
  385 + if (change_uuid && hc->uuid) {
  386 + DMWARN("Unable to change uuid of mapped device %s to %s "
  387 + "because uuid is already set to %s",
  388 + param->name, new, hc->uuid);
  389 + dm_put(hc->md);
  390 + up_write(&_hash_lock);
  391 + kfree(new_data);
  392 + return ERR_PTR(-EINVAL);
  393 + }
349 394  
  395 + if (change_uuid)
  396 + __set_cell_uuid(hc, new_data);
  397 + else
  398 + old_name = __change_cell_name(hc, new_data);
  399 +
350 400 /*
351 401 * Wake up any dm event waiters.
352 402 */
353 403  
354 404  
355 405  
356 406  
... ... @@ -774,21 +824,24 @@
774 824 static int dev_rename(struct dm_ioctl *param, size_t param_size)
775 825 {
776 826 int r;
777   - char *new_name = (char *) param + param->data_start;
  827 + char *new_data = (char *) param + param->data_start;
778 828 struct mapped_device *md;
  829 + unsigned change_uuid = (param->flags & DM_UUID_FLAG) ? 1 : 0;
779 830  
780   - if (new_name < param->data ||
781   - invalid_str(new_name, (void *) param + param_size) ||
782   - strlen(new_name) > DM_NAME_LEN - 1) {
783   - DMWARN("Invalid new logical volume name supplied.");
  831 + if (new_data < param->data ||
  832 + invalid_str(new_data, (void *) param + param_size) ||
  833 + strlen(new_data) > (change_uuid ? DM_UUID_LEN - 1 : DM_NAME_LEN - 1)) {
  834 + DMWARN("Invalid new mapped device name or uuid string supplied.");
784 835 return -EINVAL;
785 836 }
786 837  
787   - r = check_name(new_name);
788   - if (r)
789   - return r;
  838 + if (!change_uuid) {
  839 + r = check_name(new_data);
  840 + if (r)
  841 + return r;
  842 + }
790 843  
791   - md = dm_hash_rename(param, new_name);
  844 + md = dm_hash_rename(param, new_data);
792 845 if (IS_ERR(md))
793 846 return PTR_ERR(md);
794 847  
include/linux/dm-ioctl.h
... ... @@ -44,7 +44,7 @@
44 44 * Remove a device, destroy any tables.
45 45 *
46 46 * DM_DEV_RENAME:
47   - * Rename a device.
  47 + * Rename a device or set its uuid if none was previously supplied.
48 48 *
49 49 * DM_SUSPEND:
50 50 * This performs both suspend and resume, depending which flag is
51 51  
... ... @@ -267,9 +267,9 @@
267 267 #define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl)
268 268  
269 269 #define DM_VERSION_MAJOR 4
270   -#define DM_VERSION_MINOR 18
  270 +#define DM_VERSION_MINOR 19
271 271 #define DM_VERSION_PATCHLEVEL 0
272   -#define DM_VERSION_EXTRA "-ioctl (2010-06-29)"
  272 +#define DM_VERSION_EXTRA "-ioctl (2010-10-14)"
273 273  
274 274 /* Status bits */
275 275 #define DM_READONLY_FLAG (1 << 0) /* In/Out */
... ... @@ -321,6 +321,12 @@
321 321 * If set, a uevent was generated for which the caller may need to wait.
322 322 */
323 323 #define DM_UEVENT_GENERATED_FLAG (1 << 13) /* Out */
  324 +
  325 +/*
  326 + * If set, rename changes the uuid not the name. Only permitted
  327 + * if no uuid was previously supplied: an existing uuid cannot be changed.
  328 + */
  329 +#define DM_UUID_FLAG (1 << 14) /* In */
324 330  
325 331 #endif /* _LINUX_DM_IOCTL_H */