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

Commit f161d4b4 authored by Nicholas Bellinger's avatar Nicholas Bellinger
Browse files

target: Fix PR_APTPL_BUF_LEN buffer size limitation



This patch addresses the original PR_APTPL_BUF_LEN = 8k limitiation
for write-out of PR APTPL metadata that Martin has recently been
running into.

It changes core_scsi3_update_and_write_aptpl() to use vzalloc'ed
memory instead of kzalloc, and increases the default hardcoded
length to 256k.

It also adds logic in core_scsi3_update_and_write_aptpl() to double
the original length upon core_scsi3_update_aptpl_buf() failure, and
retries until the vzalloc'ed buffer is large enough to accommodate
the outgoing APTPL metadata.

Reported-by: default avatarMartin Svec <martin.svec@zoner.cz>
Cc: stable@vger.kernel.org
Signed-off-by: default avatarNicholas Bellinger <nab@linux-iscsi.org>
parent 3fd7b60f
Loading
Loading
Loading
Loading
+13 −12
Original line number Original line Diff line number Diff line
@@ -1862,8 +1862,8 @@ static int core_scsi3_update_aptpl_buf(
		}
		}


		if ((len + strlen(tmp) >= pr_aptpl_buf_len)) {
		if ((len + strlen(tmp) >= pr_aptpl_buf_len)) {
			pr_err("Unable to update renaming"
			pr_err("Unable to update renaming APTPL metadata,"
				" APTPL metadata\n");
			       " reallocating larger buffer\n");
			ret = -EMSGSIZE;
			ret = -EMSGSIZE;
			goto out;
			goto out;
		}
		}
@@ -1880,8 +1880,8 @@ static int core_scsi3_update_aptpl_buf(
			lun->lun_sep->sep_rtpi, lun->unpacked_lun, reg_count);
			lun->lun_sep->sep_rtpi, lun->unpacked_lun, reg_count);


		if ((len + strlen(tmp) >= pr_aptpl_buf_len)) {
		if ((len + strlen(tmp) >= pr_aptpl_buf_len)) {
			pr_err("Unable to update renaming"
			pr_err("Unable to update renaming APTPL metadata,"
				" APTPL metadata\n");
			       " reallocating larger buffer\n");
			ret = -EMSGSIZE;
			ret = -EMSGSIZE;
			goto out;
			goto out;
		}
		}
@@ -1944,7 +1944,7 @@ static int __core_scsi3_write_aptpl_to_file(
static sense_reason_t core_scsi3_update_and_write_aptpl(struct se_device *dev, bool aptpl)
static sense_reason_t core_scsi3_update_and_write_aptpl(struct se_device *dev, bool aptpl)
{
{
	unsigned char *buf;
	unsigned char *buf;
	int rc;
	int rc, len = PR_APTPL_BUF_LEN;


	if (!aptpl) {
	if (!aptpl) {
		char *null_buf = "No Registrations or Reservations\n";
		char *null_buf = "No Registrations or Reservations\n";
@@ -1958,25 +1958,26 @@ static sense_reason_t core_scsi3_update_and_write_aptpl(struct se_device *dev, b


		return 0;
		return 0;
	}
	}

retry:
	buf = kzalloc(PR_APTPL_BUF_LEN, GFP_KERNEL);
	buf = vzalloc(len);
	if (!buf)
	if (!buf)
		return TCM_OUT_OF_RESOURCES;
		return TCM_OUT_OF_RESOURCES;


	rc = core_scsi3_update_aptpl_buf(dev, buf, PR_APTPL_BUF_LEN);
	rc = core_scsi3_update_aptpl_buf(dev, buf, len);
	if (rc < 0) {
	if (rc < 0) {
		kfree(buf);
		vfree(buf);
		return TCM_OUT_OF_RESOURCES;
		len *= 2;
		goto retry;
	}
	}


	rc = __core_scsi3_write_aptpl_to_file(dev, buf);
	rc = __core_scsi3_write_aptpl_to_file(dev, buf);
	if (rc != 0) {
	if (rc != 0) {
		pr_err("SPC-3 PR: Could not update APTPL\n");
		pr_err("SPC-3 PR: Could not update APTPL\n");
		kfree(buf);
		vfree(buf);
		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
	}
	}
	dev->t10_pr.pr_aptpl_active = 1;
	dev->t10_pr.pr_aptpl_active = 1;
	kfree(buf);
	vfree(buf);
	pr_debug("SPC-3 PR: Set APTPL Bit Activated\n");
	pr_debug("SPC-3 PR: Set APTPL Bit Activated\n");
	return 0;
	return 0;
}
}
+1 −1
Original line number Original line Diff line number Diff line
@@ -409,7 +409,7 @@ struct t10_reservation {
	/* Activate Persistence across Target Power Loss enabled
	/* Activate Persistence across Target Power Loss enabled
	 * for SCSI device */
	 * for SCSI device */
	int pr_aptpl_active;
	int pr_aptpl_active;
#define PR_APTPL_BUF_LEN			8192
#define PR_APTPL_BUF_LEN			262144
	u32 pr_generation;
	u32 pr_generation;
	spinlock_t registration_lock;
	spinlock_t registration_lock;
	spinlock_t aptpl_reg_lock;
	spinlock_t aptpl_reg_lock;