use lockmgr() instead of bespoke code for mutual exclusion in fss_ioctl().

only take the lock when we actually need it (and particularly not for
unknown cmds that are just going to fail immediately).  fixes PR 33060.
This commit is contained in:
chs 2006-03-14 15:07:29 +00:00
parent ae84301430
commit 3b7a4338db
2 changed files with 12 additions and 21 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: fss.c,v 1.22 2006/01/11 00:49:59 yamt Exp $ */
/* $NetBSD: fss.c,v 1.23 2006/03/14 15:07:29 chs Exp $ */
/*-
* Copyright (c) 2003 The NetBSD Foundation, Inc.
@ -43,7 +43,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: fss.c,v 1.22 2006/01/11 00:49:59 yamt Exp $");
__KERNEL_RCSID(0, "$NetBSD: fss.c,v 1.23 2006/03/14 15:07:29 chs Exp $");
#include "fss.h"
@ -162,6 +162,7 @@ fssattach(int num)
sc->sc_unit = i;
sc->sc_bdev = NODEV;
simple_lock_init(&sc->sc_slock);
lockinit(&sc->sc_lock, PRIBIO, "fsslock", 0, 0);
bufq_alloc(&sc->sc_bufq, "fcfs", 0);
}
}
@ -262,7 +263,7 @@ fss_write(dev_t dev, struct uio *uio, int flags)
int
fss_ioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct lwp *l)
{
int s, error;
int error;
struct fss_softc *sc;
struct fss_set *fss = (struct fss_set *)data;
struct fss_get *fsg = (struct fss_get *)data;
@ -270,37 +271,31 @@ fss_ioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct lwp *l)
if ((sc = FSS_DEV_TO_SOFTC(dev)) == NULL)
return ENODEV;
FSS_LOCK(sc, s);
while ((sc->sc_flags & FSS_EXCL) == FSS_EXCL) {
error = ltsleep(sc, PRIBIO|PCATCH, "fsslock", 0, &sc->sc_slock);
if (error) {
FSS_UNLOCK(sc, s);
return error;
}
}
sc->sc_flags |= FSS_EXCL;
FSS_UNLOCK(sc, s);
switch (cmd) {
case FSSIOCSET:
lockmgr(&sc->sc_lock, LK_EXCLUSIVE, NULL);
if ((flag & FWRITE) == 0)
error = EPERM;
else if ((sc->sc_flags & FSS_ACTIVE) != 0)
error = EBUSY;
else
error = fss_create_snapshot(sc, fss, l);
lockmgr(&sc->sc_lock, LK_RELEASE, NULL);
break;
case FSSIOCCLR:
lockmgr(&sc->sc_lock, LK_EXCLUSIVE, NULL);
if ((flag & FWRITE) == 0)
error = EPERM;
else if ((sc->sc_flags & FSS_ACTIVE) == 0)
error = ENXIO;
else
error = fss_delete_snapshot(sc, l);
lockmgr(&sc->sc_lock, LK_RELEASE, NULL);
break;
case FSSIOCGET:
lockmgr(&sc->sc_lock, LK_EXCLUSIVE, NULL);
switch (sc->sc_flags & (FSS_PERSISTENT | FSS_ACTIVE)) {
case FSS_ACTIVE:
memcpy(fsg->fsg_mount, sc->sc_mntname, MNAMELEN);
@ -322,6 +317,7 @@ fss_ioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct lwp *l)
error = ENXIO;
break;
}
lockmgr(&sc->sc_lock, LK_RELEASE, NULL);
break;
case FSSIOFSET:
@ -339,11 +335,6 @@ fss_ioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct lwp *l)
break;
}
FSS_LOCK(sc, s);
sc->sc_flags &= ~FSS_EXCL;
FSS_UNLOCK(sc, s);
wakeup(sc);
return error;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: fssvar.h,v 1.12 2005/12/11 12:20:53 christos Exp $ */
/* $NetBSD: fssvar.h,v 1.13 2006/03/14 15:07:29 chs Exp $ */
/*-
* Copyright (c) 2003 The NetBSD Foundation, Inc.
@ -144,11 +144,11 @@ struct fss_cache {
struct fss_softc {
int sc_unit; /* Logical unit number */
struct simplelock sc_slock; /* Protect this softc */
struct lock sc_lock; /* Sleep lock for fss_ioctl */
volatile int sc_flags; /* Flags */
#define FSS_ACTIVE 0x01 /* Snapshot is active */
#define FSS_ERROR 0x02 /* I/O error occurred */
#define FSS_BS_THREAD 0x04 /* Kernel thread is running */
#define FSS_EXCL 0x08 /* Exclusive access granted */
#define FSS_PERSISTENT 0x20 /* File system internal snapshot */
#define FSS_CDEV_OPEN 0x40 /* character device open */
#define FSS_BDEV_OPEN 0x80 /* block device open */