Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 230663
b: refs/heads/master
c: 84c8955
h: refs/heads/master
i:
  230661: d929ad7
  230659: 40dbea3
  230655: 09898ce
v: v3
  • Loading branch information
Peter Jones authored and Alasdair G Kergon committed Jan 13, 2011
1 parent 96c3b24 commit 9e1fa36
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 29 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: d9bf0b508ddfe19883b982b29a03c02ccbf53806
refs/heads/master: 84c89557a302e18414a011cc52b1abd034860743
103 changes: 78 additions & 25 deletions trunk/drivers/md/dm-ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -295,33 +295,75 @@ static void dm_hash_remove_all(int keep_open_devices)
DMWARN("remove_all left %d open device(s)", dev_skipped);
}

/*
* Set the uuid of a hash_cell that isn't already set.
*/
static void __set_cell_uuid(struct hash_cell *hc, char *new_uuid)
{
mutex_lock(&dm_hash_cells_mutex);
hc->uuid = new_uuid;
mutex_unlock(&dm_hash_cells_mutex);

list_add(&hc->uuid_list, _uuid_buckets + hash_str(new_uuid));
}

/*
* Changes the name of a hash_cell and returns the old name for
* the caller to free.
*/
static char *__change_cell_name(struct hash_cell *hc, char *new_name)
{
char *old_name;

/*
* Rename and move the name cell.
*/
list_del(&hc->name_list);
old_name = hc->name;

mutex_lock(&dm_hash_cells_mutex);
hc->name = new_name;
mutex_unlock(&dm_hash_cells_mutex);

list_add(&hc->name_list, _name_buckets + hash_str(new_name));

return old_name;
}

static struct mapped_device *dm_hash_rename(struct dm_ioctl *param,
const char *new)
{
char *new_name, *old_name;
char *new_data, *old_name = NULL;
struct hash_cell *hc;
struct dm_table *table;
struct mapped_device *md;
unsigned change_uuid = (param->flags & DM_UUID_FLAG) ? 1 : 0;

/*
* duplicate new.
*/
new_name = kstrdup(new, GFP_KERNEL);
if (!new_name)
new_data = kstrdup(new, GFP_KERNEL);
if (!new_data)
return ERR_PTR(-ENOMEM);

down_write(&_hash_lock);

/*
* Is new free ?
*/
hc = __get_name_cell(new);
if (change_uuid)
hc = __get_uuid_cell(new);
else
hc = __get_name_cell(new);

if (hc) {
DMWARN("asked to rename to an already-existing name %s -> %s",
DMWARN("Unable to change %s on mapped device %s to one that "
"already exists: %s",
change_uuid ? "uuid" : "name",
param->name, new);
dm_put(hc->md);
up_write(&_hash_lock);
kfree(new_name);
kfree(new_data);
return ERR_PTR(-EBUSY);
}

Expand All @@ -330,22 +372,30 @@ static struct mapped_device *dm_hash_rename(struct dm_ioctl *param,
*/
hc = __get_name_cell(param->name);
if (!hc) {
DMWARN("asked to rename a non-existent device %s -> %s",
param->name, new);
DMWARN("Unable to rename non-existent device, %s to %s%s",
param->name, change_uuid ? "uuid " : "", new);
up_write(&_hash_lock);
kfree(new_name);
kfree(new_data);
return ERR_PTR(-ENXIO);
}

/*
* rename and move the name cell.
* Does this device already have a uuid?
*/
list_del(&hc->name_list);
old_name = hc->name;
mutex_lock(&dm_hash_cells_mutex);
hc->name = new_name;
mutex_unlock(&dm_hash_cells_mutex);
list_add(&hc->name_list, _name_buckets + hash_str(new_name));
if (change_uuid && hc->uuid) {
DMWARN("Unable to change uuid of mapped device %s to %s "
"because uuid is already set to %s",
param->name, new, hc->uuid);
dm_put(hc->md);
up_write(&_hash_lock);
kfree(new_data);
return ERR_PTR(-EINVAL);
}

if (change_uuid)
__set_cell_uuid(hc, new_data);
else
old_name = __change_cell_name(hc, new_data);

/*
* Wake up any dm event waiters.
Expand Down Expand Up @@ -774,21 +824,24 @@ static int invalid_str(char *str, void *end)
static int dev_rename(struct dm_ioctl *param, size_t param_size)
{
int r;
char *new_name = (char *) param + param->data_start;
char *new_data = (char *) param + param->data_start;
struct mapped_device *md;
unsigned change_uuid = (param->flags & DM_UUID_FLAG) ? 1 : 0;

if (new_name < param->data ||
invalid_str(new_name, (void *) param + param_size) ||
strlen(new_name) > DM_NAME_LEN - 1) {
DMWARN("Invalid new logical volume name supplied.");
if (new_data < param->data ||
invalid_str(new_data, (void *) param + param_size) ||
strlen(new_data) > (change_uuid ? DM_UUID_LEN - 1 : DM_NAME_LEN - 1)) {
DMWARN("Invalid new mapped device name or uuid string supplied.");
return -EINVAL;
}

r = check_name(new_name);
if (r)
return r;
if (!change_uuid) {
r = check_name(new_data);
if (r)
return r;
}

md = dm_hash_rename(param, new_name);
md = dm_hash_rename(param, new_data);
if (IS_ERR(md))
return PTR_ERR(md);

Expand Down
12 changes: 9 additions & 3 deletions trunk/include/linux/dm-ioctl.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
* Remove a device, destroy any tables.
*
* DM_DEV_RENAME:
* Rename a device.
* Rename a device or set its uuid if none was previously supplied.
*
* DM_SUSPEND:
* This performs both suspend and resume, depending which flag is
Expand Down Expand Up @@ -267,9 +267,9 @@ enum {
#define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl)

#define DM_VERSION_MAJOR 4
#define DM_VERSION_MINOR 18
#define DM_VERSION_MINOR 19
#define DM_VERSION_PATCHLEVEL 0
#define DM_VERSION_EXTRA "-ioctl (2010-06-29)"
#define DM_VERSION_EXTRA "-ioctl (2010-10-14)"

/* Status bits */
#define DM_READONLY_FLAG (1 << 0) /* In/Out */
Expand Down Expand Up @@ -322,4 +322,10 @@ enum {
*/
#define DM_UEVENT_GENERATED_FLAG (1 << 13) /* Out */

/*
* If set, rename changes the uuid not the name. Only permitted
* if no uuid was previously supplied: an existing uuid cannot be changed.
*/
#define DM_UUID_FLAG (1 << 14) /* In */

#endif /* _LINUX_DM_IOCTL_H */

0 comments on commit 9e1fa36

Please sign in to comment.