Signed-off-by: Tim Small <t...@seoss.co.uk>
---
 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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to