Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+23 −12
Original line number Original line Diff line number Diff line
@@ -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 @@ 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,
	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;
}
}