From 1cc7f4feb9a979fdf7ac4bb06e5632b065d4f4d9 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 25 Jan 2011 07:56:53 +1100 Subject: [PATCH] Don't close fds in write_init_super We previously closed all 'fds' associated with an array in write_init_super .. sometimes, and sometimes at bad times. This isn't neat and free_super is a better place to close them. So make sure free_super always closes the fds that the metadata manager kept hold of, and stop closing them in write_init_super. Also add a few more calls to free_super to make sure they really do get closed. Reported-by: Adam Kwolek Signed-off-by: NeilBrown --- Examine.c | 1 + Manage.c | 10 ++++++++-- super-ddf.c | 12 +++--------- super-intel.c | 6 ------ super0.c | 9 +++++++-- super1.c | 7 +++++++ 6 files changed, 26 insertions(+), 19 deletions(-) diff --git a/Examine.c b/Examine.c index ffca9ca5..f949646f 100644 --- a/Examine.c +++ b/Examine.c @@ -145,6 +145,7 @@ int Examine(struct mddev_dev *devlist, int brief, int export, int scan, } else if (export) { if (st->ss->export_examine_super) st->ss->export_examine_super(st); + st->ss->free_super(st); } else { printf("%s:\n",devlist->devname); st->ss->examine_super(st, homehost); diff --git a/Manage.c b/Manage.c index 4e6afb50..824caa98 100644 --- a/Manage.c +++ b/Manage.c @@ -728,6 +728,7 @@ int Manage_subdevs(char *devname, int fd, skip_re_add: re_add_failed = 1; } + st->ss->free_super(st); } if (add_dev != dv->devname) { if (verbose > 0) @@ -808,9 +809,10 @@ int Manage_subdevs(char *devname, int fd, close(dfd); return 1; } - /* write_init_super will close 'dfd' */ - if (tst->ss->write_init_super(tst)) + if (tst->ss->write_init_super(tst)) { + close(dfd); return 1; + } } else if (dv->re_add) { /* this had better be raid1. * As we are "--re-add"ing we must find a spare slot @@ -872,6 +874,9 @@ int Manage_subdevs(char *devname, int fd, new_mdi.disk.major = disc.major; new_mdi.disk.minor = disc.minor; new_mdi.recovery_start = 0; + /* Make sure fds are closed as they are O_EXCL which + * would block add_disk */ + tst->ss->free_super(tst); if (sysfs_add_disk(sra, &new_mdi, 0) != 0) { fprintf(stderr, Name ": add new device to external metadata" " failed for %s\n", dv->devname); @@ -889,6 +894,7 @@ int Manage_subdevs(char *devname, int fd, } if (verbose >= 0) fprintf(stderr, Name ": added %s\n", dv->devname); + tst->ss->free_super(tst); break; case 'r': diff --git a/super-ddf.c b/super-ddf.c index bd3e8840..287fa7f8 100644 --- a/super-ddf.c +++ b/super-ddf.c @@ -2272,7 +2272,7 @@ static int add_to_super_ddf(struct supertype *st, static unsigned char null_conf[4096+512]; -static int __write_init_super_ddf(struct supertype *st, int do_close) +static int __write_init_super_ddf(struct supertype *st) { struct ddf_super *ddf = st->sb; @@ -2379,12 +2379,6 @@ static int __write_init_super_ddf(struct supertype *st, int do_close) successes++; } - if (do_close) - for (d = ddf->dlist; d; d=d->next) { - close(d->fd); - d->fd = -1; - } - return attempts != successes; } @@ -2437,7 +2431,7 @@ static int write_init_super_ddf(struct supertype *st) struct dl *d; for (d = ddf->dlist; d; d=d->next) while (Kill(d->devname, NULL, 0, 1, 1) == 0); - return __write_init_super_ddf(st, 1); + return __write_init_super_ddf(st); } } @@ -3239,7 +3233,7 @@ static void ddf_sync_metadata(struct supertype *st) if (!ddf->updates_pending) return; ddf->updates_pending = 0; - __write_init_super_ddf(st, 0); + __write_init_super_ddf(st); dprintf("ddf: sync_metadata\n"); } diff --git a/super-intel.c b/super-intel.c index d86e8d81..83fcb064 100644 --- a/super-intel.c +++ b/super-intel.c @@ -3743,7 +3743,6 @@ static int write_init_super_imsm(struct supertype *st) if (st->update_tail) { /* queue the recently created array / added disk * as a metadata update */ - struct dl *d; int rv; /* determine if we are creating a volume or adding a disk */ @@ -3755,11 +3754,6 @@ static int write_init_super_imsm(struct supertype *st) } else rv = create_array(st, current_vol); - for (d = super->disks; d ; d = d->next) { - close(d->fd); - d->fd = -1; - } - return rv; } else { struct dl *d; diff --git a/super0.c b/super0.c index d69d0c04..0b95dac2 100644 --- a/super0.c +++ b/super0.c @@ -752,8 +752,6 @@ static int write_init_super0(struct supertype *st) fprintf(stderr, Name ": failed to write superblock to %s\n", di->devname); - close(di->fd); - di->fd = -1; } return rv; } @@ -1079,6 +1077,13 @@ static void free_super0(struct supertype *st) { if (st->sb) free(st->sb); + while (st->info) { + struct devinfo *di = st->info; + st->info = di->next; + if (di->fd >= 0) + close(di->fd); + free(di); + } st->sb = NULL; } diff --git a/super1.c b/super1.c index f879e669..8a89d3b1 100644 --- a/super1.c +++ b/super1.c @@ -1641,6 +1641,13 @@ static void free_super1(struct supertype *st) { if (st->sb) free(st->sb); + while (st->info) { + struct devinfo *di = st->info; + st->info = di->next; + if (di->fd >= 0) + close(di->fd); + free(di); + } st->sb = NULL; } -- 2.39.2