Package: src:linux Version: 3.16.7-ckt20-1+deb8u3~bpo70+1 Severity: normal Dear Maintainer,
There was a regression in the Linux kernel which made the I/Os to sr devices (especially when ejecting or writing to DVD-Rs) synchronous (non parallel). If you write to a few DVD writes simultaneously, a 5-7x performance degradation will occur. You can reproduce the bug easily with: for i in /dev/sr?; do (eject $i&); done If the drives do not open (almost) simultaneously but sequentially, the bug is present. Reference: http://linux-scsi.vger.kernel.narkive.com/JLvupYok/patch-scsi-sr-fix-multi-drive-performance-by-using-per-device-mutexes I adapted a patch for that version below and successfully tested it. -- Package-specific info: ** Version: Linux version 3.16.0-0.bpo.4-amd64 (debian-ker...@lists.debian.org) (gcc version 4.6.3 (Debian 4.6.3-14) ) #1 SMP Debian 3.16.7-ckt20-1+deb8u3~bpo70+1 (2016-01-19) ** Command line: BOOT_IMAGE=/vmlinuz-3.16.0-0.bpo.4-amd64 root=/dev/mapper/vg1-root ro quiet --- drivers/scsi/sr.c 2015-11-18 11:08:46.000000000 +0100 +++ drivers/scsi/sr.c.NEW 2016-02-28 19:51:54.957158326 +0100 @@ -76,7 +76,6 @@ CDC_CD_R|CDC_CD_RW|CDC_DVD|CDC_DVD_R|CDC_DVD_RAM|CDC_GENERIC_PACKET| \ CDC_MRW|CDC_MRW_W|CDC_RAM) -static DEFINE_MUTEX(sr_mutex); static int sr_probe(struct device *); static int sr_remove(struct device *); static int sr_init_command(struct scsi_cmnd *SCpnt); @@ -520,24 +519,24 @@ struct scsi_cd *cd; int ret = -ENXIO; - mutex_lock(&sr_mutex); cd = scsi_cd_get(bdev->bd_disk); if (cd) { + mutex_lock(&cd->lock); ret = cdrom_open(&cd->cdi, bdev, mode); + mutex_unlock(&cd->lock); if (ret) scsi_cd_put(cd); } - mutex_unlock(&sr_mutex); return ret; } static void sr_block_release(struct gendisk *disk, fmode_t mode) { struct scsi_cd *cd = scsi_cd(disk); - mutex_lock(&sr_mutex); + mutex_lock(&cd->lock); cdrom_release(&cd->cdi, mode); + mutex_unlock(&cd->lock); scsi_cd_put(cd); - mutex_unlock(&sr_mutex); } static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, @@ -548,7 +547,7 @@ void __user *argp = (void __user *)arg; int ret; - mutex_lock(&sr_mutex); + mutex_lock(&cd->lock); /* * Send SCSI addressing ioctls directly to mid level, send other @@ -578,7 +577,7 @@ ret = scsi_ioctl(sdev, cmd, argp); out: - mutex_unlock(&sr_mutex); + mutex_unlock(&cd->lock); return ret; } @@ -673,6 +672,8 @@ if (!disk) goto fail_free; + mutex_init(&cd->lock); + spin_lock(&sr_index_lock); minor = find_first_zero_bit(sr_index_bits, SR_DISKS); if (minor == SR_DISKS) { @@ -742,6 +743,7 @@ fail_put: put_disk(disk); + mutex_destroy(&cd->lock); fail_free: kfree(cd); fail: @@ -978,6 +980,8 @@ put_disk(disk); + mutex_destroy(&cd->lock); + kfree(cd); } --- drivers/scsi/sr.h 2015-11-18 11:08:46.000000000 +0100 +++ drivers/scsi/sr.h.NEW 2016-02-28 19:45:26.533162171 +0100 @@ -19,6 +19,7 @@ #include <linux/genhd.h> #include <linux/kref.h> +#include <linux/mutex.h> #define MAX_RETRIES 3 #define SR_TIMEOUT (30 * HZ) @@ -49,6 +50,7 @@ bool ignore_get_event:1; /* GET_EVENT is unreliable, use TUR */ struct cdrom_device_info cdi; + struct mutex lock; /* We hold gendisk and scsi_device references on probe and use * the refs on this kref to decide when to release them */ struct kref kref;