Introduce an advisory exclusive lock on the scsi link structure.

Change sd_open, sd_close and sd_ioctl to use this lock to ensure
serialization of some critical operations, thus avoiding some
race conditions. Ideas picked from NetBSD (ccd and sd devices).
This fixes one of the problems noted in PR kern/3688.
Reviewed by:	"Justin T. Gibbs" <gibbs@plutotech.com>
This commit is contained in:
Tor Egge 1997-06-25 19:07:43 +00:00
parent 048be6a261
commit 7a1d27b301
4 changed files with 47 additions and 4 deletions

View File

@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: scsi_driver.c,v 1.22 1997/02/22 09:44:31 peter Exp $
* $Id: scsi_driver.c,v 1.23 1997/03/23 06:33:47 bde Exp $
*
*/
@ -232,3 +232,25 @@ scsi_strategy(struct buf *bp, struct scsi_device *device)
}
}
}
int scsi_device_lock(struct scsi_link *sc_link)
{
int error;
while (sc_link->flags & SDEV_XLOCK) {
sc_link->flags |= SDEV_WANT;
error = tsleep(&sc_link->flags, PRIBIO | PCATCH, "sdevlk",0);
if (error)
return error;
}
sc_link->flags |= SDEV_XLOCK;
return 0;
}
void scsi_device_unlock(struct scsi_link *sc_link)
{
sc_link->flags &= ~SDEV_XLOCK;
if (sc_link->flags & SDEV_WANT) {
sc_link->flags &= ~SDEV_WANT;
wakeup(&sc_link->flags);
}
}

View File

@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: scsi_driver.h,v 1.10 1997/02/22 09:44:31 peter Exp $
* $Id: scsi_driver.h,v 1.11 1997/03/23 04:39:07 bde Exp $
*
*/
#ifndef _SCSI__DRIVER_H_
@ -50,6 +50,8 @@ struct proc;
int scsi_goaway __P((int));
int scsi_device_attach __P((struct scsi_link *));
int scsi_device_lock __P((struct scsi_link *));
void scsi_device_unlock __P((struct scsi_link *));
int scsi_open __P((dev_t, int, int, struct proc *, struct scsi_device *));
int scsi_close __P((dev_t, int, int, struct proc *, struct scsi_device *));

View File

@ -14,7 +14,7 @@
*
* Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
*
* $Id: scsiconf.h,v 1.53 1997/04/03 10:09:29 kato Exp $
* $Id: scsiconf.h,v 1.54 1997/05/19 17:32:10 jmz Exp $
*/
#ifndef SCSI_SCSICONF_H
#define SCSI_SCSICONF_H 1
@ -337,6 +337,8 @@ struct scsi_link
#define SDEV_TARGET_OPS 0x0800 /* XXX-HA: Supports target ops */
#define SDEV_IS_OPEN 0x1000 /* at least 1 open session */
#define SDEV_UK 0x2000 /* this is the "uk" device */
#define SDEV_XLOCK 0x4000 /* Device is locked */
#define SDEV_WANT 0x8000 /* A process is waiting for lock */
/*
* One of these is allocated and filled in for each scsi bus.

View File

@ -15,7 +15,7 @@
*
* Ported to run under 386BSD by Julian Elischer (julian@dialix.oz.au) Sept 1992
*
* $Id: sd.c,v 1.104 1997/03/24 11:25:02 bde Exp $
* $Id: sd.c,v 1.105 1997/05/01 19:15:38 sos Exp $
*/
#include "opt_bounce.h"
@ -279,6 +279,10 @@ sd_open(dev, mode, fmt, p, sc_link)
*/
scsi_test_unit_ready(sc_link, 0);
errcode = scsi_device_lock(sc_link);
if (errcode)
return errcode;
/*
* If it's been invalidated, then forget the label
*/
@ -354,6 +358,7 @@ sd_open(dev, mode, fmt, p, sc_link)
SC_DEBUG(sc_link, SDEV_DB3, ("open %ld %ld\n", sdstrats, sdqueues));
scsi_device_unlock(sc_link);
return 0;
bad:
@ -361,6 +366,7 @@ sd_open(dev, mode, fmt, p, sc_link)
scsi_prevent(sc_link, PR_ALLOW, SCSI_ERR_OK | SCSI_SILENT);
sc_link->flags &= ~SDEV_OPEN;
}
scsi_device_unlock(sc_link);
return errcode;
}
@ -377,13 +383,18 @@ sd_close(dev, fflag, fmt, p, sc_link)
struct scsi_link *sc_link;
{
struct scsi_data *sd;
errval errcode;
sd = sc_link->sd;
errcode = scsi_device_lock(sc_link);
if (errcode)
return errcode;
dsclose(dev, fmt, sd->dk_slices);
if (!dsisopen(sd->dk_slices)) {
scsi_prevent(sc_link, PR_ALLOW, SCSI_SILENT | SCSI_ERR_OK);
sc_link->flags &= ~SDEV_OPEN;
}
scsi_device_unlock(sc_link);
return (0);
}
@ -661,8 +672,14 @@ sd_ioctl(dev_t dev, int cmd, caddr_t addr, int flag, struct proc *p,
if (cmd == DIOCSBAD)
return (EINVAL); /* XXX */
error = scsi_device_lock(sc_link);
if (error)
return error;
error = dsioctl("sd", dev, cmd, addr, flag, &sd->dk_slices,
sdstrategy1, (ds_setgeom_t *)NULL);
scsi_device_unlock(sc_link);
if (error != -1)
return (error);
if (PARTITION(dev) != RAW_PART)