aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew R. Ochs <mrochs@linux.vnet.ibm.com>2016-03-04 16:55:17 -0500
committerMartin K. Petersen <martin.petersen@oracle.com>2016-03-08 21:17:33 -0500
commit8a96b52af58721caf4f7496d0737e8ec6b63c86e (patch)
tree1fbc33e9d6aba5a27577a3d41da0aea6ff00adf1
parent5e6632d19ea2fafaec1b7c4cda7f7157ee8ad983 (diff)
cxlflash: Simplify attach path error cleanup
The cxlflash_disk_attach() routine currently uses a cascading error gate strategy for its error cleanup path. While this strategy is commonly used to handle cleanup scenarios, it is too restrictive when function callouts need to be restructured. Problems range from inserting error path bugs in previously 'good' code to the cleanup path imposing design changes to how the normal path is structured. A less restrictive approach is needed to support ordering changes that come about when operating in different environments. To overcome this restriction, the error cleanup path is modified to have a single entrypoint and use conditional logic to cleanup where necessary. Entities that require multiple cleanup steps must be carefully vetted to ensure their APIs support state. In cases where they do not (none as of this commit) additional local variables can be used to maintain state on their behalf. Signed-off-by: Matthew R. Ochs <mrochs@linux.vnet.ibm.com> Reviewed-by: Uma Krishnan <ukrishn@linux.vnet.ibm.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-rw-r--r--drivers/scsi/cxlflash/superpipe.c55
1 files changed, 31 insertions, 24 deletions
diff --git a/drivers/scsi/cxlflash/superpipe.c b/drivers/scsi/cxlflash/superpipe.c
index b30b362318fa..7ec0b7a92876 100644
--- a/drivers/scsi/cxlflash/superpipe.c
+++ b/drivers/scsi/cxlflash/superpipe.c
@@ -1315,9 +1315,9 @@ static int cxlflash_disk_attach(struct scsi_device *sdev,
1315 u32 perms; 1315 u32 perms;
1316 int ctxid = -1; 1316 int ctxid = -1;
1317 u64 rctxid = 0UL; 1317 u64 rctxid = 0UL;
1318 struct file *file; 1318 struct file *file = NULL;
1319 1319
1320 struct cxl_context *ctx; 1320 struct cxl_context *ctx = NULL;
1321 1321
1322 int fd = -1; 1322 int fd = -1;
1323 1323
@@ -1371,7 +1371,7 @@ static int cxlflash_disk_attach(struct scsi_device *sdev,
1371 if (unlikely(!lun_access)) { 1371 if (unlikely(!lun_access)) {
1372 dev_err(dev, "%s: Unable to allocate lun_access!\n", __func__); 1372 dev_err(dev, "%s: Unable to allocate lun_access!\n", __func__);
1373 rc = -ENOMEM; 1373 rc = -ENOMEM;
1374 goto err0; 1374 goto err;
1375 } 1375 }
1376 1376
1377 lun_access->lli = lli; 1377 lun_access->lli = lli;
@@ -1391,21 +1391,21 @@ static int cxlflash_disk_attach(struct scsi_device *sdev,
1391 dev_err(dev, "%s: Could not initialize context %p\n", 1391 dev_err(dev, "%s: Could not initialize context %p\n",
1392 __func__, ctx); 1392 __func__, ctx);
1393 rc = -ENODEV; 1393 rc = -ENODEV;
1394 goto err1; 1394 goto err;
1395 } 1395 }
1396 1396
1397 ctxid = cxl_process_element(ctx); 1397 ctxid = cxl_process_element(ctx);
1398 if (unlikely((ctxid >= MAX_CONTEXT) || (ctxid < 0))) { 1398 if (unlikely((ctxid >= MAX_CONTEXT) || (ctxid < 0))) {
1399 dev_err(dev, "%s: ctxid (%d) invalid!\n", __func__, ctxid); 1399 dev_err(dev, "%s: ctxid (%d) invalid!\n", __func__, ctxid);
1400 rc = -EPERM; 1400 rc = -EPERM;
1401 goto err2; 1401 goto err;
1402 } 1402 }
1403 1403
1404 file = cxl_get_fd(ctx, &cfg->cxl_fops, &fd); 1404 file = cxl_get_fd(ctx, &cfg->cxl_fops, &fd);
1405 if (unlikely(fd < 0)) { 1405 if (unlikely(fd < 0)) {
1406 rc = -ENODEV; 1406 rc = -ENODEV;
1407 dev_err(dev, "%s: Could not get file descriptor\n", __func__); 1407 dev_err(dev, "%s: Could not get file descriptor\n", __func__);
1408 goto err2; 1408 goto err;
1409 } 1409 }
1410 1410
1411 /* Translate read/write O_* flags from fcntl.h to AFU permission bits */ 1411 /* Translate read/write O_* flags from fcntl.h to AFU permission bits */
@@ -1415,7 +1415,7 @@ static int cxlflash_disk_attach(struct scsi_device *sdev,
1415 if (unlikely(!ctxi)) { 1415 if (unlikely(!ctxi)) {
1416 dev_err(dev, "%s: Failed to create context! (%d)\n", 1416 dev_err(dev, "%s: Failed to create context! (%d)\n",
1417 __func__, ctxid); 1417 __func__, ctxid);
1418 goto err3; 1418 goto err;
1419 } 1419 }
1420 1420
1421 /* Context mutex is locked upon return */ 1421 /* Context mutex is locked upon return */
@@ -1429,13 +1429,13 @@ static int cxlflash_disk_attach(struct scsi_device *sdev,
1429 if (unlikely(rc)) { 1429 if (unlikely(rc)) {
1430 dev_dbg(dev, "%s: Could not start context rc=%d\n", 1430 dev_dbg(dev, "%s: Could not start context rc=%d\n",
1431 __func__, rc); 1431 __func__, rc);
1432 goto err4; 1432 goto err;
1433 } 1433 }
1434 1434
1435 rc = afu_attach(cfg, ctxi); 1435 rc = afu_attach(cfg, ctxi);
1436 if (unlikely(rc)) { 1436 if (unlikely(rc)) {
1437 dev_err(dev, "%s: Could not attach AFU rc %d\n", __func__, rc); 1437 dev_err(dev, "%s: Could not attach AFU rc %d\n", __func__, rc);
1438 goto err5; 1438 goto err;
1439 } 1439 }
1440 1440
1441 /* 1441 /*
@@ -1471,13 +1471,14 @@ out:
1471 __func__, ctxid, fd, attach->block_size, rc, attach->last_lba); 1471 __func__, ctxid, fd, attach->block_size, rc, attach->last_lba);
1472 return rc; 1472 return rc;
1473 1473
1474err5: 1474err:
1475 cxl_stop_context(ctx); 1475 /* Cleanup CXL context; okay to 'stop' even if it was not started */
1476err4: 1476 if (!IS_ERR_OR_NULL(ctx)) {
1477 put_context(ctxi); 1477 cxl_stop_context(ctx);
1478 destroy_context(cfg, ctxi); 1478 cxl_release_context(ctx);
1479 ctxi = NULL; 1479 ctx = NULL;
1480err3: 1480 }
1481
1481 /* 1482 /*
1482 * Here, we're overriding the fops with a dummy all-NULL fops because 1483 * Here, we're overriding the fops with a dummy all-NULL fops because
1483 * fput() calls the release fop, which will cause us to mistakenly 1484 * fput() calls the release fop, which will cause us to mistakenly
@@ -1485,15 +1486,21 @@ err3:
1485 * to that routine (cxlflash_cxl_release) we should try to fix the 1486 * to that routine (cxlflash_cxl_release) we should try to fix the
1486 * issue here. 1487 * issue here.
1487 */ 1488 */
1488 file->f_op = &null_fops; 1489 if (fd > 0) {
1489 fput(file); 1490 file->f_op = &null_fops;
1490 put_unused_fd(fd); 1491 fput(file);
1491 fd = -1; 1492 put_unused_fd(fd);
1492err2: 1493 fd = -1;
1493 cxl_release_context(ctx); 1494 file = NULL;
1494err1: 1495 }
1496
1497 /* Cleanup our context; safe to call even with mutex locked */
1498 if (ctxi) {
1499 destroy_context(cfg, ctxi);
1500 ctxi = NULL;
1501 }
1502
1495 kfree(lun_access); 1503 kfree(lun_access);
1496err0:
1497 scsi_device_put(sdev); 1504 scsi_device_put(sdev);
1498 goto out; 1505 goto out;
1499} 1506}