Commit 12c5ac27 authored by Nicholas Bellinger's avatar Nicholas Bellinger Committed by Greg Kroah-Hartman

target: Fix PR_APTPL_BUF_LEN buffer size limitation

commit f161d4b4 upstream.

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>
Signed-off-by: default avatarNicholas Bellinger <nab@linux-iscsi.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent a88c8685
...@@ -1874,8 +1874,8 @@ static int core_scsi3_update_aptpl_buf( ...@@ -1874,8 +1874,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;
} }
...@@ -1892,8 +1892,8 @@ static int core_scsi3_update_aptpl_buf( ...@@ -1892,8 +1892,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;
} }
...@@ -1956,7 +1956,7 @@ static int __core_scsi3_write_aptpl_to_file( ...@@ -1956,7 +1956,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";
...@@ -1970,25 +1970,26 @@ static sense_reason_t core_scsi3_update_and_write_aptpl(struct se_device *dev, b ...@@ -1970,25 +1970,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;
} }
......
...@@ -407,7 +407,7 @@ struct t10_reservation { ...@@ -407,7 +407,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;
......
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