X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=Grow.c;h=9e8e217293f09b41b04259b5190b4edb2dd7a6c3;hb=8a4440794afbebe6bdc710eefd21c221c9046644;hp=33e50c35567f937a7943872d2e06c770fd6b3fe6;hpb=ea32955930cc63d2fa445ff00437f5f767f7a4af;p=thirdparty%2Fmdadm.git diff --git a/Grow.c b/Grow.c index 33e50c35..9e8e2172 100644 --- a/Grow.c +++ b/Grow.c @@ -123,7 +123,7 @@ int Grow_Add_device(char *devname, int fd, char *newdev) info.disk.state = (1 << MD_DISK_SYNC) | (1 << MD_DISK_ACTIVE); st->ss->update_super(&info, super, "grow", newdev, 0); - if (st->ss->store_super(nfd, super)) { + if (st->ss->store_super(st, nfd, super)) { fprintf(stderr, Name ": Cannot store new superblock on %s\n", newdev); close(nfd); return 1; @@ -181,7 +181,7 @@ int Grow_Add_device(char *devname, int fd, char *newdev) info.disk.state = (1 << MD_DISK_SYNC) | (1 << MD_DISK_ACTIVE); st->ss->update_super(&info, super, "grow", dv, 0); - if (st->ss->store_super(fd2, super)) { + if (st->ss->store_super(st, fd2, super)) { fprintf(stderr, Name ": Cannot store new superblock on %s\n", dv); close(fd2); return 1; @@ -192,7 +192,7 @@ int Grow_Add_device(char *devname, int fd, char *newdev) return 0; } -int Grow_addbitmap(char *devname, int fd, char *file, int chunk, int delay) +int Grow_addbitmap(char *devname, int fd, char *file, int chunk, int delay, int write_behind, int force) { /* * First check that array doesn't have a bitmap @@ -206,6 +206,17 @@ int Grow_addbitmap(char *devname, int fd, char *file, int chunk, int delay) mdu_bitmap_file_t bmf; mdu_array_info_t array; struct supertype *st; + int major = BITMAP_MAJOR_HI; + int vers = md_get_version(fd); + unsigned long long bitmapsize, array_size; + + if (vers < 9003) { + major = BITMAP_MAJOR_HOSTENDIAN; +#ifdef __BIG_ENDIAN + fprintf(stderr, Name ": Warning - bitmaps created on this kernel are not portable\n" + " between different architectured. Consider upgrading the Linux kernel.\n"); +#endif + } if (ioctl(fd, GET_BITMAP_FILE, &bmf) != 0) { if (errno == ENOMEM) @@ -215,6 +226,14 @@ int Grow_addbitmap(char *devname, int fd, char *file, int chunk, int delay) return 1; } if (bmf.pathname[0]) { + if (strcmp(file,"none")==0) { + if (ioctl(fd, SET_BITMAP_FILE, -1)!= 0) { + fprintf(stderr, Name ": failed to remove bitmap %s\n", + bmf.pathname); + return 1; + } + return 0; + } fprintf(stderr, Name ": %s already has a bitmap (%s)\n", devname, bmf.pathname); return 1; @@ -224,17 +243,49 @@ int Grow_addbitmap(char *devname, int fd, char *file, int chunk, int delay) return 1; } if (array.state & (1< (0x7fffffffULL<<9)) { + /* Array is big enough that we cannot trust array.size + * try other approaches + */ + bitmapsize = get_component_size(fd); + } +#endif + if (bitmapsize == 0) { + fprintf(stderr, Name ": Cannot reliably determine size of array to create bitmap - sorry.\n"); + return 1; + } + + if (array.level == 10) { + int ncopies = (array.layout&255)*(array.layout>>8); + bitmapsize = bitmapsize * array.raid_disks / ncopies; + } + st = super_by_version(array.major_version, array.minor_version); if (!st) { fprintf(stderr, Name ": Cannot understand version %d.%d\n", array.major_version, array.minor_version); return 1; } - if (strcmp(file, "internal") == 0) { + if (strcmp(file, "none") == 0) { + fprintf(stderr, Name ": no bitmap found on %s\n", devname); + return 1; + } else if (strcmp(file, "internal") == 0) { int d; for (d=0; d< st->max_devs; d++) { mdu_disk_info_t disk; @@ -254,10 +305,15 @@ int Grow_addbitmap(char *devname, int fd, char *file, int chunk, int delay) if (fd2 < 0) continue; if (st->ss->load_super(st, fd2, &super, NULL)==0) { - st->ss->add_internal_bitmap(super, - chunk, delay, - array.size); - st->ss->write_bitmap(st, fd2, super); + if (st->ss->add_internal_bitmap(st, super, + chunk, delay, write_behind, + bitmapsize, 0, major)) + st->ss->write_bitmap(st, fd2, super); + else { + fprintf(stderr, Name ": failed to create internal bitmap - chunksize problem.\n"); + close(fd2); + return 1; + } } close(fd2); } @@ -267,8 +323,57 @@ int Grow_addbitmap(char *devname, int fd, char *file, int chunk, int delay) fprintf(stderr, Name ": failed to set internal bitmap.\n"); return 1; } - } else - abort(); /* FIXME */ + } else { + int uuid[4]; + int bitmap_fd; + int d; + int max_devs = st->max_devs; + void *super = NULL; + if (chunk == UnSet) + chunk = DEFAULT_BITMAP_CHUNK; + + /* try to load a superblock */ + for (d=0; d= 0 && + st->ss->load_super(st, fd2, &super, NULL) == 0) { + close(fd2); + st->ss->uuid_from_super(uuid, super); + break; + } + close(fd2); + } + if (d == max_devs) { + fprintf(stderr, Name ": cannot find UUID for array!\n"); + return 1; + } + if (CreateBitmap(file, force, (char*)uuid, chunk, + delay, write_behind, bitmapsize, major)) { + return 1; + } + bitmap_fd = open(file, O_RDWR); + if (bitmap_fd < 0) { + fprintf(stderr, Name ": weird: %s cannot be opened\n", + file); + return 1; + } + if (ioctl(fd, SET_BITMAP_FILE, bitmap_fd) < 0) { + fprintf(stderr, Name ": Cannot set bitmap file for %s: %s\n", + devname, strerror(errno)); + return 1; + } + } return 0; }