diff --git a/iscsi-scst/kernel/iscsi.h b/iscsi-scst/kernel/iscsi.h index 6c7f0a926..1e95f1410 100644 --- a/iscsi-scst/kernel/iscsi.h +++ b/iscsi-scst/kernel/iscsi.h @@ -404,9 +404,16 @@ struct iscsi_cmnd { */ unsigned int data_out_in_data_receiving:1; unsigned int force_release_done:1; + #ifdef CONFIG_SCST_EXTRACHECKS - unsigned int on_rx_digest_list:1; unsigned int release_called:1; + + /* + * This flag might be cleared from SCST thread after/during RX digest + * calculation in parallel with clearing release_called from the + * read thread, so it must be modifiable inependently. + */ + unsigned long on_rx_digest_list:1 __aligned(sizeof(long)); #endif /* diff --git a/scst/src/dev_handlers/scst_vdisk.c b/scst/src/dev_handlers/scst_vdisk.c index fcd8cecf4..fed13e041 100644 --- a/scst/src/dev_handlers/scst_vdisk.c +++ b/scst/src/dev_handlers/scst_vdisk.c @@ -1844,8 +1844,7 @@ static int vdisk_open_fd(struct scst_vdisk_dev *virt_dev, bool read_only) virt_dev->fd = NULL; goto out; } - virt_dev->bdev = virt_dev->blockio ? file_inode(virt_dev->fd)->i_bdev : - NULL; + virt_dev->bdev = virt_dev->blockio ? file_inode(virt_dev->fd)->i_bdev : NULL; res = 0; if (virt_dev->dif_filename != NULL) { @@ -1858,6 +1857,9 @@ static int vdisk_open_fd(struct scst_vdisk_dev *virt_dev, bool read_only) } } + TRACE_DBG("virt_dev %s: fd %p open (dif_fd %p)", virt_dev->name, + virt_dev->fd, virt_dev->dif_fd); + out: return res; @@ -1869,6 +1871,9 @@ out_close_fd: static void vdisk_close_fd(struct scst_vdisk_dev *virt_dev) { + TRACE_DBG("virt_dev %s: closing fd %p (dif_fd %p)", virt_dev->name, + virt_dev->fd, virt_dev->dif_fd); + if (virt_dev->fd) { filp_close(virt_dev->fd, NULL); virt_dev->fd = NULL; @@ -8695,12 +8700,25 @@ static int vcdrom_change(struct scst_vdisk_dev *virt_dev, char *old_fn, *p, *pp; bool old_empty; struct file *old_fd; + struct file *old_dif_fd; const char *filename = NULL; int length = strlen(buffer); int res = 0; TRACE_ENTRY(); + TRACE_DBG("virt_dev %s, empty %d, fd %p (dif_fd %p), filename %p", virt_dev->name, + virt_dev->cdrom_empty, virt_dev->fd, virt_dev->dif_fd, virt_dev->filename); + + sBUG_ON(virt_dev->dif_fd); /* DIF is not supported for CDROMs */ + + if (virt_dev->prevent_allow_medium_removal) { + PRINT_ERROR("Prevent medium removal for " + "virtual device with name %s", virt_dev->name); + res = -EBUSY; + goto out; + } + p = buffer; while (isspace(*p) && *p != '\0') @@ -8723,6 +8741,8 @@ static int vcdrom_change(struct scst_vdisk_dev *virt_dev, old_empty = virt_dev->cdrom_empty; old_fd = virt_dev->fd; + old_dif_fd = virt_dev->dif_fd; + old_fn = virt_dev->filename; if (*filename == '\0') { virt_dev->cdrom_empty = 1; @@ -8734,8 +8754,6 @@ static int vcdrom_change(struct scst_vdisk_dev *virt_dev, } else virt_dev->cdrom_empty = 0; - old_fn = virt_dev->filename; - if (!virt_dev->cdrom_empty) { char *fn = kstrdup(filename, GFP_KERNEL); @@ -8755,6 +8773,14 @@ static int vcdrom_change(struct scst_vdisk_dev *virt_dev, if (res != 0) goto out_free_fn; sBUG_ON(!virt_dev->fd); + + TRACE_DBG("Closing old_fd %p", old_fd); + if (old_fd != NULL) + filp_close(old_fd, NULL); + if (old_dif_fd != NULL) + filp_close(old_dif_fd, NULL); + old_fd = NULL; + old_dif_fd = NULL; } } else { err = 0; @@ -8762,13 +8788,6 @@ static int vcdrom_change(struct scst_vdisk_dev *virt_dev, virt_dev->fd = NULL; } - if (virt_dev->prevent_allow_medium_removal) { - PRINT_ERROR("Prevent medium removal for " - "virtual device with name %s", virt_dev->name); - res = -EBUSY; - goto out_free_fn; - } - virt_dev->file_size = err; virt_dev->nblocks = virt_dev->file_size >> virt_dev->dev->block_shift; if (!virt_dev->cdrom_empty) @@ -8791,14 +8810,15 @@ static int vcdrom_change(struct scst_vdisk_dev *virt_dev, virt_dev->name); } - if (old_fd) - filp_close(old_fd, NULL); kfree(old_fn); out_resume: scst_resume_activity(); out: + TRACE_DBG("virt_dev %s, empty %d, fd %p (dif_fd %p), filename %p", virt_dev->name, + virt_dev->cdrom_empty, virt_dev->fd, virt_dev->dif_fd, virt_dev->filename); + TRACE_EXIT_RES(res); return res;