]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Increase raid456 stripe cache size if needed to --grow the array.
authorNeil Brown <neilb@suse.de>
Thu, 14 Dec 2006 06:31:16 +0000 (17:31 +1100)
committerNeil Brown <neilb@suse.de>
Thu, 14 Dec 2006 06:31:16 +0000 (17:31 +1100)
The setting used unfortunately requires intimate knowledge of the
kernel, and it not reset when the reshape finishes.

ChangeLog
Grow.c
mdadm.h
sysfs.c

index 756ed92fd4f19035fef366f93266173d110d34c0..c584ba19b5ce62f6d80ff984300daa1e98e771e6 100644 (file)
--- 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 2a13a710b9775027f3da89f26c62fd1d065bd55e..fec0d3279300cbf97b8a05788d4967e3b74f6d5c 100644 (file)
--- 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 1976dd10cd0ae538b01f7f7a7054db97f65cede3..bfc2138884d2bca6b467a391de32b65ea40f69be 100644 (file)
--- 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 35b8883614e2e7797f622aec07264588a6609b48..166481f1a54580f652d191a932251dfbfa4190bd 100644 (file)
--- 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;