提交 3228691f 编写于 作者: M Mike Christie 提交者: Martin K. Petersen

scsi: tcmu: track nl commands

The next patch is going to fix the hung nl command issue so this adds a
list of outstanding nl commands that we can later abort when the daemon is
restarted.
Signed-off-by: NMike Christie <mchristi@redhat.com>
Signed-off-by: NMartin K. Petersen <martin.petersen@oracle.com>
上级 0297e962
...@@ -103,9 +103,16 @@ struct tcmu_hba { ...@@ -103,9 +103,16 @@ struct tcmu_hba {
#define TCMU_CONFIG_LEN 256 #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 { struct tcmu_nl_cmd {
/* wake up thread waiting for reply */ /* wake up thread waiting for reply */
struct completion complete; struct completion complete;
struct list_head nl_list;
struct tcmu_dev *udev;
int cmd; int cmd;
int status; int status;
}; };
...@@ -157,7 +164,6 @@ struct tcmu_dev { ...@@ -157,7 +164,6 @@ struct tcmu_dev {
struct list_head timedout_entry; struct list_head timedout_entry;
spinlock_t nl_cmd_lock;
struct tcmu_nl_cmd curr_nl_cmd; struct tcmu_nl_cmd curr_nl_cmd;
/* wake up threads waiting on curr_nl_cmd */ /* wake up threads waiting on curr_nl_cmd */
wait_queue_head_t nl_cmd_wq; wait_queue_head_t nl_cmd_wq;
...@@ -270,11 +276,9 @@ static struct nla_policy tcmu_attr_policy[TCMU_ATTR_MAX+1] = { ...@@ -270,11 +276,9 @@ static struct nla_policy tcmu_attr_policy[TCMU_ATTR_MAX+1] = {
static int tcmu_genl_cmd_done(struct genl_info *info, int completed_cmd) static int tcmu_genl_cmd_done(struct genl_info *info, int completed_cmd)
{ {
struct se_device *dev; struct tcmu_dev *udev = NULL;
struct tcmu_dev *udev;
struct tcmu_nl_cmd *nl_cmd; struct tcmu_nl_cmd *nl_cmd;
int dev_id, rc, ret = 0; int dev_id, rc, ret = 0;
bool is_removed = (completed_cmd == TCMU_CMD_REMOVED_DEVICE);
if (!info->attrs[TCMU_ATTR_CMD_STATUS] || if (!info->attrs[TCMU_ATTR_CMD_STATUS] ||
!info->attrs[TCMU_ATTR_DEVICE_ID]) { !info->attrs[TCMU_ATTR_DEVICE_ID]) {
...@@ -285,33 +289,36 @@ static int tcmu_genl_cmd_done(struct genl_info *info, int completed_cmd) ...@@ -285,33 +289,36 @@ static int tcmu_genl_cmd_done(struct genl_info *info, int completed_cmd)
dev_id = nla_get_u32(info->attrs[TCMU_ATTR_DEVICE_ID]); dev_id = nla_get_u32(info->attrs[TCMU_ATTR_DEVICE_ID]);
rc = nla_get_s32(info->attrs[TCMU_ATTR_CMD_STATUS]); rc = nla_get_s32(info->attrs[TCMU_ATTR_CMD_STATUS]);
dev = target_find_device(dev_id, !is_removed); mutex_lock(&tcmu_nl_cmd_mutex);
if (!dev) { list_for_each_entry(nl_cmd, &tcmu_nl_cmd_list, nl_list) {
printk(KERN_ERR "tcmu nl cmd %u/%u completion could not find device with dev id %u.\n", if (nl_cmd->udev->se_dev.dev_index == dev_id) {
completed_cmd, rc, dev_id); udev = nl_cmd->udev;
return -ENODEV; break;
}
} }
udev = TCMU_DEV(dev);
spin_lock(&udev->nl_cmd_lock); if (!udev) {
nl_cmd = &udev->curr_nl_cmd; pr_err(KERN_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, pr_debug("%s genl cmd done got id %d curr %d done %d rc %d\n",
nl_cmd->cmd, completed_cmd, rc); udev->name, dev_id, nl_cmd->cmd, completed_cmd, rc);
if (nl_cmd->cmd != completed_cmd) { if (nl_cmd->cmd != completed_cmd) {
printk(KERN_ERR "Mismatched commands (Expecting reply for %d. Current %d).\n", pr_err("Mismatched commands on %s (Expecting reply for %d. Current %d).\n",
completed_cmd, nl_cmd->cmd); udev->name, completed_cmd, nl_cmd->cmd);
ret = -EINVAL; ret = -EINVAL;
} else { goto unlock;
nl_cmd->status = rc;
} }
spin_unlock(&udev->nl_cmd_lock); nl_cmd->status = rc;
if (!is_removed) complete(&nl_cmd->complete);
target_undepend_item(&dev->dev_group.cg_item); unlock:
if (!ret) mutex_unlock(&tcmu_nl_cmd_mutex);
complete(&nl_cmd->complete);
return ret; return ret;
} }
...@@ -1258,7 +1265,6 @@ static struct se_device *tcmu_alloc_device(struct se_hba *hba, const char *name) ...@@ -1258,7 +1265,6 @@ static struct se_device *tcmu_alloc_device(struct se_hba *hba, const char *name)
timer_setup(&udev->cmd_timer, tcmu_cmd_timedout, 0); timer_setup(&udev->cmd_timer, tcmu_cmd_timedout, 0);
init_waitqueue_head(&udev->nl_cmd_wq); init_waitqueue_head(&udev->nl_cmd_wq);
spin_lock_init(&udev->nl_cmd_lock);
INIT_RADIX_TREE(&udev->data_blocks, GFP_KERNEL); INIT_RADIX_TREE(&udev->data_blocks, GFP_KERNEL);
...@@ -1544,10 +1550,10 @@ static void tcmu_init_genl_cmd_reply(struct tcmu_dev *udev, int cmd) ...@@ -1544,10 +1550,10 @@ static void tcmu_init_genl_cmd_reply(struct tcmu_dev *udev, int cmd)
return; return;
relock: relock:
spin_lock(&udev->nl_cmd_lock); mutex_lock(&tcmu_nl_cmd_mutex);
if (nl_cmd->cmd != TCMU_CMD_UNSPEC) { if (nl_cmd->cmd != TCMU_CMD_UNSPEC) {
spin_unlock(&udev->nl_cmd_lock); mutex_unlock(&tcmu_nl_cmd_mutex);
pr_debug("sleeping for open nl cmd\n"); pr_debug("sleeping for open nl cmd\n");
wait_event(udev->nl_cmd_wq, (nl_cmd->cmd == TCMU_CMD_UNSPEC)); wait_event(udev->nl_cmd_wq, (nl_cmd->cmd == TCMU_CMD_UNSPEC));
goto relock; goto relock;
...@@ -1555,9 +1561,13 @@ static void tcmu_init_genl_cmd_reply(struct tcmu_dev *udev, int cmd) ...@@ -1555,9 +1561,13 @@ static void tcmu_init_genl_cmd_reply(struct tcmu_dev *udev, int cmd)
memset(nl_cmd, 0, sizeof(*nl_cmd)); memset(nl_cmd, 0, sizeof(*nl_cmd));
nl_cmd->cmd = cmd; nl_cmd->cmd = cmd;
nl_cmd->udev = udev;
init_completion(&nl_cmd->complete); 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);
} }
static int tcmu_wait_genl_cmd_reply(struct tcmu_dev *udev) static int tcmu_wait_genl_cmd_reply(struct tcmu_dev *udev)
...@@ -1574,11 +1584,11 @@ static int tcmu_wait_genl_cmd_reply(struct tcmu_dev *udev) ...@@ -1574,11 +1584,11 @@ static int tcmu_wait_genl_cmd_reply(struct tcmu_dev *udev)
pr_debug("sleeping for nl reply\n"); pr_debug("sleeping for nl reply\n");
wait_for_completion(&nl_cmd->complete); wait_for_completion(&nl_cmd->complete);
spin_lock(&udev->nl_cmd_lock); mutex_lock(&tcmu_nl_cmd_mutex);
nl_cmd->cmd = TCMU_CMD_UNSPEC; nl_cmd->cmd = TCMU_CMD_UNSPEC;
ret = nl_cmd->status; ret = nl_cmd->status;
nl_cmd->status = 0; nl_cmd->status = 0;
spin_unlock(&udev->nl_cmd_lock); mutex_unlock(&tcmu_nl_cmd_mutex);
wake_up_all(&udev->nl_cmd_wq); wake_up_all(&udev->nl_cmd_wq);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册