Make copy manager update internal data on INQUIRY changing vdisk events

git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@6885 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Vladislav Bolkhovitin
2016-05-05 01:53:17 +00:00
parent 5ba4e1a707
commit fcb8b3c75e
5 changed files with 144 additions and 2 deletions

View File

@@ -5430,6 +5430,8 @@ void scst_reassign_retained_sess_states(struct scst_session *new_sess,
int scst_get_max_lun_commands(struct scst_session *sess, uint64_t lun);
void scst_dev_inquiry_data_changed(struct scst_device *dev);
/*
* Has to be put here open coded, because Linux doesn't have equivalent, which
* allows exclusive wake ups of threads in LIFO order. We need it to let (yet)

View File

@@ -244,6 +244,8 @@ struct scst_vdisk_dev {
char *dif_filename;
struct work_struct vdev_inq_changed_work;
/* Only to pass it to attach() callback. Don't use them anywhere else! */
int blk_shift;
enum scst_dif_mode dif_mode;
@@ -663,7 +665,10 @@ static const struct attribute *vcdrom_attrs[] = {
#endif /* CONFIG_SCST_PROC */
/* Protects vdisks addition/deletion and related activities, like search */
/*
* Protects vdisks addition/deletion and related activities, like search.
* Outer mutex regarding scst_mutex.
*/
static DEFINE_MUTEX(scst_vdisk_mutex);
/*
@@ -7670,6 +7675,23 @@ static void vdisk_free_bioset(struct scst_vdisk_dev *virt_dev)
}
#endif
static void vdev_inq_changed_fn(struct work_struct *work)
{
struct scst_vdisk_dev *virt_dev = container_of(work,
struct scst_vdisk_dev, vdev_inq_changed_work);
struct scst_device *dev = virt_dev->dev;
TRACE_ENTRY();
TRACE_DBG("Updating INQUIRY data for virt_dev %p (dev %s)",
virt_dev, dev->virt_name);
scst_dev_inquiry_data_changed(dev);
TRACE_EXIT();
return;
}
/* scst_vdisk_mutex supposed to be held */
static int vdev_create(struct scst_dev_type *devt,
const char *name, struct scst_vdisk_dev **res_virt_dev)
@@ -7703,6 +7725,7 @@ static int vdev_create(struct scst_dev_type *devt,
virt_dev->thin_provisioned = DEF_THIN_PROVISIONED;
virt_dev->tst = DEF_TST;
virt_dev->expl_alua = DEF_EXPL_ALUA;
INIT_WORK(&virt_dev->vdev_inq_changed_work, vdev_inq_changed_fn);
virt_dev->blk_shift = DEF_DISK_BLOCK_SHIFT;
@@ -7764,6 +7787,8 @@ out_free:
static void vdev_destroy(struct scst_vdisk_dev *virt_dev)
{
cancel_work_sync(&virt_dev->vdev_inq_changed_work);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
vdisk_free_bioset(virt_dev);
#endif
@@ -9303,6 +9328,8 @@ static ssize_t vdev_sysfs_t10_vend_id_store(struct kobject *kobj,
virt_dev->t10_vend_id_set = 1;
write_unlock(&vdisk_serial_rwlock);
schedule_work(&virt_dev->vdev_inq_changed_work);
res = count;
out:
@@ -9362,6 +9389,8 @@ static ssize_t vdev_sysfs_vend_specific_id_store(struct kobject *kobj,
virt_dev->vend_specific_id_set = 1;
write_unlock(&vdisk_serial_rwlock);
schedule_work(&virt_dev->vdev_inq_changed_work);
res = count;
out:
@@ -9420,6 +9449,8 @@ static ssize_t vdev_sysfs_prod_id_store(struct kobject *kobj,
virt_dev->prod_id_set = 1;
write_unlock(&vdisk_serial_rwlock);
schedule_work(&virt_dev->vdev_inq_changed_work);
res = count;
out:
@@ -9478,6 +9509,8 @@ static ssize_t vdev_sysfs_prod_rev_lvl_store(struct kobject *kobj,
virt_dev->prod_rev_lvl_set = 1;
write_unlock(&vdisk_serial_rwlock);
schedule_work(&virt_dev->vdev_inq_changed_work);
res = count;
out:
@@ -9539,6 +9572,8 @@ static ssize_t vdev_sysfs_scsi_device_name_store(struct kobject *kobj,
virt_dev->scsi_device_name_set = 0;
write_unlock(&vdisk_serial_rwlock);
schedule_work(&virt_dev->vdev_inq_changed_work);
res = count;
out:
@@ -9609,6 +9644,8 @@ static ssize_t vdev_sysfs_t10_dev_id_store(struct kobject *kobj,
virt_dev->t10_dev_id_set = 1;
schedule_work(&virt_dev->vdev_inq_changed_work);
res = count;
PRINT_INFO("T10 device id for device %s changed to %s", virt_dev->name,
@@ -9691,6 +9728,9 @@ static ssize_t vdev_sysfs_eui64_id_store(struct kobject *kobj,
#endif
write_unlock(&vdisk_serial_rwlock);
if (res >= 0)
schedule_work(&virt_dev->vdev_inq_changed_work);
out:
return res;
}
@@ -9772,6 +9812,9 @@ static ssize_t vdev_sysfs_naa_id_store(struct kobject *kobj,
#endif
write_unlock(&vdisk_serial_rwlock);
if (res >= 0)
schedule_work(&virt_dev->vdev_inq_changed_work);
out:
return res;
}
@@ -9835,6 +9878,8 @@ static ssize_t vdev_sysfs_usn_store(struct kobject *kobj,
virt_dev->usn_set = 1;
schedule_work(&virt_dev->vdev_inq_changed_work);
res = count;
PRINT_INFO("USN for device %s changed to %s", virt_dev->name,
@@ -9889,6 +9934,8 @@ static ssize_t vdev_sysfs_inq_vend_specific_store(struct kobject *kobj,
virt_dev->inq_vend_specific_len = len;
write_unlock(&vdisk_serial_rwlock);
schedule_work(&virt_dev->vdev_inq_changed_work);
res = count;
out:

View File

@@ -2518,6 +2518,36 @@ static bool scst_cm_is_lun_free(unsigned int lun)
return res;
}
/* scst_mutex supposed to be held and activities suspended */
static unsigned int scst_cm_get_lun(const struct scst_device *dev)
{
unsigned int res = -1;
int i;
bool found = false;
TRACE_ENTRY();
for (i = 0; i < SESS_TGT_DEV_LIST_HASH_SIZE; i++) {
struct list_head *head = &scst_cm_sess->sess_tgt_dev_list[i];
struct scst_tgt_dev *tgt_dev;
list_for_each_entry(tgt_dev, head, sess_tgt_dev_list_entry) {
if (tgt_dev->dev == dev) {
res = tgt_dev->lun;
found = true;
TRACE_DBG("LUN %d found (full LUN %lld)",
res, tgt_dev->lun);
goto out;
}
}
}
sBUG_ON(!found);
out:
TRACE_EXIT_RES(res);
return res;
}
/* scst_mutex supposed to be held and activities suspended */
static int scst_cm_dev_register(struct scst_device *dev, uint64_t lun)
{
@@ -2583,6 +2613,7 @@ out_unblock:
spin_lock_bh(&dev->dev_lock);
scst_unblock_dev(dev);
spin_unlock_bh(&dev->dev_lock);
scst_acg_del_lun(scst_cm_tgt->default_acg, lun, false);
out_err:
@@ -2629,6 +2660,41 @@ out:
return;
}
void scst_cm_update_dev(struct scst_device *dev)
{
int rc;
TRACE_ENTRY();
TRACE_MGMT_DBG("copy manager: updating device %s", dev->virt_name);
scst_suspend_activity(SCST_SUSPEND_TIMEOUT_UNLIMITED);
mutex_lock(&scst_mutex);
scst_cm_dev_unregister(dev, false);
spin_lock_bh(&dev->dev_lock);
scst_block_dev(dev);
spin_unlock_bh(&dev->dev_lock);
rc = scst_cm_send_init_inquiry(dev, scst_cm_get_lun(dev), NULL);
if (rc != 0)
goto out_unblock;
out_resume:
mutex_unlock(&scst_mutex);
scst_resume_activity();
TRACE_EXIT();
return;
out_unblock:
spin_lock_bh(&dev->dev_lock);
scst_unblock_dev(dev);
spin_unlock_bh(&dev->dev_lock);
goto out_resume;
}
/* scst_mutex supposed to be held and activities suspended */
int scst_cm_on_dev_register(struct scst_device *dev)
{
@@ -3650,7 +3716,8 @@ static void scst_cm_task_mgmt_fn_done(struct scst_mgmt_cmd *scst_mcmd)
static int scst_cm_report_aen(struct scst_aen *aen)
{
/* Nothing to do */
return 0;
scst_aen_done(aen);
return SCST_AEN_RES_SUCCESS;
}
static struct scst_tgt_template scst_cm_tgtt = {

View File

@@ -2855,6 +2855,30 @@ void scst_requeue_ua(struct scst_cmd *cmd, const uint8_t *buf, int size)
return;
}
void scst_dev_inquiry_data_changed(struct scst_device *dev)
{
struct scst_tgt_dev *tgt_dev;
TRACE_ENTRY();
TRACE_MGMT_DBG("Updating INQUIRY data for dev %s", dev->virt_name);
mutex_lock(&scst_mutex);
list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list, dev_tgt_dev_list_entry) {
TRACE_DBG("INQUIRY DATA HAS CHANGED on tgt_dev %p", tgt_dev);
scst_gen_aen_or_ua(tgt_dev, SCST_LOAD_SENSE(scst_sense_inquiry_data_changed));
}
mutex_unlock(&scst_mutex);
scst_cm_update_dev(dev);
TRACE_EXIT();
return;
}
EXPORT_SYMBOL(scst_dev_inquiry_data_changed);
/* The activity supposed to be suspended and scst_mutex held */
static void scst_check_reassign_sess(struct scst_session *sess)
{

View File

@@ -862,6 +862,7 @@ static inline bool scst_lba1_inside_lba2(int64_t lba1,
#ifndef CONFIG_SCST_PROC
void scst_cm_update_dev(struct scst_device *dev);
int scst_cm_on_dev_register(struct scst_device *dev);
void scst_cm_on_dev_unregister(struct scst_device *dev);
@@ -895,6 +896,7 @@ void scst_cm_exit(void);
#else /* #ifndef CONFIG_SCST_PROC */
static inline void scst_cm_update_dev(struct scst_device *dev) {}
static inline int scst_cm_on_dev_register(struct scst_device *dev) { return 0; }
static inline void scst_cm_on_dev_unregister(struct scst_device *dev) {}