git: e2c1243f427b - main - fd: Move from using device_busy to a refcount
Warner Losh
imp at FreeBSD.org
Thu Sep 30 02:19:55 UTC 2021
The branch main has been updated by imp:
URL: https://cgit.FreeBSD.org/src/commit/?id=e2c1243f427b7dd387efd42669cc199cbb9b514c
commit e2c1243f427b7dd387efd42669cc199cbb9b514c
Author: Warner Losh <imp at FreeBSD.org>
AuthorDate: 2021-09-30 02:18:28 +0000
Commit: Warner Losh <imp at FreeBSD.org>
CommitDate: 2021-09-30 02:18:28 +0000
fd: Move from using device_busy to a refcount
Use refcounting to delay the detach rather than device_busy and/or
device_unbusy. fd/fdc is one of the few consumers of device_busy in the
tree for that, and it's not a good fit. Also, nothing is waking 'fd' and
other drivers don't loop like this. Return EBUSY if we still have active
users.
Sponsored by: Netflix
Reviewed by: mav
Differential Revision: https://reviews.freebsd.org/D31830
---
sys/dev/fdc/fdc.c | 34 +++++++++++++++++++++++-----------
1 file changed, 23 insertions(+), 11 deletions(-)
diff --git a/sys/dev/fdc/fdc.c b/sys/dev/fdc/fdc.c
index 11262231c3b2..6f035e9689f1 100644
--- a/sys/dev/fdc/fdc.c
+++ b/sys/dev/fdc/fdc.c
@@ -261,6 +261,7 @@ struct fd_data {
struct g_provider *fd_provider;
device_t dev;
struct bio_queue_head fd_bq;
+ bool gone;
};
#define FD_NOT_VALID -2
@@ -1398,6 +1399,7 @@ fdautoselect(struct fd_data *fd)
static g_access_t fd_access;
static g_start_t fd_start;
static g_ioctl_t fd_ioctl;
+static g_provgone_t fd_providergone;
struct g_class g_fd_class = {
.name = "FD",
@@ -1405,6 +1407,7 @@ struct g_class g_fd_class = {
.start = fd_start,
.access = fd_access,
.ioctl = fd_ioctl,
+ .providergone = fd_providergone,
};
static int
@@ -1413,7 +1416,6 @@ fd_access(struct g_provider *pp, int r, int w, int e)
struct fd_data *fd;
struct fdc_data *fdc;
int ar, aw, ae;
- int busy;
fd = pp->geom->softc;
fdc = fd->fdc;
@@ -1431,11 +1433,9 @@ fd_access(struct g_provider *pp, int r, int w, int e)
if (ar == 0 && aw == 0 && ae == 0) {
fd->options &= ~(FDOPT_NORETRY | FDOPT_NOERRLOG | FDOPT_NOERROR);
- device_unbusy(fd->dev);
return (0);
}
- busy = 0;
if (pp->acr == 0 && pp->acw == 0 && pp->ace == 0) {
if (fdmisccmd(fd, BIO_PROBE, NULL))
return (ENXIO);
@@ -1453,13 +1453,9 @@ fd_access(struct g_provider *pp, int r, int w, int e)
fd->flags &= ~FD_NEWDISK;
mtx_unlock(&fdc->fdc_mtx);
}
- device_busy(fd->dev);
- busy = 1;
}
if (w > 0 && (fd->flags & FD_WP)) {
- if (busy)
- device_unbusy(fd->dev);
return (EROFS);
}
@@ -1588,8 +1584,6 @@ fd_ioctl(struct g_provider *pp, u_long cmd, void *data, int fflag, struct thread
return (error);
};
-
-
/*
* Configuration/initialization stuff, per controller.
*/
@@ -2055,6 +2049,16 @@ fd_attach(device_t dev)
return (0);
}
+static void
+fd_providergone(struct g_provider *pp)
+{
+ struct fd_data *fd;
+
+ fd = pp->geom->softc;
+ fd->gone = true;
+ wakeup(fd);
+}
+
static void
fd_detach_geom(void *arg, int flag)
{
@@ -2070,9 +2074,17 @@ fd_detach(device_t dev)
struct fd_data *fd;
fd = device_get_softc(dev);
+
g_waitfor_event(fd_detach_geom, fd, M_WAITOK, NULL);
- while (device_get_state(dev) == DS_BUSY)
- tsleep(fd, PZERO, "fdd", hz/10);
+ while (!fd->gone) {
+ tsleep(fd, PZERO, "fdgone", hz/10);
+ }
+
+ /*
+ * There may be accesses to the floppy while we're waitng, so drain the
+ * motor callback here. fdc_detach turns off motor if it's still on when
+ * we get to this point.
+ */
callout_drain(&fd->toffhandle);
return (0);
More information about the dev-commits-src-all
mailing list