Commit 22fe1ae8 authored by Matthew R. Ochs's avatar Matthew R. Ochs Committed by James Bottomley

cxlflash: Fix potential oops following LUN removal

When a LUN is removed, the sdev that is associated with the LUN
remains intact until its reference count drops to 0. In order
to prevent an sdev from being removed while a context is still
associated with it, obtain an additional reference per-context
for each LUN attached to the context.

This resolves a potential Oops in the release handler when a
dealing with a LUN that has already been removed.
Signed-off-by: default avatarMatthew R. Ochs <mrochs@linux.vnet.ibm.com>
Signed-off-by: default avatarManoj N. Kumar <manoj@linux.vnet.ibm.com>
Reviewed-by: default avatarBrian King <brking@linux.vnet.ibm.com>
Reviewed-by: default avatarTomas Henzl <thenzl@redhat.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Odin.com>
parent 471a5a60
...@@ -880,6 +880,9 @@ static int _cxlflash_disk_detach(struct scsi_device *sdev, ...@@ -880,6 +880,9 @@ static int _cxlflash_disk_detach(struct scsi_device *sdev,
sys_close(lfd); sys_close(lfd);
} }
/* Release the sdev reference that bound this LUN to the context */
scsi_device_put(sdev);
out: out:
if (put_ctx) if (put_ctx)
put_context(ctxi); put_context(ctxi);
...@@ -1287,11 +1290,17 @@ static int cxlflash_disk_attach(struct scsi_device *sdev, ...@@ -1287,11 +1290,17 @@ static int cxlflash_disk_attach(struct scsi_device *sdev,
} }
} }
rc = scsi_device_get(sdev);
if (unlikely(rc)) {
dev_err(dev, "%s: Unable to get sdev reference!\n", __func__);
goto out;
}
lun_access = kzalloc(sizeof(*lun_access), GFP_KERNEL); lun_access = kzalloc(sizeof(*lun_access), GFP_KERNEL);
if (unlikely(!lun_access)) { if (unlikely(!lun_access)) {
dev_err(dev, "%s: Unable to allocate lun_access!\n", __func__); dev_err(dev, "%s: Unable to allocate lun_access!\n", __func__);
rc = -ENOMEM; rc = -ENOMEM;
goto out; goto err0;
} }
lun_access->lli = lli; lun_access->lli = lli;
...@@ -1311,21 +1320,21 @@ static int cxlflash_disk_attach(struct scsi_device *sdev, ...@@ -1311,21 +1320,21 @@ static int cxlflash_disk_attach(struct scsi_device *sdev,
dev_err(dev, "%s: Could not initialize context %p\n", dev_err(dev, "%s: Could not initialize context %p\n",
__func__, ctx); __func__, ctx);
rc = -ENODEV; rc = -ENODEV;
goto err0; goto err1;
} }
ctxid = cxl_process_element(ctx); ctxid = cxl_process_element(ctx);
if (unlikely((ctxid > MAX_CONTEXT) || (ctxid < 0))) { if (unlikely((ctxid > MAX_CONTEXT) || (ctxid < 0))) {
dev_err(dev, "%s: ctxid (%d) invalid!\n", __func__, ctxid); dev_err(dev, "%s: ctxid (%d) invalid!\n", __func__, ctxid);
rc = -EPERM; rc = -EPERM;
goto err1; goto err2;
} }
file = cxl_get_fd(ctx, &cfg->cxl_fops, &fd); file = cxl_get_fd(ctx, &cfg->cxl_fops, &fd);
if (unlikely(fd < 0)) { if (unlikely(fd < 0)) {
rc = -ENODEV; rc = -ENODEV;
dev_err(dev, "%s: Could not get file descriptor\n", __func__); dev_err(dev, "%s: Could not get file descriptor\n", __func__);
goto err1; goto err2;
} }
/* Translate read/write O_* flags from fcntl.h to AFU permission bits */ /* Translate read/write O_* flags from fcntl.h to AFU permission bits */
...@@ -1335,7 +1344,7 @@ static int cxlflash_disk_attach(struct scsi_device *sdev, ...@@ -1335,7 +1344,7 @@ static int cxlflash_disk_attach(struct scsi_device *sdev,
if (unlikely(!ctxi)) { if (unlikely(!ctxi)) {
dev_err(dev, "%s: Failed to create context! (%d)\n", dev_err(dev, "%s: Failed to create context! (%d)\n",
__func__, ctxid); __func__, ctxid);
goto err2; goto err3;
} }
work = &ctxi->work; work = &ctxi->work;
...@@ -1346,13 +1355,13 @@ static int cxlflash_disk_attach(struct scsi_device *sdev, ...@@ -1346,13 +1355,13 @@ static int cxlflash_disk_attach(struct scsi_device *sdev,
if (unlikely(rc)) { if (unlikely(rc)) {
dev_dbg(dev, "%s: Could not start context rc=%d\n", dev_dbg(dev, "%s: Could not start context rc=%d\n",
__func__, rc); __func__, rc);
goto err3; goto err4;
} }
rc = afu_attach(cfg, ctxi); rc = afu_attach(cfg, ctxi);
if (unlikely(rc)) { if (unlikely(rc)) {
dev_err(dev, "%s: Could not attach AFU rc %d\n", __func__, rc); dev_err(dev, "%s: Could not attach AFU rc %d\n", __func__, rc);
goto err4; goto err5;
} }
/* /*
...@@ -1388,13 +1397,13 @@ static int cxlflash_disk_attach(struct scsi_device *sdev, ...@@ -1388,13 +1397,13 @@ static int cxlflash_disk_attach(struct scsi_device *sdev,
__func__, ctxid, fd, attach->block_size, rc, attach->last_lba); __func__, ctxid, fd, attach->block_size, rc, attach->last_lba);
return rc; return rc;
err4: err5:
cxl_stop_context(ctx); cxl_stop_context(ctx);
err3: err4:
put_context(ctxi); put_context(ctxi);
destroy_context(cfg, ctxi); destroy_context(cfg, ctxi);
ctxi = NULL; ctxi = NULL;
err2: err3:
/* /*
* Here, we're overriding the fops with a dummy all-NULL fops because * Here, we're overriding the fops with a dummy all-NULL fops because
* fput() calls the release fop, which will cause us to mistakenly * fput() calls the release fop, which will cause us to mistakenly
...@@ -1406,10 +1415,12 @@ static int cxlflash_disk_attach(struct scsi_device *sdev, ...@@ -1406,10 +1415,12 @@ static int cxlflash_disk_attach(struct scsi_device *sdev,
fput(file); fput(file);
put_unused_fd(fd); put_unused_fd(fd);
fd = -1; fd = -1;
err1: err2:
cxl_release_context(ctx); cxl_release_context(ctx);
err0: err1:
kfree(lun_access); kfree(lun_access);
err0:
scsi_device_put(sdev);
goto out; goto out;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment