summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog3
-rw-r--r--Grow.c20
-rw-r--r--mdadm.h2
-rw-r--r--sysfs.c6
4 files changed, 29 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index 756ed92..c584ba1 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 2a13a71..fec0d32 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 1976dd1..bfc2138 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 35b8883..166481f 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;