mirror of
https://github.com/torvalds/linux.git
synced 2024-12-04 01:51:34 +00:00
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: Matthew R. Ochs <mrochs@linux.vnet.ibm.com> Signed-off-by: Manoj N. Kumar <manoj@linux.vnet.ibm.com> Reviewed-by: Brian King <brking@linux.vnet.ibm.com> Reviewed-by: Tomas Henzl <thenzl@redhat.com> Signed-off-by: James Bottomley <JBottomley@Odin.com>
This commit is contained in:
parent
471a5a60aa
commit
22fe1ae80f
@ -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,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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 @@ out:
|
|||||||
__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 @@ err2:
|
|||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user