kern/116539: [fdc] fdc(4) marks /dev/fd0 device busy when it should not, so does not allow to kldunload fdc.ko

Eugene Grosbein eugen at grosbein.pp.ru
Fri Sep 21 23:20:01 PDT 2007


>Number:         116539
>Category:       kern
>Synopsis:       [fdc] fdc(4) marks /dev/fd0 device busy when it should not, so does not allow to kldunload fdc.ko
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sat Sep 22 06:20:00 GMT 2007
>Closed-Date:
>Last-Modified:
>Originator:     Eugene Grosbein
>Release:        FreeBSD 6.2-STABLE i386
>Organization:
Svyaz-Service JSC
>Environment:
System: FreeBSD grosbein.pp.ru 6.2-STABLE FreeBSD 6.2-STABLE #2: Sun Sep 16 16:54:23 KRAST 2007 eu at grosbein.pp.ru:/home/obj/usr/local/src/sys/DADV i386

>Description:
	Any access to /dev/fd0 results in call to device_busy(fd->dev)
	and should entail appropriate device_unbusy(fd->dev).
	However, an attempt to write access to write-protected floppy
	leads to device_busy(fd->dev) without corresponding
	device_unbusy(fd->dev). This locks fdc.ko from unloading.

>How-To-Repeat:
	Boot kernel without fdc(4) compiled-in. Load fdc(4) by means
	of loader or kldload having write-protected floppy in the drive
	when fdc(4) initializes. Do:

echo -n >/dev/fd0

	You'll get 'Read-only file system' error and will not be allowed
	to unload fdc.ko after that. One may use following patch to see
	what happens inside kernel. You should 'debug.fdc.debugflags=64'
	in the /boot/loader.conf to see what happens.

	You can also try 'debug.fdc.debugflags=320' to enable
	this patch's ability to force device unlocking for such case
	but this is not correct solution. It will unbusy device
	in cases where it should not: device is mounted read-only
	and an attempt to open it for writing is performed. The patch
	will call device_unbusy(fd->dev) allowing to unload fdc.ko
	while device is still mounted. I do not know correct solution.
	
--- sys/dev/fdc/fdc.c.orig	2007-09-15 16:53:23.000000000 +0800
+++ sys/dev/fdc/fdc.c	2007-09-16 16:26:07.000000000 +0800
@@ -1389,6 +1393,8 @@
 	ae = e + pp->ace;
 
 	if (ar == 0 && aw == 0 && ae == 0) {
+		if (debugflags & 0x40)
+			device_printf(fdc->fdc_dev, "marked not busy\n");
 		device_unbusy(fd->dev);
 		return (0);
 	}
@@ -1404,11 +1410,20 @@
 			fd->flags &= ~FD_NEWDISK;
 			mtx_unlock(&fdc->fdc_mtx);
 		}
+		if (debugflags & 0x40)
+			device_printf(fdc->fdc_dev, "marked busy\n");
 		device_busy(fd->dev);
 	}
 
-	if (w > 0 && (fd->flags & FD_WP))
+	if (w > 0 && (fd->flags & FD_WP)) {
+		if ((debugflags & 0x100) && 
+		    (device_get_state(fd->dev) == DS_BUSY)) {
+			if (debugflags & 0x40)
+			    device_printf(fdc->fdc_dev, "marked not busy\n");
+			device_unbusy(fd->dev);
+		}
 		return (EROFS);
+	}
 
 	pp->sectorsize = fd->sectorsize;
 	pp->stripesize = fd->ft->heads * fd->ft->sectrac * fd->sectorsize;
@@ -1749,6 +1764,7 @@
 
 	fdc = device_get_softc(dev);
 	fdc->fdc_dev = dev;
+	TUNABLE_INT_FETCH("debug.fdc.debugflags", &debugflags);
 	error = fdc_initial_reset(dev, fdc);
 	if (error) {
 		device_printf(dev, "does not respond\n");

>Fix:

	Unknown.
>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list