diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-08-15 22:06:26 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-08-15 22:06:26 -0700 |
commit | 72f02ba66bd83b54054da20eae550123de84da6f (patch) | |
tree | 96a8360400e040aa2e38e7352594dbbc485461db /drivers/target/target_core_user.c | |
parent | db06f826ec12bf0701ea7fc0a3c0aa00b84417c8 (diff) | |
parent | 51372570ac3c919b036e760f4ca449e81cf8e995 (diff) | |
download | linux-72f02ba66bd83b54054da20eae550123de84da6f.tar.gz linux-72f02ba66bd83b54054da20eae550123de84da6f.tar.bz2 linux-72f02ba66bd83b54054da20eae550123de84da6f.zip |
Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull SCSI updates from James Bottomley:
"This is mostly updates to the usual drivers: mpt3sas, lpfc, qla2xxx,
hisi_sas, smartpqi, megaraid_sas, arcmsr.
In addition, with the continuing absence of Nic we have target updates
for tcmu and target core (all with reviews and acks).
The biggest observable change is going to be that we're (again) trying
to switch to mulitqueue as the default (a user can still override the
setting on the kernel command line).
Other major core stuff is the removal of the remaining Microchannel
drivers, an update of the internal timers and some reworks of
completion and result handling"
* tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (203 commits)
scsi: core: use blk_mq_run_hw_queues in scsi_kick_queue
scsi: ufs: remove unnecessary query(DM) UPIU trace
scsi: qla2xxx: Fix issue reported by static checker for qla2x00_els_dcmd2_sp_done()
scsi: aacraid: Spelling fix in comment
scsi: mpt3sas: Fix calltrace observed while running IO & reset
scsi: aic94xx: fix an error code in aic94xx_init()
scsi: st: remove redundant pointer STbuffer
scsi: qla2xxx: Update driver version to 10.00.00.08-k
scsi: qla2xxx: Migrate NVME N2N handling into state machine
scsi: qla2xxx: Save frame payload size from ICB
scsi: qla2xxx: Fix stalled relogin
scsi: qla2xxx: Fix race between switch cmd completion and timeout
scsi: qla2xxx: Fix Management Server NPort handle reservation logic
scsi: qla2xxx: Flush mailbox commands on chip reset
scsi: qla2xxx: Fix unintended Logout
scsi: qla2xxx: Fix session state stuck in Get Port DB
scsi: qla2xxx: Fix redundant fc_rport registration
scsi: qla2xxx: Silent erroneous message
scsi: qla2xxx: Prevent sysfs access when chip is down
scsi: qla2xxx: Add longer window for chip reset
...
Diffstat (limited to 'drivers/target/target_core_user.c')
-rw-r--r-- | drivers/target/target_core_user.c | 377 |
1 files changed, 237 insertions, 140 deletions
diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c index d8dc3d22051f..9cd404acdb82 100644 --- a/drivers/target/target_core_user.c +++ b/drivers/target/target_core_user.c @@ -83,14 +83,10 @@ #define DATA_BLOCK_SIZE PAGE_SIZE #define DATA_BLOCK_SHIFT PAGE_SHIFT #define DATA_BLOCK_BITS_DEF (256 * 1024) -#define DATA_SIZE (DATA_BLOCK_BITS * DATA_BLOCK_SIZE) #define TCMU_MBS_TO_BLOCKS(_mbs) (_mbs << (20 - DATA_BLOCK_SHIFT)) #define TCMU_BLOCKS_TO_MBS(_blocks) (_blocks >> (20 - DATA_BLOCK_SHIFT)) -/* The total size of the ring is 8M + 256K * PAGE_SIZE */ -#define TCMU_RING_SIZE (CMDR_SIZE + DATA_SIZE) - /* * Default number of global data blocks(512K * PAGE_SIZE) * when the unmap thread will be started. @@ -98,6 +94,7 @@ #define TCMU_GLOBAL_MAX_BLOCKS_DEF (512 * 1024) static u8 tcmu_kern_cmd_reply_supported; +static u8 tcmu_netlink_blocked; static struct device *tcmu_root_device; @@ -107,9 +104,16 @@ struct tcmu_hba { #define TCMU_CONFIG_LEN 256 +static DEFINE_MUTEX(tcmu_nl_cmd_mutex); +static LIST_HEAD(tcmu_nl_cmd_list); + +struct tcmu_dev; + struct tcmu_nl_cmd { /* wake up thread waiting for reply */ struct completion complete; + struct list_head nl_list; + struct tcmu_dev *udev; int cmd; int status; }; @@ -133,7 +137,7 @@ struct tcmu_dev { struct inode *inode; struct tcmu_mailbox *mb_addr; - size_t dev_size; + uint64_t dev_size; u32 cmdr_size; u32 cmdr_last_cleaned; /* Offset of data area from start of mb */ @@ -161,10 +165,7 @@ struct tcmu_dev { struct list_head timedout_entry; - spinlock_t nl_cmd_lock; struct tcmu_nl_cmd curr_nl_cmd; - /* wake up threads waiting on curr_nl_cmd */ - wait_queue_head_t nl_cmd_wq; char dev_config[TCMU_CONFIG_LEN]; @@ -255,6 +256,92 @@ MODULE_PARM_DESC(global_max_data_area_mb, "Max MBs allowed to be allocated to all the tcmu device's " "data areas."); +static int tcmu_get_block_netlink(char *buffer, + const struct kernel_param *kp) +{ + return sprintf(buffer, "%s\n", tcmu_netlink_blocked ? + "blocked" : "unblocked"); +} + +static int tcmu_set_block_netlink(const char *str, + const struct kernel_param *kp) +{ + int ret; + u8 val; + + ret = kstrtou8(str, 0, &val); + if (ret < 0) + return ret; + + if (val > 1) { + pr_err("Invalid block netlink value %u\n", val); + return -EINVAL; + } + + tcmu_netlink_blocked = val; + return 0; +} + +static const struct kernel_param_ops tcmu_block_netlink_op = { + .set = tcmu_set_block_netlink, + .get = tcmu_get_block_netlink, +}; + +module_param_cb(block_netlink, &tcmu_block_netlink_op, NULL, S_IWUSR | S_IRUGO); +MODULE_PARM_DESC(block_netlink, "Block new netlink commands."); + +static int tcmu_fail_netlink_cmd(struct tcmu_nl_cmd *nl_cmd) +{ + struct tcmu_dev *udev = nl_cmd->udev; + + if (!tcmu_netlink_blocked) { + pr_err("Could not reset device's netlink interface. Netlink is not blocked.\n"); + return -EBUSY; + } + + if (nl_cmd->cmd != TCMU_CMD_UNSPEC) { + pr_debug("Aborting nl cmd %d on %s\n", nl_cmd->cmd, udev->name); + nl_cmd->status = -EINTR; + list_del(&nl_cmd->nl_list); + complete(&nl_cmd->complete); + } + return 0; +} + +static int tcmu_set_reset_netlink(const char *str, + const struct kernel_param *kp) +{ + struct tcmu_nl_cmd *nl_cmd, *tmp_cmd; + int ret; + u8 val; + + ret = kstrtou8(str, 0, &val); + if (ret < 0) + return ret; + + if (val != 1) { + pr_err("Invalid reset netlink value %u\n", val); + return -EINVAL; + } + + mutex_lock(&tcmu_nl_cmd_mutex); + list_for_each_entry_safe(nl_cmd, tmp_cmd, &tcmu_nl_cmd_list, nl_list) { + ret = tcmu_fail_netlink_cmd(nl_cmd); + if (ret) + break; + } + mutex_unlock(&tcmu_nl_cmd_mutex); + + return ret; +} + +static const struct kernel_param_ops tcmu_reset_netlink_op = { + .set = tcmu_set_reset_netlink, +}; + +module_param_cb(reset_netlink, &tcmu_reset_netlink_op, NULL, S_IWUSR); +MODULE_PARM_DESC(reset_netlink, "Reset netlink commands."); + /* multicast group */ enum tcmu_multicast_groups { TCMU_MCGRP_CONFIG, @@ -274,48 +361,50 @@ static struct nla_policy tcmu_attr_policy[TCMU_ATTR_MAX+1] = { static int tcmu_genl_cmd_done(struct genl_info *info, int completed_cmd) { - struct se_device *dev; - struct tcmu_dev *udev; + struct tcmu_dev *udev = NULL; struct tcmu_nl_cmd *nl_cmd; int dev_id, rc, ret = 0; - bool is_removed = (completed_cmd == TCMU_CMD_REMOVED_DEVICE); if (!info->attrs[TCMU_ATTR_CMD_STATUS] || !info->attrs[TCMU_ATTR_DEVICE_ID]) { printk(KERN_ERR "TCMU_ATTR_CMD_STATUS or TCMU_ATTR_DEVICE_ID not set, doing nothing\n"); - return -EINVAL; + return -EINVAL; } dev_id = nla_get_u32(info->attrs[TCMU_ATTR_DEVICE_ID]); rc = nla_get_s32(info->attrs[TCMU_ATTR_CMD_STATUS]); - dev = target_find_device(dev_id, !is_removed); - if (!dev) { - printk(KERN_ERR "tcmu nl cmd %u/%u completion could not find device with dev id %u.\n", - completed_cmd, rc, dev_id); - return -ENODEV; + mutex_lock(&tcmu_nl_cmd_mutex); + list_for_each_entry(nl_cmd, &tcmu_nl_cmd_list, nl_list) { + if (nl_cmd->udev->se_dev.dev_index == dev_id) { + udev = nl_cmd->udev; + break; + } } - udev = TCMU_DEV(dev); - spin_lock(&udev->nl_cmd_lock); - nl_cmd = &udev->curr_nl_cmd; + if (!udev) { + pr_err("tcmu nl cmd %u/%d completion could not find device with dev id %u.\n", + completed_cmd, rc, dev_id); + ret = -ENODEV; + goto unlock; + } + list_del(&nl_cmd->nl_list); - pr_debug("genl cmd done got id %d curr %d done %d rc %d\n", dev_id, - nl_cmd->cmd, completed_cmd, rc); + pr_debug("%s genl cmd done got id %d curr %d done %d rc %d stat %d\n", + udev->name, dev_id, nl_cmd->cmd, completed_cmd, rc, + nl_cmd->status); if (nl_cmd->cmd != completed_cmd) { - printk(KERN_ERR "Mismatched commands (Expecting reply for %d. Current %d).\n", - completed_cmd, nl_cmd->cmd); + pr_err("Mismatched commands on %s (Expecting reply for %d. Current %d).\n", + udev->name, completed_cmd, nl_cmd->cmd); ret = -EINVAL; - } else { - nl_cmd->status = rc; + goto unlock; } - spin_unlock(&udev->nl_cmd_lock); - if (!is_removed) - target_undepend_item(&dev->dev_group.cg_item); - if (!ret) - complete(&nl_cmd->complete); + nl_cmd->status = rc; + complete(&nl_cmd->complete); +unlock: + mutex_unlock(&tcmu_nl_cmd_mutex); return ret; } @@ -982,7 +1071,6 @@ static sense_reason_t queue_cmd_ring(struct tcmu_cmd *tcmu_cmd, int *scsi_err) &udev->cmd_timer); if (ret) { tcmu_cmd_free_data(tcmu_cmd, tcmu_cmd->dbi_cnt); - mutex_unlock(&udev->cmdr_lock); *scsi_err = TCM_OUT_OF_RESOURCES; return -1; @@ -1282,6 +1370,7 @@ static struct se_device *tcmu_alloc_device(struct se_hba *hba, const char *name) udev->max_blocks = DATA_BLOCK_BITS_DEF; mutex_init(&udev->cmdr_lock); + INIT_LIST_HEAD(&udev->node); INIT_LIST_HEAD(&udev->timedout_entry); INIT_LIST_HEAD(&udev->cmdr_queue); idr_init(&udev->commands); @@ -1289,9 +1378,6 @@ static struct se_device *tcmu_alloc_device(struct se_hba *hba, const char *name) timer_setup(&udev->qfull_timer, tcmu_qfull_timedout, 0); timer_setup(&udev->cmd_timer, tcmu_cmd_timedout, 0); - init_waitqueue_head(&udev->nl_cmd_wq); - spin_lock_init(&udev->nl_cmd_lock); - INIT_RADIX_TREE(&udev->data_blocks, GFP_KERNEL); return &udev->se_dev; @@ -1565,38 +1651,48 @@ static int tcmu_release(struct uio_info *info, struct inode *inode) return 0; } -static void tcmu_init_genl_cmd_reply(struct tcmu_dev *udev, int cmd) +static int tcmu_init_genl_cmd_reply(struct tcmu_dev *udev, int cmd) { struct tcmu_nl_cmd *nl_cmd = &udev->curr_nl_cmd; if (!tcmu_kern_cmd_reply_supported) - return; + return 0; if (udev->nl_reply_supported <= 0) - return; + return 0; + + mutex_lock(&tcmu_nl_cmd_mutex); -relock: - spin_lock(&udev->nl_cmd_lock); + if (tcmu_netlink_blocked) { + mutex_unlock(&tcmu_nl_cmd_mutex); + pr_warn("Failing nl cmd %d on %s. Interface is blocked.\n", cmd, + udev->name); + return -EAGAIN; + } if (nl_cmd->cmd != TCMU_CMD_UNSPEC) { - spin_unlock(&udev->nl_cmd_lock); - pr_debug("sleeping for open nl cmd\n"); - wait_event(udev->nl_cmd_wq, (nl_cmd->cmd == TCMU_CMD_UNSPEC)); - goto relock; + mutex_unlock(&tcmu_nl_cmd_mutex); + pr_warn("netlink cmd %d already executing on %s\n", + nl_cmd->cmd, udev->name); + return -EBUSY; } memset(nl_cmd, 0, sizeof(*nl_cmd)); nl_cmd->cmd = cmd; + nl_cmd->udev = udev; init_completion(&nl_cmd->complete); + INIT_LIST_HEAD(&nl_cmd->nl_list); + + list_add_tail(&nl_cmd->nl_list, &tcmu_nl_cmd_list); - spin_unlock(&udev->nl_cmd_lock); + mutex_unlock(&tcmu_nl_cmd_mutex); + return 0; } static int tcmu_wait_genl_cmd_reply(struct tcmu_dev *udev) { struct tcmu_nl_cmd *nl_cmd = &udev->curr_nl_cmd; int ret; - DEFINE_WAIT(__wait); if (!tcmu_kern_cmd_reply_supported) return 0; @@ -1607,13 +1703,10 @@ static int tcmu_wait_genl_cmd_reply(struct tcmu_dev *udev) pr_debug("sleeping for nl reply\n"); wait_for_completion(&nl_cmd->complete); - spin_lock(&udev->nl_cmd_lock); + mutex_lock(&tcmu_nl_cmd_mutex); nl_cmd->cmd = TCMU_CMD_UNSPEC; ret = nl_cmd->status; - nl_cmd->status = 0; - spin_unlock(&udev->nl_cmd_lock); - - wake_up_all(&udev->nl_cmd_wq); + mutex_unlock(&tcmu_nl_cmd_mutex); return ret; } @@ -1657,19 +1750,21 @@ free_skb: static int tcmu_netlink_event_send(struct tcmu_dev *udev, enum tcmu_genl_cmd cmd, - struct sk_buff **buf, void **hdr) + struct sk_buff *skb, void *msg_header) { - int ret = 0; - struct sk_buff *skb = *buf; - void *msg_header = *hdr; + int ret; genlmsg_end(skb, msg_header); - tcmu_init_genl_cmd_reply(udev, cmd); + ret = tcmu_init_genl_cmd_reply(udev, cmd); + if (ret) { + nlmsg_free(skb); + return ret; + } ret = genlmsg_multicast_allns(&tcmu_genl_family, skb, 0, TCMU_MCGRP_CONFIG, GFP_KERNEL); - /* We don't care if no one is listening */ + /* We don't care if no one is listening */ if (ret == -ESRCH) ret = 0; if (!ret) @@ -1687,9 +1782,8 @@ static int tcmu_send_dev_add_event(struct tcmu_dev *udev) &msg_header); if (ret < 0) return ret; - return tcmu_netlink_event_send(udev, TCMU_CMD_ADDED_DEVICE, &skb, - &msg_header); - + return tcmu_netlink_event_send(udev, TCMU_CMD_ADDED_DEVICE, skb, + msg_header); } static int tcmu_send_dev_remove_event(struct tcmu_dev *udev) @@ -1703,7 +1797,7 @@ static int tcmu_send_dev_remove_event(struct tcmu_dev *udev) if (ret < 0) return ret; return tcmu_netlink_event_send(udev, TCMU_CMD_REMOVED_DEVICE, - &skb, &msg_header); + skb, msg_header); } static int tcmu_update_uio_info(struct tcmu_dev *udev) @@ -1745,9 +1839,11 @@ static int tcmu_configure_device(struct se_device *dev) info = &udev->uio_info; + mutex_lock(&udev->cmdr_lock); udev->data_bitmap = kcalloc(BITS_TO_LONGS(udev->max_blocks), sizeof(unsigned long), GFP_KERNEL); + mutex_unlock(&udev->cmdr_lock); if (!udev->data_bitmap) { ret = -ENOMEM; goto err_bitmap_alloc; @@ -1842,11 +1938,6 @@ err_bitmap_alloc: return ret; } -static bool tcmu_dev_configured(struct tcmu_dev *udev) -{ - return udev->uio_info.uio_dev ? true : false; -} - static void tcmu_free_device(struct se_device *dev) { struct tcmu_dev *udev = TCMU_DEV(dev); @@ -1953,45 +2044,76 @@ enum { static match_table_t tokens = { {Opt_dev_config, "dev_config=%s"}, - {Opt_dev_size, "dev_size=%u"}, - {Opt_hw_block_size, "hw_block_size=%u"}, - {Opt_hw_max_sectors, "hw_max_sectors=%u"}, + {Opt_dev_size, "dev_size=%s"}, + {Opt_hw_block_size, "hw_block_size=%d"}, + {Opt_hw_max_sectors, "hw_max_sectors=%d"}, {Opt_nl_reply_supported, "nl_reply_supported=%d"}, - {Opt_max_data_area_mb, "max_data_area_mb=%u"}, + {Opt_max_data_area_mb, "max_data_area_mb=%d"}, {Opt_err, NULL} }; static int tcmu_set_dev_attrib(substring_t *arg, u32 *dev_attrib) { - unsigned long tmp_ul; - char *arg_p; - int ret; + int val, ret; - arg_p = match_strdup(arg); - if (!arg_p) - return -ENOMEM; - - ret = kstrtoul(arg_p, 0, &tmp_ul); - kfree(arg_p); + ret = match_int(arg, &val); if (ret < 0) { - pr_err("kstrtoul() failed for dev attrib\n"); + pr_err("match_int() failed for dev attrib. Error %d.\n", + ret); return ret; } - if (!tmp_ul) { - pr_err("dev attrib must be nonzero\n"); + + if (val <= 0) { + pr_err("Invalid dev attrib value %d. Must be greater than zero.\n", + val); return -EINVAL; } - *dev_attrib = tmp_ul; + *dev_attrib = val; return 0; } +static int tcmu_set_max_blocks_param(struct tcmu_dev *udev, substring_t *arg) +{ + int val, ret; + + ret = match_int(arg, &val); + if (ret < 0) { + pr_err("match_int() failed for max_data_area_mb=. Error %d.\n", + ret); + return ret; + } + + if (val <= 0) { + pr_err("Invalid max_data_area %d.\n", val); + return -EINVAL; + } + + mutex_lock(&udev->cmdr_lock); + if (udev->data_bitmap) { + pr_err("Cannot set max_data_area_mb after it has been enabled.\n"); + ret = -EINVAL; + goto unlock; + } + + udev->max_blocks = TCMU_MBS_TO_BLOCKS(val); + if (udev->max_blocks > tcmu_global_max_blocks) { + pr_err("%d is too large. Adjusting max_data_area_mb to global limit of %u\n", + val, TCMU_BLOCKS_TO_MBS(tcmu_global_max_blocks)); + udev->max_blocks = tcmu_global_max_blocks; + } + +unlock: + mutex_unlock(&udev->cmdr_lock); + return ret; +} + static ssize_t tcmu_set_configfs_dev_params(struct se_device *dev, const char *page, ssize_t count) { struct tcmu_dev *udev = TCMU_DEV(dev); - char *orig, *ptr, *opts, *arg_p; + char *orig, *ptr, *opts; substring_t args[MAX_OPT_ARGS]; - int ret = 0, token, tmpval; + int ret = 0, token; opts = kstrdup(page, GFP_KERNEL); if (!opts) @@ -2014,15 +2136,10 @@ static ssize_t tcmu_set_configfs_dev_params(struct se_device *dev, pr_debug("TCMU: Referencing Path: %s\n", udev->dev_config); break; case Opt_dev_size: - arg_p = match_strdup(&args[0]); - if (!arg_p) { - ret = -ENOMEM; - break; - } - ret = kstrtoul(arg_p, 0, (unsigned long *) &udev->dev_size); - kfree(arg_p); + ret = match_u64(&args[0], &udev->dev_size); if (ret < 0) - pr_err("kstrtoul() failed for dev_size=\n"); + pr_err("match_u64() failed for dev_size=. Error %d.\n", + ret); break; case Opt_hw_block_size: ret = tcmu_set_dev_attrib(&args[0], @@ -2033,48 +2150,13 @@ static ssize_t tcmu_set_configfs_dev_params(struct se_device *dev, &(dev->dev_attrib.hw_max_sectors)); break; case Opt_nl_reply_supported: - arg_p = match_strdup(&args[0]); - if (!arg_p) { - ret = -ENOMEM; - break; - } - ret = kstrtoint(arg_p, 0, &udev->nl_reply_supported); - kfree(arg_p); + ret = match_int(&args[0], &udev->nl_reply_supported); if (ret < 0) - pr_err("kstrtoint() failed for nl_reply_supported=\n"); + pr_err("match_int() failed for nl_reply_supported=. Error %d.\n", + ret); break; case Opt_max_data_area_mb: - if (dev->export_count) { - pr_err("Unable to set max_data_area_mb while exports exist\n"); - ret = -EINVAL; - break; - } - - arg_p = match_strdup(&args[0]); - if (!arg_p) { - ret = -ENOMEM; - break; - } - ret = kstrtoint(arg_p, 0, &tmpval); - kfree(arg_p); - if (ret < 0) { - pr_err("kstrtoint() failed for max_data_area_mb=\n"); - break; - } - - if (tmpval <= 0) { - pr_err("Invalid max_data_area %d\n", tmpval); - ret = -EINVAL; - break; - } - - udev->max_blocks = TCMU_MBS_TO_BLOCKS(tmpval); - if (udev->max_blocks > tcmu_global_max_blocks) { - pr_err("%d is too large. Adjusting max_data_area_mb to global limit of %u\n", - tmpval, - TCMU_BLOCKS_TO_MBS(tcmu_global_max_blocks)); - udev->max_blocks = tcmu_global_max_blocks; - } + ret = tcmu_set_max_blocks_param(udev, &args[0]); break; default: break; @@ -2095,7 +2177,7 @@ static ssize_t tcmu_show_configfs_dev_params(struct se_device *dev, char *b) bl = sprintf(b + bl, "Config: %s ", udev->dev_config[0] ? udev->dev_config : "NULL"); - bl += sprintf(b + bl, "Size: %zu ", udev->dev_size); + bl += sprintf(b + bl, "Size: %llu ", udev->dev_size); bl += sprintf(b + bl, "MaxDataAreaMB: %u\n", TCMU_BLOCKS_TO_MBS(udev->max_blocks)); @@ -2222,7 +2304,7 @@ static int tcmu_send_dev_config_event(struct tcmu_dev *udev, return ret; } return tcmu_netlink_event_send(udev, TCMU_CMD_RECONFIG_DEVICE, - &skb, &msg_header); + skb, msg_header); } @@ -2239,7 +2321,7 @@ static ssize_t tcmu_dev_config_store(struct config_item *item, const char *page, return -EINVAL; /* Check if device has been configured before */ - if (tcmu_dev_configured(udev)) { + if (target_dev_configured(&udev->se_dev)) { ret = tcmu_send_dev_config_event(udev, page); if (ret) { pr_err("Unable to reconfigure device\n"); @@ -2264,7 +2346,7 @@ static ssize_t tcmu_dev_size_show(struct config_item *item, char *page) struct se_dev_attrib, da_group); struct tcmu_dev *udev = TCMU_DEV(da->da_dev); - return snprintf(page, PAGE_SIZE, "%zu\n", udev->dev_size); + return snprintf(page, PAGE_SIZE, "%llu\n", udev->dev_size); } static int tcmu_send_dev_size_event(struct tcmu_dev *udev, u64 size) @@ -2284,7 +2366,7 @@ static int tcmu_send_dev_size_event(struct tcmu_dev *udev, u64 size) return ret; } return tcmu_netlink_event_send(udev, TCMU_CMD_RECONFIG_DEVICE, - &skb, &msg_header); + skb, msg_header); } static ssize_t tcmu_dev_size_store(struct config_item *item, const char *page, @@ -2301,7 +2383,7 @@ static ssize_t tcmu_dev_size_store(struct config_item *item, const char *page, return ret; /* Check if device has been configured before */ - if (tcmu_dev_configured(udev)) { + if (target_dev_configured(&udev->se_dev)) { ret = tcmu_send_dev_size_event(udev, val); if (ret) { pr_err("Unable to reconfigure device\n"); @@ -2366,7 +2448,7 @@ static int tcmu_send_emulate_write_cache(struct tcmu_dev *udev, u8 val) return ret; } return tcmu_netlink_event_send(udev, TCMU_CMD_RECONFIG_DEVICE, - &skb, &msg_header); + skb, msg_header); } static ssize_t tcmu_emulate_write_cache_store(struct config_item *item, @@ -2383,7 +2465,7 @@ static ssize_t tcmu_emulate_write_cache_store(struct config_item *item, return ret; /* Check if device has been configured before */ - if (tcmu_dev_configured(udev)) { + if (target_dev_configured(&udev->se_dev)) { ret = tcmu_send_emulate_write_cache(udev, val); if (ret) { pr_err("Unable to reconfigure device\n"); @@ -2419,6 +2501,11 @@ static ssize_t tcmu_block_dev_store(struct config_item *item, const char *page, u8 val; int ret; + if (!target_dev_configured(&udev->se_dev)) { + pr_err("Device is not configured.\n"); + return -EINVAL; + } + ret = kstrtou8(page, 0, &val); if (ret < 0) return ret; @@ -2446,6 +2533,11 @@ static ssize_t tcmu_reset_ring_store(struct config_item *item, const char *page, u8 val; int ret; + if (!target_dev_configured(&udev->se_dev)) { + pr_err("Device is not configured.\n"); + return -EINVAL; + } + ret = kstrtou8(page, 0, &val); if (ret < 0) return ret; @@ -2510,6 +2602,11 @@ static void find_free_blocks(void) list_for_each_entry(udev, &root_udev, node) { mutex_lock(&udev->cmdr_lock); + if (!target_dev_configured(&udev->se_dev)) { + mutex_unlock(&udev->cmdr_lock); + continue; + } + /* Try to complete the finished commands first */ tcmu_handle_completions(udev); |