numam-spdk/lib/scsi
Shuhei Matsumoto 7a9ecf8284 lib/scsi: Free bdev_io just after getting completion from bdev for non-read I/O
Previously, for iSCSI target, freeing bdev_io of SCSI task was deferred
until the reference count of the SCSI task becomes zero.

But this will cause the use-after-free issue when doing LUN hotplug during
large write I/O workload.

The scenario is the following:

- Large iSCSI write I/O is split into multiple I/Os, the first I/O is from immediate,
  and subsetquent I/Os are from R2T.

1. The first I/O allocates iSCSI task as primary, and is submitted to  the bdev layer.
   The first I/O is pending in the bdev layer.
2. The second I/O allocates iSCSI task as secondary (secondary is associated with
   primary by incrementing reference count).
3. Before submitting the second I/O to the bdev layer, LUN hotplug is started.
   LUN hotplug waits for getting completion of the first write I/O from the bdev layer.
4. The bdev layer completes the first I/O. The primary iSCSI task is tried to free,
   but reference count is still one, and is not done yet.
5. LUN hotplug detects completion of the first write I/O, and returns
   LUN I/O channel to the bdev layer.
6. The second I/O is tried to submit to the bdev layer, but LUN is already removed,
   and so free the secondary iSCSI task.
7. Then the reference count of the primary iSCSI task becomes zero,
   and its bdev_io is freed. However, LUN I/O channel is already freed and freeing
   bdev_io fails.

This issue is caused by separating iSCSI task allocation and submission.

For write I/O, we don't have to keep bdev_io after getting completion
of it from the bdev layer.

This applies to other non-read I/O types.

So for non-read I/O, free bdev_io after getting SCSI status in
bdev_scsi_task_complete_cmd(), and for read I/O, set bdev_io to
task as same as before.

The next patch will do the same for management task.

Signed-off-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Change-Id: I530fb491514880ce41858e1bea55d422d606dfc4
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/471695
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Community-CI: Broadcom SPDK FC-NVMe CI <spdk-ci.pdl@broadcom.com>
2019-10-22 17:20:51 +00:00
..
dev.c lib/scsi: Check pending tasks for the SCSI device only from the specific initiator 2019-10-18 17:30:13 +00:00
lun.c lib/scsi: Check pending tasks for the LUN only from the specific initiator 2019-10-18 17:30:13 +00:00
Makefile scsi: add persistent reservation out with register feature support 2019-05-24 23:04:03 +00:00
port.c scsi: add iSCSI initiator port TransportID 2018-12-05 16:04:06 +00:00
scsi_bdev.c lib/scsi: Free bdev_io just after getting completion from bdev for non-read I/O 2019-10-22 17:20:51 +00:00
scsi_internal.h lib/scsi: Check pending tasks for the LUN only from the specific initiator 2019-10-18 17:30:13 +00:00
scsi_pr.c scsi: fix error break when checking SCSI reservation 2019-07-04 08:15:44 +00:00
scsi_rpc.c rpc: Rename get_scsi_devices to scsi_get_devices 2019-10-03 23:01:27 +00:00
scsi.c trace: remove short_name 2019-05-02 08:41:56 +00:00
task.c scsi: alloc temporary data buffer with regular calloc 2019-05-01 17:59:34 +00:00