From 758d3a8e7d3e0620d68d3b9e72ef0747319c6dac Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Thu, 14 Dec 2006 17:31:16 +1100 Subject: [PATCH] Increase raid456 stripe cache size if needed to --grow the array. The setting used unfortunately requires intimate knowledge of the kernel, and it not reset when the reshape finishes. --- ChangeLog | 3 +++ Grow.c | 20 ++++++++++++++++++-- mdadm.h | 2 ++ sysfs.c | 6 ++++++ 4 files changed, 29 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 756ed92f..c584ba19 100644 --- a/ChangeLog +++ b/ChangeLog @@ -12,6 +12,9 @@ Changes Prior to this release get created automatically, as this is almost always what is wanted. - Give useful message if raid4/5/6 cannot be started because it is not clean and is also degraded. + - Increase raid456 stripe cache size if needed to --grow the array. + The setting used unfortunately requires intimate knowledge of the + kernel, and it not reset when the reshape finishes. Changes Prior to 2.5.6 release - Fix bug which meant "bitmap=xxx" in mdadm.conf was not handled diff --git a/Grow.c b/Grow.c index 2a13a710..fec0d327 100644 --- a/Grow.c +++ b/Grow.c @@ -523,7 +523,7 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file, case 6: st = super_by_version(array.major_version, array.minor_version); - /* size can be changed independantly. + /* size can be changed independently. * layout/chunksize/raid_disks/level can be changed * though the kernel may not support it all. * If 'suspend_lo' is not present in devfs, then @@ -620,7 +620,8 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file, printf("mdadm: Need to backup %lluK of critical section..\n", last_block/2); sra = sysfs_read(fd, 0, - GET_COMPONENT|GET_DEVS|GET_OFFSET|GET_STATE); + GET_COMPONENT|GET_DEVS|GET_OFFSET|GET_STATE| + GET_CACHE); if (!sra) { fprintf(stderr, Name ": %s: Cannot get array details from sysfs\n", devname); @@ -742,10 +743,25 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file, array.chunk_size = nchunk; array.layout = nlayout; if (ioctl(fd, SET_ARRAY_INFO, &array) != 0) { + if (errno == ENOSPC) { + /* stripe cache is not big enough. + * It needs to be 4 times chunksize_size, + * and we assume pagesize is 4K + */ + if (sra->cache_size < 4 * (nchunk/4096)) { + sysfs_set_num(sra, NULL, + "stripe_cache_size", + 4 * (nchunk/4096) +1); + if (ioctl(fd, SET_ARRAY_INFO, + &array) == 0) + goto ok; + } + } fprintf(stderr, Name ": Cannot set device size/shape for %s: %s\n", devname, strerror(errno)); goto abort; } + ok: ; /* suspend the relevant region */ sysfs_set_num(sra, NULL, "suspend_hi", 0); /* just in case */ diff --git a/mdadm.h b/mdadm.h index 1976dd10..bfc21388 100644 --- a/mdadm.h +++ b/mdadm.h @@ -257,12 +257,14 @@ struct sysarray { int layout; int level; int spares; + int cache_size; }; /* various details can be requested */ #define GET_LEVEL 1 #define GET_LAYOUT 2 #define GET_COMPONENT 4 #define GET_CHUNK 8 +#define GET_CACHE 16 #define GET_DEVS 1024 /* gets role, major, minor */ #define GET_OFFSET 2048 diff --git a/sysfs.c b/sysfs.c index 35b88836..166481f1 100644 --- a/sysfs.c +++ b/sysfs.c @@ -107,6 +107,12 @@ struct sysarray *sysfs_read(int fd, int devnum, unsigned long options) goto abort; sra->chunk = strtoul(buf, NULL, 0); } + if (options & GET_CACHE) { + strcpy(base, "stripe_cache_size"); + if (load_sys(fname, buf)) + goto abort; + sra->cache_size = strtoul(buf, NULL, 0); + } if (! (options & GET_DEVS)) return sra; -- 2.39.2