diff --git a/sys/kern/subr_disk.c b/sys/kern/subr_disk.c index b68948ed6c09..50cb1d827fdb 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 d5e1f9e6b035..b93cae87526e 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));