From: Neil Brown Date: Fri, 14 Dec 2007 09:14:00 +0000 (+1100) Subject: Allow metadata handlers to free their own superblock. X-Git-Tag: mdadm-2.6.5~36 X-Git-Url: http://git.ipfire.org/?p=thirdparty%2Fmdadm.git;a=commitdiff_plain;h=df37ffc0393b919ba5607bb48b2eaf2f9a1832d7 Allow metadata handlers to free their own superblock. As the metadata handler allocates the superblock, it should free it too. DDF will have a more complex 'superblock' which needs more complex freeing. --- diff --git a/Assemble.c b/Assemble.c index 7f673e06..c30dfe99 100644 --- a/Assemble.c +++ b/Assemble.c @@ -226,11 +226,6 @@ int Assemble(struct supertype *st, char *mddev, int mdfd, continue; } - if (super) { - free(super); - super = NULL; - } - dfd = dev_open(devname, O_RDONLY|O_EXCL); if (dfd < 0) { if ((inargv && verbose >= 0) || verbose > 0) @@ -265,35 +260,35 @@ int Assemble(struct supertype *st, char *mddev, int mdfd, if ((inargv && verbose >= 0) || verbose > 0) fprintf(stderr, Name ": %s has wrong uuid.\n", devname); - continue; + goto loop; } if (ident->name[0] && (!update || strcmp(update, "name")!= 0) && (!super || name_matches(info.name, ident->name, homehost)==0)) { if ((inargv && verbose >= 0) || verbose > 0) fprintf(stderr, Name ": %s has wrong name.\n", devname); - continue; + goto loop; } if (ident->super_minor != UnSet && (!super || ident->super_minor != info.array.md_minor)) { if ((inargv && verbose >= 0) || verbose > 0) fprintf(stderr, Name ": %s has wrong super-minor.\n", devname); - continue; + goto loop; } if (ident->level != UnSet && (!super|| ident->level != info.array.level)) { if ((inargv && verbose >= 0) || verbose > 0) fprintf(stderr, Name ": %s has wrong raid level.\n", devname); - continue; + goto loop; } if (ident->raid_disks != UnSet && (!super || ident->raid_disks!= info.array.raid_disks)) { if ((inargv && verbose >= 0) || verbose > 0) fprintf(stderr, Name ": %s requires wrong number of drives.\n", devname); - continue; + goto loop; } if (mdfd < 0) { if (tst == NULL || super == NULL) @@ -306,7 +301,7 @@ int Assemble(struct supertype *st, char *mddev, int mdfd, /* Auto-assemble, and this is not a usable host */ /* if update != NULL, we are updating the host * name... */ - continue; + goto loop; } } /* If we are this far, then we are nearly commited to this device. @@ -319,7 +314,7 @@ int Assemble(struct supertype *st, char *mddev, int mdfd, if (!super) { fprintf(stderr, Name ": %s has no superblock - assembly aborted\n", devname); - free(first_super); + st->ss->free_super(first_super); return 1; } @@ -334,7 +329,7 @@ int Assemble(struct supertype *st, char *mddev, int mdfd, * for now. */ if (mdfd < 0) - continue; + goto loop; if (homehost) { int first = st->ss->match_home(first_super, homehost); int last = tst->ss->match_home(super, homehost); @@ -344,7 +339,7 @@ int Assemble(struct supertype *st, char *mddev, int mdfd, if ((inargv && verbose >= 0) || verbose > 0) fprintf(stderr, Name ": %s misses out due to wrong homehost\n", devname); - continue; + goto loop; } else { /* reject all those sofar */ mddev_dev_t td; if ((inargv && verbose >= 0) || verbose > 0) @@ -354,18 +349,23 @@ int Assemble(struct supertype *st, char *mddev, int mdfd, if (td->used == 1) td->used = 0; tmpdev->used = 1; - continue; + goto loop; } } } fprintf(stderr, Name ": superblock on %s doesn't match others - assembly aborted\n", devname); - free(super); - free(first_super); + tst->ss->free_super(super); + st->ss->free_super(first_super); return 1; } tmpdev->used = 1; + + loop: + if (super) + tst->ss->free_super(super); + super = NULL; } if (mdfd < 0) { @@ -388,7 +388,7 @@ int Assemble(struct supertype *st, char *mddev, int mdfd, asprintf(&mddev, "/dev/md/%s", c); mdfd = open_mddev(mddev, ident->autof); if (mdfd < 0) { - free(first_super); + st->ss->free_super(first_super); free(devices); first_super = NULL; goto try_again; @@ -405,7 +405,7 @@ int Assemble(struct supertype *st, char *mddev, int mdfd, mddev, tmpdev->devname); close(mdfd); mdfd = -1; - free(first_super); + st->ss->free_super(first_super); free(devices); first_super = NULL; goto try_again; @@ -442,11 +442,6 @@ int Assemble(struct supertype *st, char *mddev, int mdfd, remove_partitions(dfd); - if (super) { - free(super); - super = NULL; - } - st->ss->load_super(st, dfd, &super, NULL); st->ss->getinfo_super(&info, super); @@ -485,11 +480,6 @@ int Assemble(struct supertype *st, char *mddev, int mdfd, remove_partitions(dfd); - if (super) { - free(super); - super = NULL; - } - st->ss->load_super(st, dfd, &super, NULL); st->ss->getinfo_super(&info, super); close(dfd); @@ -570,11 +560,11 @@ int Assemble(struct supertype *st, char *mddev, int mdfd, best[i] = devcnt; } devcnt++; - } - if (super) - free(super); - super = NULL; + if (super) + st->ss->free_super(super); + super = NULL; + } if (update && strcmp(update, "byteorder")==0) st->minor_version = 90; @@ -582,7 +572,7 @@ int Assemble(struct supertype *st, char *mddev, int mdfd, if (devcnt == 0) { fprintf(stderr, Name ": no devices found for %s\n", mddev); - free(first_super); + st->ss->free_super(first_super); if (must_close) close(mdfd); return 1; } @@ -674,7 +664,7 @@ int Assemble(struct supertype *st, char *mddev, int mdfd, fprintf(stderr, Name ": Could not re-write superblock on %s\n", devices[chosen_drive].devname); devices[chosen_drive].events = 0; - free(super); + st->ss->free_super(super); continue; } close(fd); @@ -682,7 +672,7 @@ int Assemble(struct supertype *st, char *mddev, int mdfd, devices[chosen_drive].uptodate = 1; avail[chosen_drive] = 1; okcnt++; - free(super); + st->ss->free_super(super); /* If there are any other drives of the same vintage, * add them in as well. We can't lose and we might gain diff --git a/Create.c b/Create.c index fec7567f..8f554fad 100644 --- a/Create.c +++ b/Create.c @@ -553,7 +553,7 @@ int Create(struct supertype *st, char *mddev, int mdfd, if (ioctl(mdfd, ADD_NEW_DISK, &disk)) { fprintf(stderr, Name ": ADD_NEW_DISK for %s failed: %s\n", dv->devname, strerror(errno)); - free(super); + st->ss->free_super(super); return 1; } @@ -562,7 +562,7 @@ int Create(struct supertype *st, char *mddev, int mdfd, if (dv == moved_disk && dnum != insert_point) break; } } - free(super); + st->ss->free_super(super); /* param is not actually used */ if (runstop == 1 || subdevs >= raiddisks) { diff --git a/Detail.c b/Detail.c index 22f0e5c0..a5796038 100644 --- a/Detail.c +++ b/Detail.c @@ -119,7 +119,7 @@ int Detail(char *dev, int brief, int export, int test, char *homehost) st->ss->getinfo_super(&info, super); if (info.array.ctime != array.ctime || info.array.level != array.level) { - free(super); + st->ss->free_super(super); super = NULL; } } @@ -378,6 +378,8 @@ This is pretty boring if (spares && brief) printf(" spares=%d", spares); if (super && brief && st) st->ss->brief_detail_super(super); + if (super) + st->ss->free_super(super); if (brief > 1 && devices) printf("\n devices=%s", devices); if (brief) printf("\n"); diff --git a/Examine.c b/Examine.c index ba00270e..b4dc963a 100644 --- a/Examine.c +++ b/Examine.c @@ -119,7 +119,7 @@ int Examine(mddev_dev_t devlist, int brief, int scan, st->ss->getinfo_super(&ap->info, super); } else { st->ss->getinfo_super(&ap->info, super); - free(super); + st->ss->free_super(super); } if (!(ap->info.disk.state & MD_DISK_SYNC)) ap->spares++; @@ -128,7 +128,7 @@ int Examine(mddev_dev_t devlist, int brief, int scan, } else { printf("%s:\n",devlist->devname); st->ss->examine_super(super, homehost); - free(super); + st->ss->free_super(super); } } if (brief) { @@ -145,7 +145,7 @@ int Examine(mddev_dev_t devlist, int brief, int scan, sep=','; } } - free(ap->super); + ap->st->ss->free_super(ap->super); /* FIXME free ap */ if (ap->spares || brief > 1) printf("\n"); diff --git a/Grow.c b/Grow.c index 82533dee..793e5515 100644 --- a/Grow.c +++ b/Grow.c @@ -103,7 +103,8 @@ int Grow_Add_device(char *devname, int fd, char *newdev) fprintf(stderr, Name ": cannot open device file %s\n", dv); return 1; } - if (super) free(super); + if (super) + st->ss->free_super(super); super= NULL; if (st->ss->load_super(st, fd2, &super, NULL)) { fprintf(stderr, Name ": cannot find super block on %s\n", dv); @@ -906,7 +907,8 @@ int Grow_restart(struct supertype *st, struct mdinfo *info, int *fdlist, int cnt continue; st->ss->getinfo_super(&dinfo, super); - free(super); super = NULL; + st->ss->free_super(super); + super = NULL; if (lseek64(fd, (dinfo.data_offset + dinfo.component_size - 8) <<9, 0) < 0) @@ -948,7 +950,8 @@ int Grow_restart(struct supertype *st, struct mdinfo *info, int *fdlist, int cnt /* FIXME should be this be an error */ continue; st->ss->getinfo_super(&dinfo, super); - free(super); super = NULL; + st->ss->free_super(super); + super = NULL; offsets[j] = dinfo.data_offset; } printf(Name ": restoring critical section\n"); @@ -974,7 +977,7 @@ int Grow_restart(struct supertype *st, struct mdinfo *info, int *fdlist, int cnt dinfo.reshape_progress = __le64_to_cpu(bsb.length); st->ss->update_super(&dinfo, super, "_reshape_progress",NULL,0, 0, NULL); st->ss->store_super(st, fdlist[j], super); - free(super); + st->ss->free_super(super); } /* And we are done! */ diff --git a/Incremental.c b/Incremental.c index 705c402c..94ef47d5 100644 --- a/Incremental.c +++ b/Incremental.c @@ -502,7 +502,7 @@ static void find_reject(int mdfd, struct supertype *st, struct sysarray *sra, continue; } st->ss->getinfo_super(&info, super); - free(super); + st->ss->free_super(super); close(dfd); if (info.disk.number != number || @@ -574,24 +574,24 @@ static int count_active(struct supertype *st, int mdfd, char **availp, if (avail[i]) avail[i]--; avail[info.disk.raid_disk] = 2; - free(best_super); + st->ss->free_super(best_super); best_super = super; super = NULL; } else { /* info.events much bigger */ cnt = 1; cnt1 = 0; memset(avail, 0, info.disk.raid_disk); max_events = info.events; - free(best_super); + st->ss->free_super(best_super); best_super = super; super = NULL; } } if (super) - free(super); + st->ss->free_super(super); } if (best_super) { st->ss->getinfo_super(bestinfo,best_super); - free(best_super); + st->ss->free_super(best_super); } return cnt + cnt1; } @@ -636,7 +636,7 @@ void RebuildMap(void) map_add(&map, md->devnum, st->ss->major, st->minor_version, info.uuid, path ? : "/unknown"); - free(super); + st->ss->free_super(super); break; } } diff --git a/Kill.c b/Kill.c index ce692cea..c13dba7e 100644 --- a/Kill.c +++ b/Kill.c @@ -66,7 +66,7 @@ int Kill(char *dev, int force, int quiet) if (rv== 0 || (force && rv >= 2)) { mdu_array_info_t info; info.major_version = -1; /* zero superblock */ - free(super); + st->ss->free_super(super); st->ss->init_super(st, &super, &info, 0, "", NULL, NULL); if (st->ss->store_super(st, fd, super)) { if (!quiet) diff --git a/mdadm.h b/mdadm.h index 5e9eeee7..de71b55a 100644 --- a/mdadm.h +++ b/mdadm.h @@ -365,6 +365,7 @@ extern struct superswitch { unsigned long long size, int may_change, int major); void (*locate_bitmap)(struct supertype *st, int fd, void *sbv); int (*write_bitmap)(struct supertype *st, int fd, void *sbv); + void (*free_super)(void *super); int major; int swapuuid; /* true if uuid is bigending rather than hostendian */ } super0, super1, *superlist[]; diff --git a/super0.c b/super0.c index 2a2938df..9a7eb15e 100644 --- a/super0.c +++ b/super0.c @@ -953,6 +953,12 @@ int write_bitmap0(struct supertype *st, int fd, void *sbv) return rv; } +static void free_super0(void *super) +{ + if (super) + free(super); +} + struct superswitch super0 = { #ifndef MDASSEMBLE .examine_super = examine_super0, @@ -976,6 +982,7 @@ struct superswitch super0 = { .add_internal_bitmap = add_internal_bitmap0, .locate_bitmap = locate_bitmap0, .write_bitmap = write_bitmap0, + .free_super = free_super0, .major = 0, .swapuuid = 0, }; diff --git a/super1.c b/super1.c index 2b096d32..804a07e1 100644 --- a/super1.c +++ b/super1.c @@ -1366,6 +1366,12 @@ static int write_bitmap1(struct supertype *st, int fd, void *sbv) return rv; } +static void free_super1(void *super) +{ + if (super) + free(super); +} + struct superswitch super1 = { #ifndef MDASSEMBLE .examine_super = examine_super1, @@ -1389,6 +1395,7 @@ struct superswitch super1 = { .add_internal_bitmap = add_internal_bitmap1, .locate_bitmap = locate_bitmap1, .write_bitmap = write_bitmap1, + .free_super = free_super1, .major = 1, #if __BYTE_ORDER == BIG_ENDIAN .swapuuid = 0, diff --git a/util.c b/util.c index 4a751aaf..b6681f55 100644 --- a/util.c +++ b/util.c @@ -334,7 +334,7 @@ int check_raid(int fd, char *name) fprintf(stderr, Name ": %s appears to be part of a raid array:\n", name); st->ss->getinfo_super(&info, super); - free(super); + st->ss->free_super(super); crtime = info.array.ctime; level = map_num(pers, info.array.level); if (!level) level = "-unknown-";