[PATCH 2/2] imsm: volume rename functionality

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Functionality renames array by changing serial ID in the metadata.
Target array must be disassembled before an attempt to rename.

	mdadm --misc --update=name <new-name> [ -N <name> | -u <uuid> ] \
		<container-or-devlist>

<new-name> must follow --update (or -U),
<container-or-devlist> is the list of devices provided with the same rules
as delete subarray.

Signed-off-by: Przemyslaw Czarnowski <przemyslaw.hawrylewicz.czarnowski@xxxxxxxxx>
---
 Manage.c      |   95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 mdadm.c       |   18 +++++++++--
 mdadm.h       |    2 +
 super-intel.c |   93 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 205 insertions(+), 3 deletions(-)

diff --git a/Manage.c b/Manage.c
index f848d8b..ee15cfa 100644
--- a/Manage.c
+++ b/Manage.c
@@ -871,4 +871,99 @@ int autodetect(void)
 	}
 	return rv;
 }
+
+/*
+ * It may contain no more than 16 characters (not counting the terminating null).
+ * It may  contain any ASCII character with  a value from 32  to 126 (inclusive),
+ * except  it shall not  contain the  backslash character  (ASCII code  92).  All
+ * other characters are invalid.
+ * Check for conformity with these rules is made in st->ss->rename_subarray().
+ */
+
+int Rename(mddev_dev_t devlist, int force, int quiet, struct mddev_ident_s *ident)
+{
+	char new_name[36] = "";
+	mddev_dev_t dv;
+	struct array_dev_list *dl;
+	int rv;
+	int i, found;
+	struct mdinfo info;
+
+	if (!devlist)
+		return 1;
+
+	/* get new name */
+	if (devlist->used == 1) {
+		strncpy(new_name, devlist->devname, 36);
+		devlist = devlist->next;
+	} else {
+		for (dv = devlist; dv;)
+		{
+			if (dv->used == 1) {
+				mddev_dev_t t;
+				t = dv;
+				strncpy(new_name, dv->devname, 36);
+				dv = dv->next;
+				free(t);
+				continue;
+			}
+			dv = dv->next;
+		}
+	}
+
+	if ((dl = check_devices(devlist, force, quiet, "imsm")) == NULL) {
+		return 1;
+	}
+
+	if (new_name[0] == '\0') {
+		if (!quiet)
+			fprintf(stderr, Name ": New name is not provided. Provide new name right after --update=name switch\n");
+		return 1;
+	}
+
+	while(dl) {
+		for (i = 0, found = 0, rv = 0; rv == 0; i++) {
+			snprintf(dl->st->subarray, sizeof(dl->st->subarray) - 1, "%d", i);
+			rv = dl->st->ss->load_super(dl->st, dl->fd, NULL);
+			if (rv)
+				break;
+
+			dl->st->ss->getinfo_super(dl->st, &info);
+			/* match based on subarray number, name or uuid */
+			if ((ident->member_index != -1 && i == ident->member_index) ||
+			    (ident->name[0] && !strncmp(info.name, ident->name, sizeof(info.name))) ||
+			    (ident->uuid_set && same_uuid(info.uuid, ident->uuid, dl->st->ss->swapuuid))) {
+				if (dl->st->loaded_container) {
+					struct map_ent *map;
+					int devname;
+					map_read(&map);
+					if (!find_array_minor(info.text_version, map, &devname)) {
+						fprintf(stderr, Name ": Attempting to modify properties of array, which is active.\n    Stop array and try again\n");
+						map_free(map);
+						return -1;
+					}
+					map_free(map);
+				}
+				rv = dl->st->ss->rename_subarray(dl->st, new_name, dl->fd);
+				found = 1;
+				break;
+			}
+		}
+
+		if (!found) {
+			if (!quiet)
+				fprintf(stderr, Name ": Could not find array with given identifier\n");
+			rv = 1;
+		}
+
+		if (!quiet && rv && found)
+			fprintf(stderr, Name ": Failed to rename\n");
+
+		dl = dl->next;
+	}
+
+	free_array_dev_list(dl);
+
+	return rv;
+}
 #endif
diff --git a/mdadm.c b/mdadm.c
index 65cc4b5..343652d 100644
--- a/mdadm.c
+++ b/mdadm.c
@@ -103,6 +103,7 @@ int main(int argc, char *argv[])
 	int dosyslog = 0;
 	int rebuild_map = 0;
 	int auto_update_home = 0;
+	int new_name = 0;

 	int print_help = 0;
 	FILE *outf;
@@ -293,7 +294,8 @@ int main(int argc, char *argv[])
 			continue;
 		}
 		if (opt == 1) {
-		        /* an undecorated option - must be a device name.
+		        /* an undecorated option - must be a device name, except MISC-rename
+			 * New name is provided this way
 			 */
 			if (devs_found > 0 && mode == '@' && !devmode) {
 				fprintf(stderr, Name ": Must give one of -a/-r/-f for subsequent devices at %s\n", optarg);
@@ -312,12 +314,13 @@ int main(int argc, char *argv[])
 			dv->disposition = devmode;
 			dv->writemostly = writemostly;
 			dv->re_add = re_add;
-			dv->used = 0;
+			dv->used = new_name;
 			dv->content = NULL;
 			dv->next = NULL;
 			*devlistend = dv;
 			devlistend = &dv->next;

+			new_name = 0;
 			devs_found++;
 			continue;
 		}
@@ -642,8 +645,11 @@ int main(int argc, char *argv[])
 				continue;
 			if (strcmp(update, "uuid")==0)
 				continue;
-			if (strcmp(update, "name")==0)
+			if (strcmp(update, "name")==0) {
+				if (mode == MISC)
+					new_name = 1;
 				continue;
+			}
 			if (strcmp(update, "homehost")==0)
 				continue;
 			if (strcmp(update, "devicesize")==0)
@@ -1307,6 +1313,12 @@ int main(int argc, char *argv[])
 				exit(2);
 			}
 			rv = Kill_Subarray(devlist, force, quiet, &ident);
+		} else if (update && !strcmp(update, "name")) {
+			if (!ident.uuid_set && !ident.name[0] && ident.member_index == -1) {
+				fprintf(stderr, Name ": Name, Uuid or Member Index must be set for --zero-subarray.\n");
+				exit(2);
+			}
+			rv = Rename(devlist, force, quiet, &ident);
 		} else {
 			if (devlist == NULL) {
 				if ((devmode=='D' || devmode == Waitclean) && scan) {
diff --git a/mdadm.h b/mdadm.h
index f5e239c..4905566 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -596,6 +596,7 @@ extern struct superswitch {
 	int (*write_bitmap)(struct supertype *st, int fd);
 	void (*free_super)(struct supertype *st);
 	int (*delete_subarray)(struct supertype *st, int fd);
+	int (*rename_subarray)(struct supertype *st, char *new_name, int fd);

 	/* validate_geometry is called with an st returned by
 	 * match_metadata_desc.
@@ -826,6 +827,7 @@ extern int Monitor(mddev_dev_t devlist,

 extern int Kill(char *dev, struct supertype *st, int force, int quiet, int noexcl);
 extern int Kill_Subarray(mddev_dev_t devlist, int force, int quiet, struct mddev_ident_s *ident);
+extern int Rename(mddev_dev_t devlist, int force, int quiet, struct mddev_ident_s *ident);
 extern int Wait(char *dev);
 extern int WaitClean(char *dev, int sock, int verbose);

diff --git a/super-intel.c b/super-intel.c
index 1b54df8..6348e48 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -284,6 +284,7 @@ enum imsm_update_type {
 	update_create_array,
 	update_add_disk,
 	update_kill_subarray,
+	update_rename_subarray,
 };

 struct imsm_update_activate_spare {
@@ -3458,6 +3459,7 @@ static int write_init_super_imsm(struct supertype *st)
 struct imsm_vol_modify_data
 {
 	enum imsm_update_type type;
+	char name[36];
 	int index;
 };

@@ -3592,6 +3594,89 @@ int delete_subarray_imsm(struct supertype *st, int fd)
 	return rv;
 }

+#define IMSM_SERIAL_MAX_LEN 16
+
+static int _validate_name(char *name)
+{
+	int i, len;
+
+	if (!name)
+		return 1;
+
+	if ((len = strlen(name)) > IMSM_SERIAL_MAX_LEN)
+		return 1;
+
+	for (i = 0; name[i] && i < len; i++) {
+		if (name[i] < 32 || name[i] > 126 || name[i] == 92)
+			break;
+	}
+
+	if (i < len)
+		return 1;
+	return 0;
+}
+
+static int rename_subarray_imsm(struct supertype *st, char *new_name, int fd)
+{
+	struct intel_super *super;
+	struct imsm_super *mpb;
+	struct imsm_dev *dev;
+	int container_index;
+	int rv = 0;
+
+	if (!st)
+		return 1;
+
+	super = st->sb;
+	mpb = super ? super->anchor : NULL;
+
+	if (!mpb)
+		return 1;
+
+	container_index = super->current_vol;
+
+	if (_validate_name(new_name)) {
+		fprintf(stderr, Name ": New array name contains illegal characters or is too long.\n");
+		return 1;
+	}
+
+	/* delegate mdmon to do this job */
+	if (!st->arrays && mdmon_running(st->container_dev)) {
+		struct imsm_vol_modify_data *u;
+
+		u = malloc(sizeof(*u));
+		if (!u)
+			return 3;
+
+		u->type = update_rename_subarray;
+		u->index = container_index;
+		strcpy(u->name, new_name);
+
+		st->update_tail = &st->updates;
+		append_metadata_update(st, u, sizeof(*u));
+
+		flush_metadata_updates(st);
+
+		return 0;
+	}
+
+	dev = get_imsm_dev(super, container_index);
+	strncpy((char *) dev->volume, new_name, MAX_RAID_SERIAL_LEN);
+
+	if (st->arrays) /* mdmon context */
+		super->updates_pending++;
+	else {
+		/* use passed fd if container is not loaded and handle in
+		 * intel_super is not available
+		 */
+		if (!st->loaded_container)
+			super->disks->fd = fd;
+
+		rv = write_super_imsm(super, 0);
+	}
+
+	return rv;
+}
 static int store_super_imsm(struct supertype *st, int fd)
 {
 	struct intel_super *super = st->sb;
@@ -5227,6 +5312,13 @@ static void imsm_process_update(struct supertype *st,
 		st->ss->delete_subarray(st, -1);
 		break;
 	}
+	case update_rename_subarray: {
+		struct imsm_vol_modify_data *u = (void *)update->buf;
+
+		super->current_vol = u->index;
+		st->ss->rename_subarray(st, u->name, -1);
+		break;
+	}
 	}
 }

@@ -5376,6 +5468,7 @@ struct superswitch super_imsm = {
 	.brief_detail_super = brief_detail_super_imsm,
 	.write_init_super = write_init_super_imsm,
 	.delete_subarray = delete_subarray_imsm,
+	.rename_subarray = rename_subarray_imsm,
 	.validate_geometry = validate_geometry_imsm,
 	.add_to_super	= add_to_super_imsm,
 	.detail_platform = detail_platform_imsm,
--
1.6.4.2

--
To unsubscribe from this list: send the line "unsubscribe linux-raid" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux RAID Wiki]     [ATA RAID]     [Linux SCSI Target Infrastructure]     [Linux Block]     [Linux IDE]     [Linux SCSI]     [Linux Hams]     [Device Mapper]     [Device Mapper Cryptographics]     [Kernel]     [Linux Admin]     [Linux Net]     [GFS]     [RPM]     [git]     [Yosemite Forum]


  Powered by Linux