Allow metadata handlers to free their own superblock.
authorNeil Brown <neilb@suse.de>
Fri, 14 Dec 2007 09:14:00 +0000 (20:14 +1100)
committerNeil Brown <neilb@suse.de>
Fri, 14 Dec 2007 09:14:00 +0000 (20:14 +1100)
As the metadata handler allocates the superblock, it should free it
too.  DDF will have a more complex 'superblock' which needs more complex
freeing.

Assemble.c
Create.c
Detail.c
Examine.c
Grow.c
Incremental.c
Kill.c
mdadm.h
super0.c
super1.c
util.c

index 7f673e0..c30dfe9 100644 (file)
@@ -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
index fec7567..8f554fa 100644 (file)
--- 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) {
index 22f0e5c..a579603 100644 (file)
--- 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");
index ba00270..b4dc963 100644 (file)
--- 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 82533de..793e551 100644 (file)
--- 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! */
index 705c402..94ef47d 100644 (file)
@@ -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 ce692ce..c13dba7 100644 (file)
--- 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 5e9eeee..de71b55 100644 (file)
--- 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[];
index 2a2938d..9a7eb15 100644 (file)
--- 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,
 };
index 2b096d3..804a07e 100644 (file)
--- 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 4a751aa..b6681f5 100644 (file)
--- 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-";