aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/target/target_core_user.c
diff options
context:
space:
mode:
authorMike Christie <mchristi@redhat.com>2018-06-22 17:40:19 -0400
committerMartin K. Petersen <martin.petersen@oracle.com>2018-06-26 12:27:05 -0400
commit3228691ffec134353cb5bf6fb4342283e0243412 (patch)
tree46efebf9fc6b44dac7ede03eea16a49c27722cc6 /drivers/target/target_core_user.c
parent0297e962907d98ece34188cb267d3313812b6e42 (diff)
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: Mike Christie <mchristi@redhat.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/target/target_core_user.c')
-rw-r--r--drivers/target/target_core_user.c68
1 files changed, 39 insertions, 29 deletions
diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c
index 898a5619f2d6..73a57681e312 100644
--- a/drivers/target/target_core_user.c
+++ b/drivers/target/target_core_user.c
@@ -103,9 +103,16 @@ struct tcmu_hba {
103 103
104#define TCMU_CONFIG_LEN 256 104#define TCMU_CONFIG_LEN 256
105 105
106static DEFINE_MUTEX(tcmu_nl_cmd_mutex);
107static LIST_HEAD(tcmu_nl_cmd_list);
108
109struct tcmu_dev;
110
106struct tcmu_nl_cmd { 111struct tcmu_nl_cmd {
107 /* wake up thread waiting for reply */ 112 /* wake up thread waiting for reply */
108 struct completion complete; 113 struct completion complete;
114 struct list_head nl_list;
115 struct tcmu_dev *udev;
109 int cmd; 116 int cmd;
110 int status; 117 int status;
111}; 118};
@@ -157,7 +164,6 @@ struct tcmu_dev {
157 164
158 struct list_head timedout_entry; 165 struct list_head timedout_entry;
159 166
160 spinlock_t nl_cmd_lock;
161 struct tcmu_nl_cmd curr_nl_cmd; 167 struct tcmu_nl_cmd curr_nl_cmd;
162 /* wake up threads waiting on curr_nl_cmd */ 168 /* wake up threads waiting on curr_nl_cmd */
163 wait_queue_head_t nl_cmd_wq; 169 wait_queue_head_t nl_cmd_wq;
@@ -270,11 +276,9 @@ static struct nla_policy tcmu_attr_policy[TCMU_ATTR_MAX+1] = {
270 276
271static int tcmu_genl_cmd_done(struct genl_info *info, int completed_cmd) 277static int tcmu_genl_cmd_done(struct genl_info *info, int completed_cmd)
272{ 278{
273 struct se_device *dev; 279 struct tcmu_dev *udev = NULL;
274 struct tcmu_dev *udev;
275 struct tcmu_nl_cmd *nl_cmd; 280 struct tcmu_nl_cmd *nl_cmd;
276 int dev_id, rc, ret = 0; 281 int dev_id, rc, ret = 0;
277 bool is_removed = (completed_cmd == TCMU_CMD_REMOVED_DEVICE);
278 282
279 if (!info->attrs[TCMU_ATTR_CMD_STATUS] || 283 if (!info->attrs[TCMU_ATTR_CMD_STATUS] ||
280 !info->attrs[TCMU_ATTR_DEVICE_ID]) { 284 !info->attrs[TCMU_ATTR_DEVICE_ID]) {
@@ -285,33 +289,36 @@ static int tcmu_genl_cmd_done(struct genl_info *info, int completed_cmd)
285 dev_id = nla_get_u32(info->attrs[TCMU_ATTR_DEVICE_ID]); 289 dev_id = nla_get_u32(info->attrs[TCMU_ATTR_DEVICE_ID]);
286 rc = nla_get_s32(info->attrs[TCMU_ATTR_CMD_STATUS]); 290 rc = nla_get_s32(info->attrs[TCMU_ATTR_CMD_STATUS]);
287 291
288 dev = target_find_device(dev_id, !is_removed); 292 mutex_lock(&tcmu_nl_cmd_mutex);
289 if (!dev) { 293 list_for_each_entry(nl_cmd, &tcmu_nl_cmd_list, nl_list) {
290 printk(KERN_ERR "tcmu nl cmd %u/%u completion could not find device with dev id %u.\n", 294 if (nl_cmd->udev->se_dev.dev_index == dev_id) {
291 completed_cmd, rc, dev_id); 295 udev = nl_cmd->udev;
292 return -ENODEV; 296 break;
297 }
293 } 298 }
294 udev = TCMU_DEV(dev);
295 299
296 spin_lock(&udev->nl_cmd_lock); 300 if (!udev) {
297 nl_cmd = &udev->curr_nl_cmd; 301 pr_err(KERN_ERR "tcmu nl cmd %u/%d completion could not find device with dev id %u.\n",
302 completed_cmd, rc, dev_id);
303 ret = -ENODEV;
304 goto unlock;
305 }
306 list_del(&nl_cmd->nl_list);
298 307
299 pr_debug("genl cmd done got id %d curr %d done %d rc %d\n", dev_id, 308 pr_debug("%s genl cmd done got id %d curr %d done %d rc %d\n",
300 nl_cmd->cmd, completed_cmd, rc); 309 udev->name, dev_id, nl_cmd->cmd, completed_cmd, rc);
301 310
302 if (nl_cmd->cmd != completed_cmd) { 311 if (nl_cmd->cmd != completed_cmd) {
303 printk(KERN_ERR "Mismatched commands (Expecting reply for %d. Current %d).\n", 312 pr_err("Mismatched commands on %s (Expecting reply for %d. Current %d).\n",
304 completed_cmd, nl_cmd->cmd); 313 udev->name, completed_cmd, nl_cmd->cmd);
305 ret = -EINVAL; 314 ret = -EINVAL;
306 } else { 315 goto unlock;
307 nl_cmd->status = rc;
308 } 316 }
309 317
310 spin_unlock(&udev->nl_cmd_lock); 318 nl_cmd->status = rc;
311 if (!is_removed) 319 complete(&nl_cmd->complete);
312 target_undepend_item(&dev->dev_group.cg_item); 320unlock:
313 if (!ret) 321 mutex_unlock(&tcmu_nl_cmd_mutex);
314 complete(&nl_cmd->complete);
315 return ret; 322 return ret;
316} 323}
317 324
@@ -1258,7 +1265,6 @@ static struct se_device *tcmu_alloc_device(struct se_hba *hba, const char *name)
1258 timer_setup(&udev->cmd_timer, tcmu_cmd_timedout, 0); 1265 timer_setup(&udev->cmd_timer, tcmu_cmd_timedout, 0);
1259 1266
1260 init_waitqueue_head(&udev->nl_cmd_wq); 1267 init_waitqueue_head(&udev->nl_cmd_wq);
1261 spin_lock_init(&udev->nl_cmd_lock);
1262 1268
1263 INIT_RADIX_TREE(&udev->data_blocks, GFP_KERNEL); 1269 INIT_RADIX_TREE(&udev->data_blocks, GFP_KERNEL);
1264 1270
@@ -1544,10 +1550,10 @@ static void tcmu_init_genl_cmd_reply(struct tcmu_dev *udev, int cmd)
1544 return; 1550 return;
1545 1551
1546relock: 1552relock:
1547 spin_lock(&udev->nl_cmd_lock); 1553 mutex_lock(&tcmu_nl_cmd_mutex);
1548 1554
1549 if (nl_cmd->cmd != TCMU_CMD_UNSPEC) { 1555 if (nl_cmd->cmd != TCMU_CMD_UNSPEC) {
1550 spin_unlock(&udev->nl_cmd_lock); 1556 mutex_unlock(&tcmu_nl_cmd_mutex);
1551 pr_debug("sleeping for open nl cmd\n"); 1557 pr_debug("sleeping for open nl cmd\n");
1552 wait_event(udev->nl_cmd_wq, (nl_cmd->cmd == TCMU_CMD_UNSPEC)); 1558 wait_event(udev->nl_cmd_wq, (nl_cmd->cmd == TCMU_CMD_UNSPEC));
1553 goto relock; 1559 goto relock;
@@ -1555,9 +1561,13 @@ relock:
1555 1561
1556 memset(nl_cmd, 0, sizeof(*nl_cmd)); 1562 memset(nl_cmd, 0, sizeof(*nl_cmd));
1557 nl_cmd->cmd = cmd; 1563 nl_cmd->cmd = cmd;
1564 nl_cmd->udev = udev;
1558 init_completion(&nl_cmd->complete); 1565 init_completion(&nl_cmd->complete);
1566 INIT_LIST_HEAD(&nl_cmd->nl_list);
1567
1568 list_add_tail(&nl_cmd->nl_list, &tcmu_nl_cmd_list);
1559 1569
1560 spin_unlock(&udev->nl_cmd_lock); 1570 mutex_unlock(&tcmu_nl_cmd_mutex);
1561} 1571}
1562 1572
1563static int tcmu_wait_genl_cmd_reply(struct tcmu_dev *udev) 1573static 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 pr_debug("sleeping for nl reply\n"); 1584 pr_debug("sleeping for nl reply\n");
1575 wait_for_completion(&nl_cmd->complete); 1585 wait_for_completion(&nl_cmd->complete);
1576 1586
1577 spin_lock(&udev->nl_cmd_lock); 1587 mutex_lock(&tcmu_nl_cmd_mutex);
1578 nl_cmd->cmd = TCMU_CMD_UNSPEC; 1588 nl_cmd->cmd = TCMU_CMD_UNSPEC;
1579 ret = nl_cmd->status; 1589 ret = nl_cmd->status;
1580 nl_cmd->status = 0; 1590 nl_cmd->status = 0;
1581 spin_unlock(&udev->nl_cmd_lock); 1591 mutex_unlock(&tcmu_nl_cmd_mutex);
1582 1592
1583 wake_up_all(&udev->nl_cmd_wq); 1593 wake_up_all(&udev->nl_cmd_wq);
1584 1594