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