lkml.org 
[lkml]   [2005]   [Dec]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[PATCH 2.6.15-rc6] block: Make CDROMEJECT more robust
    Reference: https://bugzilla.ubuntu.com/5049

    The eject command was failing for a large group of users for removable
    devices. The "eject -r" command, which uses the CDROMEJECT ioctl would not
    work, however "eject -s", which uses SG_IO did work, but required root access.

    Since SG_IO was using the same mechanism as CDROMEJECT, there should be no
    difference. The main reason for getting the CDROMEJECT ioctl working was
    because it didn't need root privileges like the SG_IO commands did.

    One bug was noticed, and that is CDROMEJECT was setting the blk request to a
    WRITE operation, when in fact it wasn't. The block layer did not like getting
    WRITE requests when data_len==0 and data==NULL.

    The other issue was that "eject -s" was sending two extra commands that
    seemed to work for just about any removable device. CDROMEJECT works as
    such:

    START_STOP : 0x02

    While "eject -s" sent(via SG_IO):

    ALLOW_MEDIUM_REMOVAL
    START_STOP : 0x01
    START_STOP : 0x02

    This patch fixes the WRITE vs READ issue, and also sends the extra two
    commands. Anyone with an iPod connected via USB (not sure about firewire)
    should be able to reproduce this issue, and verify the patch.


    diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
    index 382dea7..573da94 100644
    --- a/block/scsi_ioctl.c
    +++ b/block/scsi_ioctl.c
    @@ -442,11 +442,38 @@ error:
    return err;
    }

    +/* This is only useful for the following macros */
    +static int __blk_send_generic(request_queue_t *q, struct gendisk *bd_disk, int cmd, int data)
    +{
    + struct request *rq;
    + int err;
    +
    + rq = blk_get_request(q, READ, __GFP_WAIT);
    + rq->flags |= REQ_BLOCK_PC;
    + rq->data = NULL;
    + rq->data_len = 0;
    + rq->timeout = BLK_DEFAULT_TIMEOUT;
    + memset(rq->cmd, 0, sizeof(rq->cmd));
    + rq->cmd[0] = cmd;
    + rq->cmd[4] = data;
    + rq->cmd_len = 6;
    + err = blk_execute_rq(q, bd_disk, rq, 0);
    + blk_put_request(rq);
    +
    + return err;
    +}
    +
    +#define blk_send_start_stop(q, bd_disk, data) \
    + __blk_send_generic(q, bd_disk, GPCMD_START_STOP_UNIT, data)
    +
    +#define blk_send_allow_medium_removal(q, bd_disk) \
    + __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;
    - struct request *rq;
    - int close = 0, err;
    + int err;

    q = bd_disk->queue;
    if (!q)
    @@ -564,19 +591,14 @@ int scsi_cmd_ioctl(struct file *file, st
    err = sg_scsi_ioctl(file, q, bd_disk, arg);
    break;
    case CDROMCLOSETRAY:
    - close = 1;
    + err = blk_send_start_stop(q, bd_disk, 0x03);
    + break;
    case CDROMEJECT:
    - rq = blk_get_request(q, WRITE, __GFP_WAIT);
    - rq->flags |= REQ_BLOCK_PC;
    - rq->data = NULL;
    - rq->data_len = 0;
    - rq->timeout = BLK_DEFAULT_TIMEOUT;
    - memset(rq->cmd, 0, sizeof(rq->cmd));
    - rq->cmd[0] = GPCMD_START_STOP_UNIT;
    - rq->cmd[4] = 0x02 + (close != 0);
    - rq->cmd_len = 6;
    - err = blk_execute_rq(q, bd_disk, rq, 0);
    - blk_put_request(rq);
    + 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;
    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/
    \
     
     \ /
      Last update: 2005-12-19 17:44    [W:0.025 / U:0.292 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site