Signed-off-by: Tim Small <tim@xxxxxxxxxxx> --- drivers/cdrom/cdrom.c | 86 +++++++++++++++++++++++++++++++++++---------------- include/linux/cdrom.h | 1 + 2 files changed, 60 insertions(+), 27 deletions(-) diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index 5d28a45..c39bef1 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -633,6 +633,8 @@ int register_cdrom(struct cdrom_device_info *cdi) if (!cdo->generic_packet) cdo->generic_packet = cdrom_dummy_generic_packet; + mutex_init(&cdi->ioctl_mutex); + cd_dbg(CD_REG_UNREG, "drive \"/dev/%s\" registered\n", cdi->name); mutex_lock(&cdrom_mutex); list_add(&cdi->list, &cdrom_list); @@ -3315,41 +3317,60 @@ int cdrom_ioctl(struct cdrom_device_info *cdi, struct block_device *bdev, if (ret != -ENOTTY) return ret; + mutex_lock(&cdi->ioctl_mutex); + switch (cmd) { case CDROMMULTISESSION: - return cdrom_ioctl_multisession(cdi, argp); + ret = cdrom_ioctl_multisession(cdi, argp); + goto out; case CDROMEJECT: - return cdrom_ioctl_eject(cdi); + ret = cdrom_ioctl_eject(cdi); + goto out; case CDROMCLOSETRAY: - return cdrom_ioctl_closetray(cdi); + ret = cdrom_ioctl_closetray(cdi); + goto out; case CDROMEJECT_SW: - return cdrom_ioctl_eject_sw(cdi, arg); + ret = cdrom_ioctl_eject_sw(cdi, arg); + goto out; case CDROM_MEDIA_CHANGED: - return cdrom_ioctl_media_changed(cdi, arg); + ret = cdrom_ioctl_media_changed(cdi, arg); + goto out; case CDROM_SET_OPTIONS: - return cdrom_ioctl_set_options(cdi, arg); + ret = cdrom_ioctl_set_options(cdi, arg); + goto out; case CDROM_CLEAR_OPTIONS: - return cdrom_ioctl_clear_options(cdi, arg); + ret = cdrom_ioctl_clear_options(cdi, arg); + goto out; case CDROM_SELECT_SPEED: - return cdrom_ioctl_select_speed(cdi, arg); + ret = cdrom_ioctl_select_speed(cdi, arg); + goto out; case CDROM_SELECT_DISC: - return cdrom_ioctl_select_disc(cdi, arg); + ret = cdrom_ioctl_select_disc(cdi, arg); + goto out; case CDROMRESET: - return cdrom_ioctl_reset(cdi, bdev); + ret = cdrom_ioctl_reset(cdi, bdev); + goto out; case CDROM_LOCKDOOR: - return cdrom_ioctl_lock_door(cdi, arg); + ret = cdrom_ioctl_lock_door(cdi, arg); + goto out; case CDROM_DEBUG: - return cdrom_ioctl_debug(cdi, arg); + ret = cdrom_ioctl_debug(cdi, arg); + goto out; case CDROM_GET_CAPABILITY: - return cdrom_ioctl_get_capability(cdi); + ret = cdrom_ioctl_get_capability(cdi); + goto out; case CDROM_GET_MCN: - return cdrom_ioctl_get_mcn(cdi, argp); + ret = cdrom_ioctl_get_mcn(cdi, argp); + goto out; case CDROM_DRIVE_STATUS: - return cdrom_ioctl_drive_status(cdi, arg); + ret = cdrom_ioctl_drive_status(cdi, arg); + goto out; case CDROM_DISC_STATUS: - return cdrom_ioctl_disc_status(cdi); + ret = cdrom_ioctl_disc_status(cdi); + goto out; case CDROM_CHANGER_NSLOTS: - return cdrom_ioctl_changer_nslots(cdi); + ret = cdrom_ioctl_changer_nslots(cdi); + goto out; } /* @@ -3361,7 +3382,7 @@ int cdrom_ioctl(struct cdrom_device_info *cdi, struct block_device *bdev, if (CDROM_CAN(CDC_GENERIC_PACKET)) { ret = mmc_ioctl(cdi, cmd, arg); if (ret != -ENOTTY) - return ret; + goto out; } /* @@ -3371,27 +3392,38 @@ int cdrom_ioctl(struct cdrom_device_info *cdi, struct block_device *bdev, */ switch (cmd) { case CDROMSUBCHNL: - return cdrom_ioctl_get_subchnl(cdi, argp); + ret = cdrom_ioctl_get_subchnl(cdi, argp); + goto out; case CDROMREADTOCHDR: - return cdrom_ioctl_read_tochdr(cdi, argp); + ret = cdrom_ioctl_read_tochdr(cdi, argp); + goto out; case CDROMREADTOCENTRY: - return cdrom_ioctl_read_tocentry(cdi, argp); + ret = cdrom_ioctl_read_tocentry(cdi, argp); + goto out; case CDROMPLAYMSF: - return cdrom_ioctl_play_msf(cdi, argp); + ret = cdrom_ioctl_play_msf(cdi, argp); + goto out; case CDROMPLAYTRKIND: - return cdrom_ioctl_play_trkind(cdi, argp); + ret = cdrom_ioctl_play_trkind(cdi, argp); + goto out; case CDROMVOLCTRL: - return cdrom_ioctl_volctrl(cdi, argp); + ret = cdrom_ioctl_volctrl(cdi, argp); + goto out; case CDROMVOLREAD: - return cdrom_ioctl_volread(cdi, argp); + ret = cdrom_ioctl_volread(cdi, argp); + goto out; case CDROMSTART: case CDROMSTOP: case CDROMPAUSE: case CDROMRESUME: - return cdrom_ioctl_audioctl(cdi, cmd); + ret = cdrom_ioctl_audioctl(cdi, cmd); + goto out; } - return -ENOSYS; + ret = -ENOSYS; +out: + mutex_unlock(&cdi->ioctl_mutex); + return ret; } EXPORT_SYMBOL(cdrom_get_last_written); diff --git a/include/linux/cdrom.h b/include/linux/cdrom.h index 8609d57..954e659 100644 --- a/include/linux/cdrom.h +++ b/include/linux/cdrom.h @@ -40,6 +40,7 @@ struct cdrom_device_info { struct list_head list; /* linked list of all device_info */ struct gendisk *disk; /* matching block layer disk */ void *handle; /* driver-dependent data */ + struct mutex ioctl_mutex; /* cdrom_ioctl_* not all thread safe */ /* specifications */ int mask; /* mask of capability: disables them */ int speed; /* maximum speed for reading data */ -- 2.1.3 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html