Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 16 Jul 2007 19:17:37 +0200 (CEST)
From:      Tijl Coosemans <tijl@ulyssis.org>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   kern/114636: [patch] ioctl on empty scsi/atapicam cdrom drive locks up entire system
Message-ID:  <200707161717.l6GHHbwp001586@kalimero.kotnet.org>
Resent-Message-ID: <200707161750.l6GHo2qY065242@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         114636
>Category:       kern
>Synopsis:       [patch] ioctl on empty scsi/atapicam cdrom drive locks up entire system
>Confidential:   no
>Severity:       critical
>Priority:       high
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Mon Jul 16 17:50:01 GMT 2007
>Closed-Date:
>Last-Modified:
>Originator:     Tijl Coosemans
>Release:        FreeBSD 7.0-CURRENT i386
>Organization:
>Environment:
cd0 at ata1 bus 0 target 0 lun 0
cd0: <MATSHITA UJ-831D 1.00> Removable CD-ROM SCSI-0 device
cd0: 3.300MB/s transfers
cd0: Attempt to query device size failed: NOT READY, Medium not present

>Description:
An ioctl call on an empty scsi/atapicam cdrom drive causes
the system to semi-hang when the file descriptor is later
closed. Semi meaning the system is responsive to mouse and
keyboard, but (most) processes hang and no new processes can
be started. Pressing ctrl+alt+delete responds by disabling
terminals but doesn't reset the system. A hard reset is
needed to recover.

>How-To-Repeat:
The following program opens /dev/cd0 and does CDIOCSTART
to spin up the drive. When the drive is empty the close(2)
call causes the entire system to (semi-)hang.

BE WARNED because a hard reset is required to recover.
So don't try if you don't like fsck.

--- cdrom.c begins here ---
#include <sys/cdio.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

int main(void) {
	int fd;
	int ret;

	fd = open( "/dev/cd0", O_RDONLY );
	ret = ioctl( fd, CDIOCSTART );
	printf( "ret = %d, errno = %d\n", ret, errno );

	close( fd );	
	return 0;
}
--- cdrom.c ends here ---

>Fix:
The problem is caused by a forgotten cam_periph_unhold()
when there's no media in the drive.

--- patch-sys-cam-scsi-scsi_cd.c begins here ---
--- sys/cam/scsi/scsi_cd.c.orig	2007-07-12 15:32:30.000000000 +0200
+++ sys/cam/scsi/scsi_cd.c	2007-07-12 15:39:15.000000000 +0200
@@ -1859,16 +1859,18 @@
 	 && ((cmd != CDIOCCLOSE)
 	  && (cmd != CDIOCEJECT))
 	 && (IOCGROUP(cmd) == 'c')) {
-		error = cdcheckmedia(periph);
+		if ((error = cdcheckmedia(periph)) != 0) {
+			cam_periph_unhold(periph);
+			cam_periph_unlock(periph);
+			return (error);
+		}
 	}
+
 	/*
 	 * Drop the lock here so later mallocs can use WAITOK.  The periph
 	 * is essentially locked still with the cam_periph_hold call above.
 	 */
 	cam_periph_unlock(periph);
-	if (error != 0)
-		return (error);
-
 	nocopyout = 0;
 	switch (cmd) {
 
--- patch-sys-cam-scsi-scsi_cd.c ends here ---
>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200707161717.l6GHHbwp001586>