Commit 4cc987ea authored by Nicholas Bellinger's avatar Nicholas Bellinger

target: Drop lun_sep_lock for se_lun->lun_se_dev RCU usage

With se_port and t10_alua_tg_pt_gp_member being absored into se_lun,
there is no need for an extra lock to protect se_lun->lun_se_dev
assignment.

This patch also converts backend drivers to use call_rcu() release
to allow any se_device readers to complete.  The call_rcu() instead
of kfree_rcu() is required here because se_device is embedded into
the backend driver specific structure.

Also, convert se_lun->lun_stats to use atomic_long_t within the
target_complete_ok_work() completion callback, and add FIXME for
transport_lookup_tmr_lun() with se_lun->lun_ref.

Finally, update sbp_update_unit_directory() special case usage with
proper rcu_dereference_raw() and configfs symlink comment.
Reported-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarHannes Reinecke <hare@suse.de>
Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: Chris Boot <bootc@bootc.net>
Signed-off-by: default avatarNicholas Bellinger <nab@linux-iscsi.org>
parent adf653f9
...@@ -1905,8 +1905,11 @@ static int sbp_update_unit_directory(struct sbp_tport *tport) ...@@ -1905,8 +1905,11 @@ static int sbp_update_unit_directory(struct sbp_tport *tport)
hlist_for_each_entry_rcu(lun, &tport->tpg->se_tpg.tpg_lun_hlist, link) { hlist_for_each_entry_rcu(lun, &tport->tpg->se_tpg.tpg_lun_hlist, link) {
struct se_device *dev; struct se_device *dev;
int type; int type;
/*
dev = lun->lun_se_dev; * rcu_dereference_raw protected by se_lun->lun_group symlink
* reference to se_device->dev_group.
*/
dev = rcu_dereference_raw(lun->lun_se_dev);
type = dev->transport->get_device_type(dev); type = dev->transport->get_device_type(dev);
/* logical_unit_number */ /* logical_unit_number */
......
...@@ -1935,7 +1935,11 @@ ssize_t core_alua_store_tg_pt_gp_info( ...@@ -1935,7 +1935,11 @@ ssize_t core_alua_store_tg_pt_gp_info(
size_t count) size_t count)
{ {
struct se_portal_group *tpg = lun->lun_tpg; struct se_portal_group *tpg = lun->lun_tpg;
struct se_device *dev = lun->lun_se_dev; /*
* rcu_dereference_raw protected by se_lun->lun_group symlink
* reference to se_device->dev_group.
*/
struct se_device *dev = rcu_dereference_raw(lun->lun_se_dev);
struct t10_alua_tg_pt_gp *tg_pt_gp = NULL, *tg_pt_gp_new = NULL; struct t10_alua_tg_pt_gp *tg_pt_gp = NULL, *tg_pt_gp_new = NULL;
unsigned char buf[TG_PT_GROUP_NAME_BUF]; unsigned char buf[TG_PT_GROUP_NAME_BUF];
int move = 0; int move = 0;
...@@ -2189,7 +2193,11 @@ ssize_t core_alua_store_offline_bit( ...@@ -2189,7 +2193,11 @@ ssize_t core_alua_store_offline_bit(
const char *page, const char *page,
size_t count) size_t count)
{ {
struct se_device *dev = lun->lun_se_dev; /*
* rcu_dereference_raw protected by se_lun->lun_group symlink
* reference to se_device->dev_group.
*/
struct se_device *dev = rcu_dereference_raw(lun->lun_se_dev);
unsigned long tmp; unsigned long tmp;
int ret; int ret;
......
...@@ -61,7 +61,6 @@ transport_lookup_cmd_lun(struct se_cmd *se_cmd, u32 unpacked_lun) ...@@ -61,7 +61,6 @@ transport_lookup_cmd_lun(struct se_cmd *se_cmd, u32 unpacked_lun)
struct se_lun *se_lun = NULL; struct se_lun *se_lun = NULL;
struct se_session *se_sess = se_cmd->se_sess; struct se_session *se_sess = se_cmd->se_sess;
struct se_node_acl *nacl = se_sess->se_node_acl; struct se_node_acl *nacl = se_sess->se_node_acl;
struct se_device *dev;
struct se_dev_entry *deve; struct se_dev_entry *deve;
if (unpacked_lun >= TRANSPORT_MAX_LUNS_PER_TPG) if (unpacked_lun >= TRANSPORT_MAX_LUNS_PER_TPG)
...@@ -128,16 +127,21 @@ transport_lookup_cmd_lun(struct se_cmd *se_cmd, u32 unpacked_lun) ...@@ -128,16 +127,21 @@ transport_lookup_cmd_lun(struct se_cmd *se_cmd, u32 unpacked_lun)
percpu_ref_get(&se_lun->lun_ref); percpu_ref_get(&se_lun->lun_ref);
se_cmd->lun_ref_active = true; se_cmd->lun_ref_active = true;
} }
/*
* RCU reference protected by percpu se_lun->lun_ref taken above that
* must drop to zero (including initial reference) before this se_lun
* pointer can be kfree_rcu() by the final se_lun->lun_group put via
* target_core_fabric_configfs.c:target_fabric_port_release
*/
se_cmd->se_dev = rcu_dereference_raw(se_lun->lun_se_dev);
atomic_long_inc(&se_cmd->se_dev->num_cmds);
/* Directly associate cmd with se_dev */
se_cmd->se_dev = se_lun->lun_se_dev;
dev = se_lun->lun_se_dev;
atomic_long_inc(&dev->num_cmds);
if (se_cmd->data_direction == DMA_TO_DEVICE) if (se_cmd->data_direction == DMA_TO_DEVICE)
atomic_long_add(se_cmd->data_length, &dev->write_bytes); atomic_long_add(se_cmd->data_length,
&se_cmd->se_dev->write_bytes);
else if (se_cmd->data_direction == DMA_FROM_DEVICE) else if (se_cmd->data_direction == DMA_FROM_DEVICE)
atomic_long_add(se_cmd->data_length, &dev->read_bytes); atomic_long_add(se_cmd->data_length,
&se_cmd->se_dev->read_bytes);
return 0; return 0;
} }
...@@ -173,10 +177,11 @@ int transport_lookup_tmr_lun(struct se_cmd *se_cmd, u32 unpacked_lun) ...@@ -173,10 +177,11 @@ int transport_lookup_tmr_lun(struct se_cmd *se_cmd, u32 unpacked_lun)
unpacked_lun); unpacked_lun);
return -ENODEV; return -ENODEV;
} }
/*
/* Directly associate cmd with se_dev */ * XXX: Add percpu se_lun->lun_ref reference count for TMR
se_cmd->se_dev = se_lun->lun_se_dev; */
se_tmr->tmr_dev = se_lun->lun_se_dev; se_cmd->se_dev = rcu_dereference_raw(se_lun->lun_se_dev);
se_tmr->tmr_dev = rcu_dereference_raw(se_lun->lun_se_dev);
spin_lock_irqsave(&se_tmr->tmr_dev->se_tmr_lock, flags); spin_lock_irqsave(&se_tmr->tmr_dev->se_tmr_lock, flags);
list_add_tail(&se_tmr->tmr_list, &se_tmr->tmr_dev->dev_tmr_list); list_add_tail(&se_tmr->tmr_list, &se_tmr->tmr_dev->dev_tmr_list);
...@@ -389,6 +394,11 @@ void core_disable_device_list_for_node( ...@@ -389,6 +394,11 @@ void core_disable_device_list_for_node(
struct se_node_acl *nacl, struct se_node_acl *nacl,
struct se_portal_group *tpg) struct se_portal_group *tpg)
{ {
/*
* rcu_dereference_raw protected by se_lun->lun_group symlink
* reference to se_device->dev_group.
*/
struct se_device *dev = rcu_dereference_raw(lun->lun_se_dev);
/* /*
* If the MappedLUN entry is being disabled, the entry in * If the MappedLUN entry is being disabled, the entry in
* lun->lun_deve_list must be removed now before clearing the * lun->lun_deve_list must be removed now before clearing the
...@@ -426,7 +436,7 @@ void core_disable_device_list_for_node( ...@@ -426,7 +436,7 @@ void core_disable_device_list_for_node(
kfree_rcu(orig, rcu_head); kfree_rcu(orig, rcu_head);
core_scsi3_free_pr_reg_from_nacl(lun->lun_se_dev, nacl); core_scsi3_free_pr_reg_from_nacl(dev, nacl);
} }
/* core_clear_lun_from_tpg(): /* core_clear_lun_from_tpg():
...@@ -629,6 +639,11 @@ int core_dev_add_initiator_node_lun_acl( ...@@ -629,6 +639,11 @@ int core_dev_add_initiator_node_lun_acl(
u32 lun_access) u32 lun_access)
{ {
struct se_node_acl *nacl = lacl->se_lun_nacl; struct se_node_acl *nacl = lacl->se_lun_nacl;
/*
* rcu_dereference_raw protected by se_lun->lun_group symlink
* reference to se_device->dev_group.
*/
struct se_device *dev = rcu_dereference_raw(lun->lun_se_dev);
if (!nacl) if (!nacl)
return -EINVAL; return -EINVAL;
...@@ -652,7 +667,7 @@ int core_dev_add_initiator_node_lun_acl( ...@@ -652,7 +667,7 @@ int core_dev_add_initiator_node_lun_acl(
* Check to see if there are any existing persistent reservation APTPL * Check to see if there are any existing persistent reservation APTPL
* pre-registrations that need to be enabled for this LUN ACL.. * pre-registrations that need to be enabled for this LUN ACL..
*/ */
core_scsi3_check_aptpl_registration(lun->lun_se_dev, tpg, lun, nacl, core_scsi3_check_aptpl_registration(dev, tpg, lun, nacl,
lacl->mapped_lun); lacl->mapped_lun);
return 0; return 0;
} }
...@@ -746,6 +761,7 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name) ...@@ -746,6 +761,7 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name)
dev->se_hba = hba; dev->se_hba = hba;
dev->transport = hba->backend->ops; dev->transport = hba->backend->ops;
dev->prot_length = sizeof(struct se_dif_v1_tuple); dev->prot_length = sizeof(struct se_dif_v1_tuple);
dev->hba_index = hba->hba_index;
INIT_LIST_HEAD(&dev->dev_list); INIT_LIST_HEAD(&dev->dev_list);
INIT_LIST_HEAD(&dev->dev_sep_list); INIT_LIST_HEAD(&dev->dev_sep_list);
...@@ -802,8 +818,7 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name) ...@@ -802,8 +818,7 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name)
dev->dev_attrib.max_write_same_len = DA_MAX_WRITE_SAME_LEN; dev->dev_attrib.max_write_same_len = DA_MAX_WRITE_SAME_LEN;
xcopy_lun = &dev->xcopy_lun; xcopy_lun = &dev->xcopy_lun;
xcopy_lun->lun_se_dev = dev; rcu_assign_pointer(xcopy_lun->lun_se_dev, dev);
spin_lock_init(&xcopy_lun->lun_sep_lock);
init_completion(&xcopy_lun->lun_ref_comp); init_completion(&xcopy_lun->lun_ref_comp);
INIT_LIST_HEAD(&xcopy_lun->lun_deve_list); INIT_LIST_HEAD(&xcopy_lun->lun_deve_list);
INIT_LIST_HEAD(&xcopy_lun->lun_dev_link); INIT_LIST_HEAD(&xcopy_lun->lun_dev_link);
......
...@@ -241,6 +241,14 @@ fail: ...@@ -241,6 +241,14 @@ fail:
return ret; return ret;
} }
static void fd_dev_call_rcu(struct rcu_head *p)
{
struct se_device *dev = container_of(p, struct se_device, rcu_head);
struct fd_dev *fd_dev = FD_DEV(dev);
kfree(fd_dev);
}
static void fd_free_device(struct se_device *dev) static void fd_free_device(struct se_device *dev)
{ {
struct fd_dev *fd_dev = FD_DEV(dev); struct fd_dev *fd_dev = FD_DEV(dev);
...@@ -249,8 +257,7 @@ static void fd_free_device(struct se_device *dev) ...@@ -249,8 +257,7 @@ static void fd_free_device(struct se_device *dev)
filp_close(fd_dev->fd_file, NULL); filp_close(fd_dev->fd_file, NULL);
fd_dev->fd_file = NULL; fd_dev->fd_file = NULL;
} }
call_rcu(&dev->rcu_head, fd_dev_call_rcu);
kfree(fd_dev);
} }
static int fd_do_rw(struct se_cmd *cmd, struct file *fd, static int fd_do_rw(struct se_cmd *cmd, struct file *fd,
......
...@@ -191,6 +191,14 @@ out: ...@@ -191,6 +191,14 @@ out:
return ret; return ret;
} }
static void iblock_dev_call_rcu(struct rcu_head *p)
{
struct se_device *dev = container_of(p, struct se_device, rcu_head);
struct iblock_dev *ib_dev = IBLOCK_DEV(dev);
kfree(ib_dev);
}
static void iblock_free_device(struct se_device *dev) static void iblock_free_device(struct se_device *dev)
{ {
struct iblock_dev *ib_dev = IBLOCK_DEV(dev); struct iblock_dev *ib_dev = IBLOCK_DEV(dev);
...@@ -200,7 +208,7 @@ static void iblock_free_device(struct se_device *dev) ...@@ -200,7 +208,7 @@ static void iblock_free_device(struct se_device *dev)
if (ib_dev->ibd_bio_set != NULL) if (ib_dev->ibd_bio_set != NULL)
bioset_free(ib_dev->ibd_bio_set); bioset_free(ib_dev->ibd_bio_set);
kfree(ib_dev); call_rcu(&dev->rcu_head, iblock_dev_call_rcu);
} }
static unsigned long long iblock_emulate_read_cap_with_block_size( static unsigned long long iblock_emulate_read_cap_with_block_size(
......
...@@ -579,6 +579,14 @@ static int pscsi_configure_device(struct se_device *dev) ...@@ -579,6 +579,14 @@ static int pscsi_configure_device(struct se_device *dev)
return -ENODEV; return -ENODEV;
} }
static void pscsi_dev_call_rcu(struct rcu_head *p)
{
struct se_device *dev = container_of(p, struct se_device, rcu_head);
struct pscsi_dev_virt *pdv = PSCSI_DEV(dev);
kfree(pdv);
}
static void pscsi_free_device(struct se_device *dev) static void pscsi_free_device(struct se_device *dev)
{ {
struct pscsi_dev_virt *pdv = PSCSI_DEV(dev); struct pscsi_dev_virt *pdv = PSCSI_DEV(dev);
...@@ -610,8 +618,7 @@ static void pscsi_free_device(struct se_device *dev) ...@@ -610,8 +618,7 @@ static void pscsi_free_device(struct se_device *dev)
pdv->pdv_sd = NULL; pdv->pdv_sd = NULL;
} }
call_rcu(&dev->rcu_head, pscsi_dev_call_rcu);
kfree(pdv);
} }
static void pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg, static void pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg,
......
...@@ -350,12 +350,20 @@ fail: ...@@ -350,12 +350,20 @@ fail:
return ret; return ret;
} }
static void rd_dev_call_rcu(struct rcu_head *p)
{
struct se_device *dev = container_of(p, struct se_device, rcu_head);
struct rd_dev *rd_dev = RD_DEV(dev);
kfree(rd_dev);
}
static void rd_free_device(struct se_device *dev) static void rd_free_device(struct se_device *dev)
{ {
struct rd_dev *rd_dev = RD_DEV(dev); struct rd_dev *rd_dev = RD_DEV(dev);
rd_release_device_space(rd_dev); rd_release_device_space(rd_dev);
kfree(rd_dev); call_rcu(&dev->rcu_head, rd_dev_call_rcu);
} }
static struct rd_dev_sg_table *rd_get_sg_table(struct rd_dev *rd_dev, u32 page) static struct rd_dev_sg_table *rd_get_sg_table(struct rd_dev *rd_dev, u32 page)
......
...@@ -692,7 +692,7 @@ spc_emulate_inquiry(struct se_cmd *cmd) ...@@ -692,7 +692,7 @@ spc_emulate_inquiry(struct se_cmd *cmd)
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
} }
if (dev == tpg->tpg_virt_lun0->lun_se_dev) if (dev == rcu_access_pointer(tpg->tpg_virt_lun0->lun_se_dev))
buf[0] = 0x3f; /* Not connected */ buf[0] = 0x3f; /* Not connected */
else else
buf[0] = dev->transport->get_device_type(dev); buf[0] = dev->transport->get_device_type(dev);
......
...@@ -545,11 +545,11 @@ static ssize_t target_stat_scsi_port_show_attr_inst( ...@@ -545,11 +545,11 @@ static ssize_t target_stat_scsi_port_show_attr_inst(
struct se_device *dev; struct se_device *dev;
ssize_t ret = -ENODEV; ssize_t ret = -ENODEV;
spin_lock(&lun->lun_sep_lock); rcu_read_lock();
dev = lun->lun_se_dev; dev = rcu_dereference(lun->lun_se_dev);
if (dev) if (dev)
ret = snprintf(page, PAGE_SIZE, "%u\n", dev->se_hba->hba_index); ret = snprintf(page, PAGE_SIZE, "%u\n", dev->hba_index);
spin_unlock(&lun->lun_sep_lock); rcu_read_unlock();
return ret; return ret;
} }
DEV_STAT_SCSI_PORT_ATTR_RO(inst); DEV_STAT_SCSI_PORT_ATTR_RO(inst);
...@@ -561,11 +561,11 @@ static ssize_t target_stat_scsi_port_show_attr_dev( ...@@ -561,11 +561,11 @@ static ssize_t target_stat_scsi_port_show_attr_dev(
struct se_device *dev; struct se_device *dev;
ssize_t ret = -ENODEV; ssize_t ret = -ENODEV;
spin_lock(&lun->lun_sep_lock); rcu_read_lock();
dev = lun->lun_se_dev; dev = rcu_dereference(lun->lun_se_dev);
if (dev) if (dev)
ret = snprintf(page, PAGE_SIZE, "%u\n", dev->dev_index); ret = snprintf(page, PAGE_SIZE, "%u\n", dev->dev_index);
spin_unlock(&lun->lun_sep_lock); rcu_read_unlock();
return ret; return ret;
} }
DEV_STAT_SCSI_PORT_ATTR_RO(dev); DEV_STAT_SCSI_PORT_ATTR_RO(dev);
...@@ -577,11 +577,11 @@ static ssize_t target_stat_scsi_port_show_attr_indx( ...@@ -577,11 +577,11 @@ static ssize_t target_stat_scsi_port_show_attr_indx(
struct se_device *dev; struct se_device *dev;
ssize_t ret = -ENODEV; ssize_t ret = -ENODEV;
spin_lock(&lun->lun_sep_lock); rcu_read_lock();
dev = lun->lun_se_dev; dev = rcu_dereference(lun->lun_se_dev);
if (dev) if (dev)
ret = snprintf(page, PAGE_SIZE, "%u\n", lun->lun_rtpi); ret = snprintf(page, PAGE_SIZE, "%u\n", lun->lun_rtpi);
spin_unlock(&lun->lun_sep_lock); rcu_read_unlock();
return ret; return ret;
} }
DEV_STAT_SCSI_PORT_ATTR_RO(indx); DEV_STAT_SCSI_PORT_ATTR_RO(indx);
...@@ -593,11 +593,11 @@ static ssize_t target_stat_scsi_port_show_attr_role( ...@@ -593,11 +593,11 @@ static ssize_t target_stat_scsi_port_show_attr_role(
struct se_device *dev; struct se_device *dev;
ssize_t ret = -ENODEV; ssize_t ret = -ENODEV;
spin_lock(&lun->lun_sep_lock); rcu_read_lock();
dev = lun->lun_se_dev; dev = rcu_dereference(lun->lun_se_dev);
if (dev) if (dev)
ret = snprintf(page, PAGE_SIZE, "%s%u\n", "Device", dev->dev_index); ret = snprintf(page, PAGE_SIZE, "%s%u\n", "Device", dev->dev_index);
spin_unlock(&lun->lun_sep_lock); rcu_read_unlock();
return ret; return ret;
} }
DEV_STAT_SCSI_PORT_ATTR_RO(role); DEV_STAT_SCSI_PORT_ATTR_RO(role);
...@@ -609,13 +609,13 @@ static ssize_t target_stat_scsi_port_show_attr_busy_count( ...@@ -609,13 +609,13 @@ static ssize_t target_stat_scsi_port_show_attr_busy_count(
struct se_device *dev; struct se_device *dev;
ssize_t ret = -ENODEV; ssize_t ret = -ENODEV;
spin_lock(&lun->lun_sep_lock); rcu_read_lock();
dev = lun->lun_se_dev; dev = rcu_dereference(lun->lun_se_dev);
if (dev) { if (dev) {
/* FIXME: scsiPortBusyStatuses */ /* FIXME: scsiPortBusyStatuses */
ret = snprintf(page, PAGE_SIZE, "%u\n", 0); ret = snprintf(page, PAGE_SIZE, "%u\n", 0);
} }
spin_unlock(&lun->lun_sep_lock); rcu_read_unlock();
return ret; return ret;
} }
DEV_STAT_SCSI_PORT_ATTR_RO(busy_count); DEV_STAT_SCSI_PORT_ATTR_RO(busy_count);
...@@ -666,11 +666,11 @@ static ssize_t target_stat_scsi_tgt_port_show_attr_inst( ...@@ -666,11 +666,11 @@ static ssize_t target_stat_scsi_tgt_port_show_attr_inst(
struct se_device *dev; struct se_device *dev;
ssize_t ret = -ENODEV; ssize_t ret = -ENODEV;
spin_lock(&lun->lun_sep_lock); rcu_read_lock();
dev = lun->lun_se_dev; dev = rcu_dereference(lun->lun_se_dev);
if (dev) if (dev)
ret = snprintf(page, PAGE_SIZE, "%u\n", dev->se_hba->hba_index); ret = snprintf(page, PAGE_SIZE, "%u\n", dev->hba_index);
spin_unlock(&lun->lun_sep_lock); rcu_read_unlock();
return ret; return ret;
} }
DEV_STAT_SCSI_TGT_PORT_ATTR_RO(inst); DEV_STAT_SCSI_TGT_PORT_ATTR_RO(inst);
...@@ -682,11 +682,11 @@ static ssize_t target_stat_scsi_tgt_port_show_attr_dev( ...@@ -682,11 +682,11 @@ static ssize_t target_stat_scsi_tgt_port_show_attr_dev(
struct se_device *dev; struct se_device *dev;
ssize_t ret = -ENODEV; ssize_t ret = -ENODEV;
spin_lock(&lun->lun_sep_lock); rcu_read_lock();
dev = lun->lun_se_dev; dev = rcu_dereference(lun->lun_se_dev);
if (dev) if (dev)
ret = snprintf(page, PAGE_SIZE, "%u\n", dev->dev_index); ret = snprintf(page, PAGE_SIZE, "%u\n", dev->dev_index);
spin_unlock(&lun->lun_sep_lock); rcu_read_unlock();
return ret; return ret;
} }
DEV_STAT_SCSI_TGT_PORT_ATTR_RO(dev); DEV_STAT_SCSI_TGT_PORT_ATTR_RO(dev);
...@@ -698,11 +698,11 @@ static ssize_t target_stat_scsi_tgt_port_show_attr_indx( ...@@ -698,11 +698,11 @@ static ssize_t target_stat_scsi_tgt_port_show_attr_indx(
struct se_device *dev; struct se_device *dev;
ssize_t ret = -ENODEV; ssize_t ret = -ENODEV;
spin_lock(&lun->lun_sep_lock); rcu_read_lock();
dev = lun->lun_se_dev; dev = rcu_dereference(lun->lun_se_dev);
if (dev) if (dev)
ret = snprintf(page, PAGE_SIZE, "%u\n", lun->lun_rtpi); ret = snprintf(page, PAGE_SIZE, "%u\n", lun->lun_rtpi);
spin_unlock(&lun->lun_sep_lock); rcu_read_unlock();
return ret; return ret;
} }
DEV_STAT_SCSI_TGT_PORT_ATTR_RO(indx); DEV_STAT_SCSI_TGT_PORT_ATTR_RO(indx);
...@@ -715,13 +715,13 @@ static ssize_t target_stat_scsi_tgt_port_show_attr_name( ...@@ -715,13 +715,13 @@ static ssize_t target_stat_scsi_tgt_port_show_attr_name(
struct se_device *dev; struct se_device *dev;
ssize_t ret = -ENODEV; ssize_t ret = -ENODEV;
spin_lock(&lun->lun_sep_lock); rcu_read_lock();
dev = lun->lun_se_dev; dev = rcu_dereference(lun->lun_se_dev);
if (dev) if (dev)
ret = snprintf(page, PAGE_SIZE, "%sPort#%u\n", ret = snprintf(page, PAGE_SIZE, "%sPort#%u\n",
tpg->se_tpg_tfo->get_fabric_name(), tpg->se_tpg_tfo->get_fabric_name(),
lun->lun_rtpi); lun->lun_rtpi);
spin_unlock(&lun->lun_sep_lock); rcu_read_unlock();
return ret; return ret;
} }
DEV_STAT_SCSI_TGT_PORT_ATTR_RO(name); DEV_STAT_SCSI_TGT_PORT_ATTR_RO(name);
...@@ -734,13 +734,13 @@ static ssize_t target_stat_scsi_tgt_port_show_attr_port_index( ...@@ -734,13 +734,13 @@ static ssize_t target_stat_scsi_tgt_port_show_attr_port_index(
struct se_device *dev; struct se_device *dev;
ssize_t ret = -ENODEV; ssize_t ret = -ENODEV;
spin_lock(&lun->lun_sep_lock); rcu_read_lock();
dev = lun->lun_se_dev; dev = rcu_dereference(lun->lun_se_dev);
if (dev) if (dev)
ret = snprintf(page, PAGE_SIZE, "%s%s%d\n", ret = snprintf(page, PAGE_SIZE, "%s%s%d\n",
tpg->se_tpg_tfo->tpg_get_wwn(tpg), "+t+", tpg->se_tpg_tfo->tpg_get_wwn(tpg), "+t+",
tpg->se_tpg_tfo->tpg_get_tag(tpg)); tpg->se_tpg_tfo->tpg_get_tag(tpg));
spin_unlock(&lun->lun_sep_lock); rcu_read_unlock();
return ret; return ret;
} }
DEV_STAT_SCSI_TGT_PORT_ATTR_RO(port_index); DEV_STAT_SCSI_TGT_PORT_ATTR_RO(port_index);
...@@ -752,11 +752,12 @@ static ssize_t target_stat_scsi_tgt_port_show_attr_in_cmds( ...@@ -752,11 +752,12 @@ static ssize_t target_stat_scsi_tgt_port_show_attr_in_cmds(
struct se_device *dev; struct se_device *dev;
ssize_t ret = -ENODEV; ssize_t ret = -ENODEV;
spin_lock(&lun->lun_sep_lock); rcu_read_lock();
dev = lun->lun_se_dev; dev = rcu_dereference(lun->lun_se_dev);
if (dev) if (dev)
ret = snprintf(page, PAGE_SIZE, "%u\n", lun->lun_stats.cmd_pdus); ret = snprintf(page, PAGE_SIZE, "%lu\n",
spin_unlock(&lun->lun_sep_lock); atomic_long_read(&lun->lun_stats.cmd_pdus));
rcu_read_unlock();
return ret; return ret;
} }
DEV_STAT_SCSI_TGT_PORT_ATTR_RO(in_cmds); DEV_STAT_SCSI_TGT_PORT_ATTR_RO(in_cmds);
...@@ -768,12 +769,12 @@ static ssize_t target_stat_scsi_tgt_port_show_attr_write_mbytes( ...@@ -768,12 +769,12 @@ static ssize_t target_stat_scsi_tgt_port_show_attr_write_mbytes(
struct se_device *dev; struct se_device *dev;
ssize_t ret = -ENODEV; ssize_t ret = -ENODEV;
spin_lock(&lun->lun_sep_lock); rcu_read_lock();
dev = lun->lun_se_dev; dev = rcu_dereference(lun->lun_se_dev);
if (dev) if (dev)
ret = snprintf(page, PAGE_SIZE, "%u\n", ret = snprintf(page, PAGE_SIZE, "%u\n",
(u32)(lun->lun_stats.rx_data_octets >> 20)); (u32)(atomic_long_read(&lun->lun_stats.rx_data_octets) >> 20));
spin_unlock(&lun->lun_sep_lock); rcu_read_unlock();
return ret; return ret;
} }
DEV_STAT_SCSI_TGT_PORT_ATTR_RO(write_mbytes); DEV_STAT_SCSI_TGT_PORT_ATTR_RO(write_mbytes);
...@@ -785,12 +786,12 @@ static ssize_t target_stat_scsi_tgt_port_show_attr_read_mbytes( ...@@ -785,12 +786,12 @@ static ssize_t target_stat_scsi_tgt_port_show_attr_read_mbytes(
struct se_device *dev; struct se_device *dev;
ssize_t ret = -ENODEV; ssize_t ret = -ENODEV;
spin_lock(&lun->lun_sep_lock); rcu_read_lock();
dev = lun->lun_se_dev; dev = rcu_dereference(lun->lun_se_dev);
if (dev) if (dev)
ret = snprintf(page, PAGE_SIZE, "%u\n", ret = snprintf(page, PAGE_SIZE, "%u\n",
(u32)(lun->lun_stats.tx_data_octets >> 20)); (u32)(atomic_long_read(&lun->lun_stats.tx_data_octets) >> 20));
spin_unlock(&lun->lun_sep_lock); rcu_read_unlock();
return ret; return ret;
} }
DEV_STAT_SCSI_TGT_PORT_ATTR_RO(read_mbytes); DEV_STAT_SCSI_TGT_PORT_ATTR_RO(read_mbytes);
...@@ -802,13 +803,13 @@ static ssize_t target_stat_scsi_tgt_port_show_attr_hs_in_cmds( ...@@ -802,13 +803,13 @@ static ssize_t target_stat_scsi_tgt_port_show_attr_hs_in_cmds(
struct se_device *dev; struct se_device *dev;
ssize_t ret = -ENODEV; ssize_t ret = -ENODEV;
spin_lock(&lun->lun_sep_lock); rcu_read_lock();
dev = lun->lun_se_dev; dev = rcu_dereference(lun->lun_se_dev);
if (dev) { if (dev) {
/* FIXME: scsiTgtPortHsInCommands */ /* FIXME: scsiTgtPortHsInCommands */
ret = snprintf(page, PAGE_SIZE, "%u\n", 0); ret = snprintf(page, PAGE_SIZE, "%u\n", 0);
} }
spin_unlock(&lun->lun_sep_lock); rcu_read_unlock();
return ret; return ret;
} }
DEV_STAT_SCSI_TGT_PORT_ATTR_RO(hs_in_cmds); DEV_STAT_SCSI_TGT_PORT_ATTR_RO(hs_in_cmds);
...@@ -865,11 +866,11 @@ static ssize_t target_stat_scsi_transport_show_attr_inst( ...@@ -865,11 +866,11 @@ static ssize_t target_stat_scsi_transport_show_attr_inst(
struct se_device *dev; struct se_device *dev;
ssize_t ret = -ENODEV; ssize_t ret = -ENODEV;
spin_lock(&lun->lun_sep_lock); rcu_read_lock();
dev = lun->lun_se_dev; dev = rcu_dereference(lun->lun_se_dev);
if (dev) if (dev)
ret = snprintf(page, PAGE_SIZE, "%u\n", dev->se_hba->hba_index); ret = snprintf(page, PAGE_SIZE, "%u\n", dev->hba_index);
spin_unlock(&lun->lun_sep_lock); rcu_read_unlock();
return ret; return ret;
} }
DEV_STAT_SCSI_TRANSPORT_ATTR_RO(inst); DEV_STAT_SCSI_TRANSPORT_ATTR_RO(inst);
...@@ -882,14 +883,14 @@ static ssize_t target_stat_scsi_transport_show_attr_device( ...@@ -882,14 +883,14 @@ static ssize_t target_stat_scsi_transport_show_attr_device(
struct se_portal_group *tpg = lun->lun_tpg; struct se_portal_group *tpg = lun->lun_tpg;
ssize_t ret = -ENODEV; ssize_t ret = -ENODEV;
spin_lock(&lun->lun_sep_lock); rcu_read_lock();
dev = lun->lun_se_dev; dev = rcu_dereference(lun->lun_se_dev);
if (dev) { if (dev) {
/* scsiTransportType */ /* scsiTransportType */
ret = snprintf(page, PAGE_SIZE, "scsiTransport%s\n", ret = snprintf(page, PAGE_SIZE, "scsiTransport%s\n",
tpg->se_tpg_tfo->get_fabric_name()); tpg->se_tpg_tfo->get_fabric_name());
} }
spin_unlock(&lun->lun_sep_lock); rcu_read_unlock();
return ret; return ret;
} }
DEV_STAT_SCSI_TRANSPORT_ATTR_RO(device); DEV_STAT_SCSI_TRANSPORT_ATTR_RO(device);
...@@ -902,12 +903,12 @@ static ssize_t target_stat_scsi_transport_show_attr_indx( ...@@ -902,12 +903,12 @@ static ssize_t target_stat_scsi_transport_show_attr_indx(
struct se_portal_group *tpg = lun->lun_tpg; struct se_portal_group *tpg = lun->lun_tpg;
ssize_t ret = -ENODEV; ssize_t ret = -ENODEV;
spin_lock(&lun->lun_sep_lock);