Rob Bray wrote: > I am trying to grow a raid5 volume in-place. I would like to expand the > partition boundaries, then grow raid5 into the newly-expanded partitions. > I was wondering if there is a way to move the superblock from the end of > the "old" partition to the end of the "new" partition. I've tried dd > if=/dev/sdX1 of=/dev/sdX1 bs=512 count=256 > skip=(sizeOfOldPartitionInBlocks - 256) seek=(sizeOfNewPartitionInBlocks - > 256) unsuccessfully. Also, copying the last 128KB (256 blocks) of the old > partition before the table modification to a file, and placing that data > at the tail of the new partition also yields no beans. I can drop one > drive at a time from the group, change the partition table, then hot-add > it, but a resync times 7 drives is a lot of juggling. Any ideas? The superblock location is somewhat tricky to calculate correctly. I've used a tiny program (attached) for exactly this purpose. /mjt
/* mdsuper: read or write a linux software raid superbloc (version 0.90) * from or to a given device. * * GPL. * Written by Michael Tokarev (mjt@xxxxxxxxxx) */ #define _GNU_SOURCE #include <sys/types.h> #include <stdio.h> #include <unistd.h> #include <errno.h> #include <stdlib.h> #include <fcntl.h> #include <string.h> #include <sys/ioctl.h> #include <linux/ioctl.h> #include <linux/types.h> #include <linux/raid/md_p.h> #include <linux/fs.h> int main(int argc, char **argv) { unsigned long long dsize; unsigned long long offset; int mdfd; int n; mdp_super_t super; const char *dev; if (argc != 3) { fprintf(stderr, "mdsuper: usage: mdsuper {read|write} mddev\n"); return 1; } if (strcmp(argv[1], "read") == 0) n = O_RDONLY; else if (strcmp(argv[1], "write") == 0) n = O_WRONLY; else { fprintf(stderr, "mdsuper: read or write arg required, not \"%s\"\n", argv[1]); return 1; } dev = argv[2]; mdfd = open(dev, n, 0); if (mdfd < 0) { perror(dev); return 1; } if (ioctl(mdfd, BLKGETSIZE64, &dsize) < 0) { perror(dev); return 1; } if (dsize < MD_RESERVED_SECTORS*2) { fprintf(stderr, "mdsuper: %s is too small\n", dev); return 1; } offset = MD_NEW_SIZE_SECTORS(dsize>>9); fprintf(stderr, "size=%Lu (%Lu sect), offset=%Lu (%Lu sect)\n", dsize, dsize>>9, offset * 512, offset); offset *= 512; if (n == O_RDONLY) { if (pread64(mdfd, &super, sizeof(super), offset) != sizeof(super)) { perror(dev); return 1; } if (super.md_magic != MD_SB_MAGIC) { fprintf(stderr, "%s: bad magic (0x%08x, should be 0x%08x)\n", dev, super.md_magic, MD_SB_MAGIC); return 1; } if (write(1, &super, sizeof(super)) != sizeof(super)) { perror("write"); return 1; } } else { if (read(0, &super, sizeof(super)) != sizeof(super)) { perror("read"); return 1; } if (pwrite64(mdfd, &super, sizeof(super), offset) != sizeof(super)) { perror(dev); return 1; } } return 0; }