DF-4758 / fix.diff
--- a/sys/dev/raid/vinum/vinum.c +++ b/sys/dev/raid/vinum/vinum.c @@ -201,6 +201,7 @@ union daemoninfo di = { .nothing = 0 }; int i; int drives_allocated = vinum_conf.drives_allocated; + int daemon_wait = 5 * hz; /* DF-4760: bound the daemon wait */ if (DRIVE != NULL) { if (cleardrive) { /* remove the vinum config */ @@ -212,10 +213,12 @@ } Free(DRIVE); } - while ((vinum_conf.flags & (VF_STOPPING | VF_DAEMONOPEN)) + if ((vinum_conf.flags & (VF_STOPPING | VF_DAEMONOPEN)) == (VF_STOPPING | VF_DAEMONOPEN)) { /* at least one daemon open, we're stopping */ - queue_daemon_request(daemonrq_return, di); /* stop the daemon */ - tsleep(&vinumclose, 0, "vstop", 1); /* and wait for it */ + queue_daemon_request(daemonrq_return, di); /* stop the daemon (queue ONCE: DF-4760) */ + while ((vinum_conf.flags & VF_DAEMONOPEN) != 0 + && daemon_wait-- > 0) /* bounded wait: DF-4760 */ + tsleep(&vinumclose, 0, "vstop", 1); /* and wait for it */ } if (SD != NULL) { for (i = 0; i < vinum_conf.subdisks_allocated; i++) { @@ -302,6 +305,17 @@ case MOD_UNLOAD: if (!vinum_inactive(1)) /* is anything open? */ return EBUSY; /* yes, we can't do it */ + if (vinum_conf.flags & VF_DAEMONOPEN) { /* DF-4760: daemon device open */ + union daemoninfo di = { .nothing = 0 }; + int daemon_wait = 5 * hz; + + queue_daemon_request(daemonrq_return, di); /* ask it to leave: ONCE */ + while ((vinum_conf.flags & VF_DAEMONOPEN) != 0 + && daemon_wait-- > 0) /* bounded wait */ + tsleep(&vinumclose, 0, "vstop", 1); + if (vinum_conf.flags & VF_DAEMONOPEN) /* it never left: */ + return EBUSY; /* tear nothing down */ + } vinum_conf.flags |= VF_STOPPING; /* note that we want to stop */ sys_sync(NULL, NULL); /* write out buffers */ free_vinum(0); /* clean up */ @@ -560,8 +574,20 @@ { cdev_t dev = ap->a_head.a_dev; struct volume *vol; + int index; - vol = &VOL[Volno(dev)]; + /* + * DF-4758: only volume devices carry a volume number in the minor. + * Raw plex/sd minors encode the plex/sd number in the low 8 bits, + * which Volno() extracts verbatim, so dispatch on the type and + * bound the index before touching the VOL[] array. + */ + if (DEVTYPE(dev) != VINUM_VOLUME_TYPE) + return (ENODEV); + index = Volno(dev); + if (index >= vinum_conf.volumes_allocated) + return (ENXIO); + vol = &VOL[index]; if (vol->state == volume_up) { ap->a_result = (int64_t)vol->size; |