mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-19 19:51:27 +00:00
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:
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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) {}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user