[PATCH 05/23] imsm: Reconfigure mdmon, grow_array() implementation

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

 



(Online Capacity Expansion for IMSM)
When mdmon calls grow_array() on disks increase detection,
grow_array() has to add new disks to active_array structure.
According to this memory for internal imsm data has to be reallocated
reallocate_imsm_dev() takes current memory contents of internal imsm data and copies it to new (larger) memory location. Manages memory relink then.

Signed-off-by: Adam Kwolek <adam.kwolek@xxxxxxxxx>
---

 mdadm.h       |    2 +
 monitor.c     |   50 -----------------------
 super-intel.c |  126 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 util.c        |   51 +++++++++++++++++++++++
 4 files changed, 179 insertions(+), 50 deletions(-)

diff --git a/mdadm.h b/mdadm.h
index a846098..ecef25c 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -861,6 +861,8 @@ extern int conf_name_is_free(char *name);  extern int devname_matches(char *name, char *match);  extern struct mddev_ident_s *conf_match(struct mdinfo *info, struct supertype *st);  extern void sleep2(unsigned int sec, unsigned int usec);
+extern int read_attr(char *buf, int len, int fd); extern int 
+read_dev_state(int fd);
 
 extern void free_line(char *line);
 extern int match_oneof(char *devices, char *devname); diff --git a/monitor.c b/monitor.c index 4578718..3c99dff 100644
--- a/monitor.c
+++ b/monitor.c
@@ -45,27 +45,6 @@ static void add_fd(fd_set *fds, int *maxfd, int fd)
 	FD_SET(fd, fds);
 }
 
-static int read_attr(char *buf, int len, int fd) -{
-	int n;
-
-	if (fd < 0) {
-		buf[0] = 0;
-		return 0;
-	}
-	lseek(fd, 0, 0);
-	n = read(fd, buf, len - 1);
-
-	if (n <= 0) {
-		buf[0] = 0;
-		return 0;
-	}
-	buf[n] = 0;
-	if (buf[n-1] == '\n')
-		buf[n-1] = 0;
-	return n;
-}
-
 static unsigned long long read_resync_start(int fd)  {
 	char buf[30];
@@ -100,35 +79,6 @@ static enum sync_action read_action( int fd)
 	return (enum sync_action) sysfs_match_word(buf, sync_actions);  }
 
-int read_dev_state(int fd)
-{
-	char buf[60];
-	int n = read_attr(buf, 60, fd);
-	char *cp;
-	int rv = 0;
-
-	if (n <= 0)
-		return 0;
-
-	cp = buf;
-	while (cp) {
-		if (sysfs_attr_match(cp, "faulty"))
-			rv |= DS_FAULTY;
-		if (sysfs_attr_match(cp, "in_sync"))
-			rv |= DS_INSYNC;
-		if (sysfs_attr_match(cp, "write_mostly"))
-			rv |= DS_WRITE_MOSTLY;
-		if (sysfs_attr_match(cp, "spare"))
-			rv |= DS_SPARE;
-		if (sysfs_attr_match(cp, "blocked"))
-			rv |= DS_BLOCKED;
-		cp = strchr(cp, ',');
-		if (cp)
-			cp++;
-	}
-	return rv;
-}
-
 static void signal_manager(void)
 {
 	/* tgkill(getpid(), mon_tid, SIGUSR1); */ diff --git a/super-intel.c b/super-intel.c index a4ffb3f..115a5f0 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -5098,6 +5098,131 @@ static struct mdinfo *imsm_activate_spare(struct active_array *a,
 	return rv;
 }
 
+int imsm_grow_array(struct active_array *a,  int new_raid_disks) {
+	int ret_val = 0;
+	struct intel_super *super = a->container->sb;
+	int inst = a->info.container_member;
+	struct imsm_dev *dev = get_imsm_dev(super, inst);
+	struct imsm_map *map = get_imsm_map(dev, 0);
+	struct mdinfo *d;
+	struct mdinfo *di;
+	struct dl *dl;
+	int i;
+	int rv;
+	char dv[1024];
+	char nm[1024];
+	char *dname;
+
+	dprintf("imsm: grow array: inst=%d raid disks=%d level=%d\n",
+		inst, a->info.array.raid_disks, a->info.array.level);
+
+	/* grow support only */
+	if ((a->info.array.raid_disks >= new_raid_disks) &&
+	    (new_raid_disks > 0))
+		return ret_val;
+
+	/* Look for all disks beyond current configuration
+	 * To handle degradation after takeover
+	 * look also on last disk in configuration.
+	 */
+	for (i = a->info.array.raid_disks-1; i < new_raid_disks; i++) {
+		for (d = a->info.devs ; d ; d = d->next)
+			if (d->disk.raid_disk == i)
+				break;
+		dprintf("found %d: %p %x\n", i, d, d ? d->curr_state : 0);
+		if (d && (d->state_fd >= 0))
+			continue;
+
+		/* OK, this device can be added.  Try to add.
+		 */
+		dl = imsm_add_spare(super, i, a, 0);
+		if (!dl)
+			dl = imsm_add_spare(super, i, a, 1);
+		if (!dl)
+			continue;
+
+		if (dl->index < 0)
+			dl->index = i;
+		/* found a usable disk with enough space */
+		di = malloc(sizeof(*di));
+		if (!di)
+			continue;
+		memset(di, 0, sizeof(*di));
+
+		/* dl->index will be -1 in the case we are activating a
+		 * pristine spare.  imsm_process_update() will create a
+		 * new index in this case.  Once a disk is found to be
+		 * failed in all member arrays it is kicked from the
+		 * metadata
+		 */
+		di->disk.number = dl->index;
+
+		dl->disk.status |= CONFIGURED_DISK;
+		dl->disk.status &= ~SPARE_DISK;
+
+		/* (ab)use di->devs to store a pointer to the device
+		 * we chose
+		 */
+		di->devs = (struct mdinfo *) dl;
+
+		di->disk.raid_disk = i;
+		di->disk.major = dl->major;
+		di->disk.minor = dl->minor;
+		di->disk.state = (1<<MD_DISK_SYNC) |
+				 (1<<MD_DISK_ACTIVE);
+
+		/* set handle to state in sysfs
+		 */
+		sprintf(dv, "/sys/dev/block/%d:%d", di->disk.major, di->disk.minor);
+		memset(nm, 0, sizeof(nm));
+		rv = readlink(dv, nm, sizeof(nm));
+		if (rv > 0) {
+			nm[rv] = '\0';
+			dname = strrchr(nm, '/');
+			if (dname) {
+				dname++;
+				sprintf(di->sys_name, "dev-%s", dname);
+			}
+		}
+
+		di->state_fd = sysfs_open(a->devnum,
+					  di->sys_name,
+					  "state");
+		di->recovery_fd = sysfs_open(a->devnum,
+					  di->sys_name,
+					  "recovery_start");
+
+		di->prev_state = read_dev_state(di->state_fd);
+		di->curr_state = di->prev_state;
+		di->next_state = 0;
+
+		di->recovery_start = 0;
+		di->data_offset = __le32_to_cpu(map->pba_of_lba0);
+		di->component_size = a->info.component_size;
+		di->container_member = inst;
+		super->random = random32();
+
+		di->next = a->info.devs;
+		a->info.devs = di;
+
+		ret_val++;
+		dprintf("%x:%x to be %d at %llu\n", dl->major, dl->minor,
+			i, di->data_offset);
+	}
+
+	if ((new_raid_disks - a->info.array.raid_disks) != ret_val) {
+		dprintf("imsm: ERROR: imsm_grow_array() configures %i raid disks\n",
+			ret_val);
+	}
+
+	/* prepare device to receive new disk(s)
+	 */
+	reallocate_imsm_dev(super, inst, new_raid_disks);
+
+	return ret_val;
+}
+
 static int disks_overlap(struct intel_super *super, int idx, struct imsm_update_create_array *u)  {
 	struct imsm_dev *dev = get_imsm_dev(super, idx); @@ -5697,6 +5822,7 @@ struct superswitch super_imsm = {
 	.match_metadata_desc = match_metadata_desc_imsm,
 	.container_content = container_content_imsm,
 	.default_layout = imsm_level_to_layout,
+	.grow_array	= imsm_grow_array,
 	.external	= 1,
 	.name = "imsm",
 
diff --git a/util.c b/util.c
index 5779d52..7f5e20a 100644
--- a/util.c
+++ b/util.c
@@ -1656,3 +1656,54 @@ void sleep2(unsigned int sec, unsigned int usec)
 	tv.tv_usec = usec;
 	select(0, NULL, NULL, NULL, &tv);
 }
+
+int read_attr(char *buf, int len, int fd) {
+	int n;
+
+	if (fd < 0) {
+		buf[0] = 0;
+		return 0;
+	}
+	lseek(fd, 0, 0);
+	n = read(fd, buf, len - 1);
+
+	if (n <= 0) {
+		buf[0] = 0;
+		return 0;
+	}
+	buf[n] = 0;
+	if (buf[n-1] == '\n')
+		buf[n-1] = 0;
+
+	return n;
+}
+
+int read_dev_state(int fd)
+{
+	char buf[60];
+	int n = read_attr(buf, 60, fd);
+	char *cp;
+	int rv = 0;
+
+	if (n <= 0)
+		return 0;
+
+	cp = buf;
+	while (cp) {
+		if (sysfs_attr_match(cp, "faulty"))
+			rv |= DS_FAULTY;
+		if (sysfs_attr_match(cp, "in_sync"))
+			rv |= DS_INSYNC;
+		if (sysfs_attr_match(cp, "write_mostly"))
+			rv |= DS_WRITE_MOSTLY;
+		if (sysfs_attr_match(cp, "spare"))
+			rv |= DS_SPARE;
+		if (sysfs_attr_match(cp, "blocked"))
+			rv |= DS_BLOCKED;
+		cp = strchr(cp, ',');
+		if (cp)
+			cp++;
+	}
+	return rv;
+}

��.n��������+%������w��{.n�����{����w��ܨ}���Ơz�j:+v�����w����ޙ��&�)ߡ�a����z�ޗ���ݢj��w�f



[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