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:
parent
048be6a261
commit
7a1d27b301
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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 *));
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user