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 <adam.kwolek@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
This commit is contained in:
NeilBrown 2011-01-25 07:56:53 +11:00
parent 446d2a5ad4
commit 1cc7f4feb9
6 changed files with 26 additions and 19 deletions

View File

@ -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);

View File

@ -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':

View File

@ -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");
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}