Skip to contentSkip to conversation

CDROMEJECT cannot eject some devices

PATCH In review Randy Dunlap 3 participants 3 messages Jul 3, 2006

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 CDROMEJECT cannot eject some devices

Fix the bug where CDROMEJECT cannot eject some devices.

bug discussion: https://bugzilla.ubuntu.com/show_bug.cgi?id=5049

Patch location:
http://www.kernel.org/git/?p=linux/kernel/git/bcollins/ubuntu-dapper.git;a=commitdiff;h=f431f87fc9ac9ba248f43662ef9da9cdaa3418c2

---
 block/scsi_ioctl.c |   13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)
block/scsi_ioctl.c +11 -2
@@ -501,7 +501,7 @@ static int __blk_send_generic(request_qu
 	struct request *rq;
 	int err;
 
-	rq = blk_get_request(q, WRITE, __GFP_WAIT);
+	rq = blk_get_request(q, READ, __GFP_WAIT);
 	rq->flags |= REQ_BLOCK_PC;
 	rq->data = NULL;
 	rq->data_len = 0;
@@ -521,6 +521,11 @@ static inline int blk_send_start_stop(re
 	return __blk_send_generic(q, bd_disk, GPCMD_START_STOP_UNIT, data);
 }
 
+static inline int blk_send_allow_medium_removal(request_queue_t *q, struct gendisk *bd_disk)
+{
+	return __blk_send_generic(q, bd_disk, GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL, 0);
+}
+
 int scsi_cmd_ioctl(struct file *file, struct gendisk *bd_disk, unsigned int cmd, void __user *arg)
 {
 	request_queue_t *q;
@@ -645,7 +650,11 @@ int scsi_cmd_ioctl(struct file *file, st
 			err = blk_send_start_stop(q, bd_disk, 0x03);
 			break;
 		case CDROMEJECT:
-			err = blk_send_start_stop(q, bd_disk, 0x02);
+			err = 0;
+
+			err |= blk_send_allow_medium_removal(q, bd_disk);
+			err |= blk_send_start_stop(q, bd_disk, 0x01);
+			err |= blk_send_start_stop(q, bd_disk, 0x02);
 			break;
 		default:
 			err = -ENOTTY;
#1 lore raw

block/scsi_ioctl.c static int __blk_send_generic(request_qu · line 504

Quoted 11 lines · Randy Dunlap

Fix the bug where CDROMEJECT cannot eject some devices.

block/scsi_ioctl.c +1 -1
@@ -501,7 +501,7 @@ static int __blk_send_generic(request_qu
 	struct request *rq;
 	int err;
 
-	rq = blk_get_request(q, WRITE, __GFP_WAIT);
+	rq = blk_get_request(q, READ, __GFP_WAIT);

I don't believe this hunk is necessary for mainline. IIRC, there was a bug around length checks vs read vs write which is now fixed. Presumably it's still needed in Ubuntu's kernel though.

#2 lore raw
In reply to Randy Dunlap

block/scsi_ioctl.c int scsi_cmd_ioctl(struct file *file, st · line 655

Quoted 4 lines · Randy Dunlap
block/scsi_ioctl.c +3 -1
-			err = blk_send_start_stop(q, bd_disk, 0x02);
+			err = 0;
+
+			err |= blk_send_allow_medium_removal(q, bd_disk);

This piece is clearly wrong. If the medium has physically been locked (and the lock is managed by the cdrom layer) then we don't want to be overriding it. It should be up to the user or the tools to figure out who has it open or mounted and take the appropriate action.

block/scsi_ioctl.c int scsi_cmd_ioctl(struct file *file, st · line 656

Quoted 1 line
block/scsi_ioctl.c +1 -0
+			err |= blk_send_start_stop(q, bd_disk, 0x01);

And this looks unnecessary. Why does the device need to be started to eject its medium?

block/scsi_ioctl.c int scsi_cmd_ioctl(struct file *file, st · line 657

Quoted 1 line
block/scsi_ioctl.c +1 -0
+			err |= blk_send_start_stop(q, bd_disk, 0x02);

James