6 ConcurrentLinuxSr
Thomas Schmitt edited this page 6 months ago

The problems with concurrent burns on Linux

Beginning with high version numbers of Linux kernel 2.6 and up to probably kernel 5.6 or 5.7 there is a performance problem when more than one optical drive is used for burning or reading via libburn at the same time. The overall throughput is less than the throughput of the slowest drive when it is used as only one.

This affects SATA and USB attached drives alike. Most probably also IDE attached ones.

Kernel theory

The most plausible explanation for the problem is the introduction of a global lock for all optical drives which is held during the whole transaction time of ioctl(SG_IO). This ioctl is used by libburn to send SCSI commands to the burner drive. So each single burner blocks the other libburn processes until it has ended its transaction.

See the problematic changeset which affected drivers/scsi/sr.c among many other kernel parts:

https://lkml.org/lkml/2010/9/14/338

and the summary of consequences with remedy proposal:

http://marc.info/?l=linux-scsi&m=135705061804384&w=2

Obviously the deprecated device file family /dev/sg* does not have such a lock.

Relief can be expected by a commit of Feb 24, 2020:

51a858817d

At that time, the kernel version was in the 5.6-rc era.

Consequences for libburn

Using /dev/sg* against all good advise

The libburn call burn_preset_device_open(), cdrskin option drive_scsi_dev_family=, and xorriso command -scsi_dev_family can cause libburn to use /dev/sg* instead of /dev/sr*. Without such special setting a /dev/sg* address given by the user would be mapped to the corresponding /dev/sr*.

These runs of version 1.4.4 or higher can coexist without throughput problems:

xorriso -scsi_dev_family sg -dev /dev/sr0 -map ./data /data
xorriso -as cdrecord drive_scsi_dev_family=sg dev=/dev/sr1 -v image2.iso
cdrskin drive_scsi_dev_family=sg dev=/dev/sr3 -v image3.iso

/dev/sg with older versions of cdrskin

A bug in libburn-0.5.2 to 1.4.2 prevented automatic conversion from /dev/sr* addresses to /dev/sg* addresses if drive_scsi_dev_family=sg is given. xorriso up to version 1.4.2 did not offer the opportunity to use /dev/sg*.

Nevertheless it is possible to let older cdrskin versions work with /dev/sg*:

$ cdrskin drive_scsi_dev_family=sg --devices
...
  0  dev='/dev/sg2'  rwrw-- :  'HL-DT-ST'  'BDDVDRW GGC-H20L'
  1  dev='/dev/sg3'  rwrw-- :  'HL-DT-ST'  'DVDRAM GH24NSC0'
  2  dev='/dev/sg4'  rwrw-- :  'ASUS    '  'BW-16D1HT'
  3  dev='/dev/sg5'  rwrw-- :  'HL-DT-ST'  'BD-RE GGW-H20L'
  4  dev='/dev/sg6'  rwrw-- :  'Optiarc '  'BD RW BD-5300S'
$ cdrskin drive_scsi_dev_family=sg dev=/dev/sg2 -v image1.iso
$ cdrskin drive_scsi_dev_family=sg dev=/dev/sg3 -v image2.iso
$ cdrskin drive_scsi_dev_family=sg dev=/dev/sg6 -v image3.iso

Meanwhile the releases on release page have the bug fixed and xorriso augmented by a new command.

Changing kernel source to make /dev/sr* as fast as /dev/sg*

Despite the fine performance of /dev/sg* it remains desirable to use /dev/sr* because /dev/sg is deprecated by the kernel developers, the translation from /dev/sr to /dev/sg is not guaranteed to work in future, and /dev/sr* is better coordinated with mount(8) and open(2) for read(2).

If you are able to compile an own Linux kernel, then the remedy is quite simple. In the source code of kernel 4.19 i edited drivers/scsi/sr.c, included <scsi/sg.h> which defines SG_IO, and skipped the mutex calls in function sr_block_ioctl() in case of SG_IO:

...
#include <scsi/sg.h>            /* For number value of ioctl cmd SG_IO */
...
static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
                          unsigned long arg)
{

       ...
       if (cmd != SG_IO)
               mutex_lock(&sr_mutex);
       ...
       if (cmd != SG_IO)
               mutex_unlock(&sr_mutex);
       ...
}

Staying with /dev/sr* as bad as it is

Without such a kernel change, long lasting SCSI transactions via /dev/sr* cause long delays of communication with the other drives. Some of these delays cannot be avoided. E.g. the SCSI command to eject the tray needs several seconds to be completed.

Another long delay can be circumvented, though:

If the buffer of a drive is nearly full and a WRITE command arrives, then the drive may delay the reply until there is room in the buffer for the next WRITE command. Depending on the firmware and buffer size, this may last quite some time. Further the time granularity of lock waiting seems quite coarse.

These long waiting WRITE commands can be avoided if libburn keeps itself from filling the drive buffer to a level where the firmware would begin to delay the reply.

xorriso command -modesty_on_drive, cdrskin option modesty_on_drive=, and libburn call burn_drive_set_buffer_waiting() apply a strategy which stems from the days of IDE when the slow CD drive clogged the IDE controller which it shared with a HDD.

Example:

  -modesty_on_drive on:min_percent=90:max_percent=95

Some drive firmwares work well with partly empty buffer, some don't.

Regrettably there is no similar remedy known for reading from /dev/sr* via ioctl(SG_IO).

Parameter considerations

Those drives which can work well with -modesty_on_drive still may need adjustment of the modesty parameters.

The threshold for delaying further WRITE commands is controlled by parameter max_percent. The threshold for resuming to send WRITE commands is min_percent.

So if min_percent=90:max_percent=95 does not show the desired effect of reaching about 80 to 90 percent of the throughput of an undisturbed burn run of a single burner, then one has to try variations. Keep in mind that min_percent has to stay lower than max_percent.

Drives have been observed to report their buffer fill too low. This risks to send a long blocking WRITE command by mistake. A lower max_percent percent value may compensate.

  -modesty_on_drive on:min_percent=75:max_percent=80

Drives have been observed to become even slower by waiting for more input before writing if their buffer is not full enough. A higher min_percent may help.

  -modesty_on_drive on:min_percent=95:max_percent=97

Drives have been observed to slow down their write speed if the input comes in small amounts with some short waiting time inbetween. A larger gap between min_percent and max_percent may help to get larger write amounts without intermediate waiting.

  -modesty_on_drive on:min_percent=75:max_percent=95

Finally there are drives which perform poorly with stream recording if their buffer is not completely full. This means that they will not be able to burn DVD-RAM, BD-RE, or formatted BD-R at full nominal speed if -modesty_on_drive is set to on.