summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>1999-11-06 10:25:58 +0000
committerphk <phk@FreeBSD.org>1999-11-06 10:25:58 +0000
commit6d8658fdf79a07f5d249e7026b9e69f16b59198a (patch)
treee54f14b9b7b4144b798c299e0ab03a31ffae3320
parentbd87d69eda3d704f97820326f8f17b533446670b (diff)
downloadFreeBSD-src-6d8658fdf79a07f5d249e7026b9e69f16b59198a.zip
FreeBSD-src-6d8658fdf79a07f5d249e7026b9e69f16b59198a.tar.gz
Put a lock on the disk structure while we open to avoid races.
PR: 14486
-rw-r--r--sys/kern/subr_disk.c18
-rw-r--r--sys/sys/disk.h6
2 files changed, 20 insertions, 4 deletions
diff --git a/sys/kern/subr_disk.c b/sys/kern/subr_disk.c
index b68948e..50cb1d8 100644
--- a/sys/kern/subr_disk.c
+++ b/sys/kern/subr_disk.c
@@ -52,7 +52,7 @@ disk_create(int unit, struct disk *dp, int flags, struct cdevsw *cdevsw, struct
dev->si_disk = dp;
dp->d_dev = dev;
- dp->d_flags = flags;
+ dp->d_dsflags = flags;
dp->d_devsw = cdevsw;
return (dev);
}
@@ -114,6 +114,12 @@ diskopen(dev_t dev, int oflags, int devtype, struct proc *p)
if (!dp)
return (ENXIO);
+ while (dp->d_flags & DISKFLAG_LOCK) {
+ dp->d_flags |= DISKFLAG_WANTED;
+ tsleep(dp, PRIBIO | PCATCH, "diskopen", hz);
+ }
+ dp->d_flags |= DISKFLAG_LOCK;
+
if (!dsisopen(dp->d_slice)) {
if (!pdev->si_iosize_max)
pdev->si_iosize_max = dev->si_iosize_max;
@@ -129,12 +135,18 @@ diskopen(dev_t dev, int oflags, int devtype, struct proc *p)
dev->si_bsize_best = pdev->si_bsize_best;
if (error)
- return(error);
+ goto out;
- error = dsopen(dev, devtype, dp->d_flags, &dp->d_slice, &dp->d_label);
+ error = dsopen(dev, devtype, dp->d_dsflags, &dp->d_slice, &dp->d_label);
if (!dsisopen(dp->d_slice))
dp->d_devsw->d_close(pdev, oflags, devtype, p);
+out:
+ dp->d_flags &= ~DISKFLAG_LOCK;
+ if (dp->d_flags & DISKFLAG_WANTED) {
+ dp->d_flags &= ~DISKFLAG_WANTED;
+ wakeup(dp);
+ }
return(error);
}
diff --git a/sys/sys/disk.h b/sys/sys/disk.h
index d5e1f9e..b93cae8 100644
--- a/sys/sys/disk.h
+++ b/sys/sys/disk.h
@@ -22,13 +22,17 @@
#endif /* _SYS_DISKLABEL */
struct disk {
- int d_flags;
+ u_int d_flags;
+ u_int d_dsflags;
struct cdevsw *d_devsw;
dev_t d_dev;
struct diskslices *d_slice;
struct disklabel d_label;
};
+#define DISKFLAG_LOCK 0x1
+#define DISKFLAG_WANTED 0x2
+
dev_t disk_create __P((int unit, struct disk *disk, int flags, struct cdevsw *cdevsw, struct cdevsw *diskdevsw));
void disk_delete __P((dev_t dev));
int disk_dumpcheck __P((dev_t dev, u_int *count, u_int *blkno, u_int *secsize));
OpenPOWER on IntegriCloud