DF-4599 / fix.diff
--- a/sys/dev/raid/vinum/vinumioctl.c +++ b/sys/dev/raid/vinum/vinumioctl.c @@ -217,13 +217,24 @@ * Note the open count. We may be called from v, so we'll be open. * Keep the count so we don't underflow */ - free_vinum(1); /* clean up everything */ - log(LOG_NOTICE, "vinum: CONFIGURATION OBLITERATED\n"); - ioctl_reply = (struct _ioctl_reply *) data; /* reinstate the address to reply to */ - ioctl_reply->error = 0; + error = lock_config(); /* DF-4599: free_vinum() must not race + * VINUM_CREATE, which holds the config + * lock while growing and freeing the + * DRIVE/SD/PLEX/VOL arrays */ + if (error) + break; + error = setjmp(command_fail); /* free_vinum -> remove_drive -> save_config may throw */ + if (error == 0) { + free_vinum(1); /* clean up everything */ + log(LOG_NOTICE, "vinum: CONFIGURATION OBLITERATED\n"); + ioctl_reply = (struct _ioctl_reply *) data; /* reinstate the address to reply to */ + ioctl_reply->error = 0; + } + unlock_config(); } else { error = EBUSY; } + break; /* DF-1741: no fallthrough into VINUM_SETSTATE */ case VINUM_SETSTATE: setstate((struct vinum_ioctl_msg *) data); /* set an object state */ |