summaryrefslogtreecommitdiffstats
path: root/sys/cam/ctl/ctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/cam/ctl/ctl.c')
-rw-r--r--sys/cam/ctl/ctl.c61
1 files changed, 48 insertions, 13 deletions
diff --git a/sys/cam/ctl/ctl.c b/sys/cam/ctl/ctl.c
index b4354f4..b9ec2ad 100644
--- a/sys/cam/ctl/ctl.c
+++ b/sys/cam/ctl/ctl.c
@@ -435,7 +435,9 @@ static int ctl_inquiry_evpd_lbp(struct ctl_scsiio *ctsio, int alloc_len);
static int ctl_inquiry_evpd(struct ctl_scsiio *ctsio);
static int ctl_inquiry_std(struct ctl_scsiio *ctsio);
static int ctl_get_lba_len(union ctl_io *io, uint64_t *lba, uint64_t *len);
-static ctl_action ctl_extent_check(union ctl_io *io1, union ctl_io *io2);
+static ctl_action ctl_extent_check(union ctl_io *io1, union ctl_io *io2,
+ bool seq);
+static ctl_action ctl_extent_check_seq(union ctl_io *io1, union ctl_io *io2);
static ctl_action ctl_check_for_blockage(struct ctl_lun *lun,
union ctl_io *pending_io, union ctl_io *ooa_io);
static ctl_action ctl_check_ooa(struct ctl_lun *lun, union ctl_io *pending_io,
@@ -4592,6 +4594,17 @@ ctl_alloc_lun(struct ctl_softc *ctl_softc, struct ctl_lun *ctl_lun,
if (value != NULL && strcmp(value, "on") == 0)
lun->flags |= CTL_LUN_READONLY;
+ lun->serseq = CTL_LUN_SERSEQ_OFF;
+ if (be_lun->flags & CTL_LUN_FLAG_SERSEQ_READ)
+ lun->serseq = CTL_LUN_SERSEQ_READ;
+ value = ctl_get_opt(&be_lun->options, "serseq");
+ if (value != NULL && strcmp(value, "on") == 0)
+ lun->serseq = CTL_LUN_SERSEQ_ON;
+ else if (value != NULL && strcmp(value, "read") == 0)
+ lun->serseq = CTL_LUN_SERSEQ_READ;
+ else if (value != NULL && strcmp(value, "off") == 0)
+ lun->serseq = CTL_LUN_SERSEQ_OFF;
+
lun->ctl_softc = ctl_softc;
TAILQ_INIT(&lun->ooa_queue);
TAILQ_INIT(&lun->blocked_queue);
@@ -10754,15 +10767,15 @@ ctl_get_lba_len(union ctl_io *io, uint64_t *lba, uint64_t *len)
}
static ctl_action
-ctl_extent_check_lba(uint64_t lba1, uint64_t len1, uint64_t lba2, uint64_t len2)
+ctl_extent_check_lba(uint64_t lba1, uint64_t len1, uint64_t lba2, uint64_t len2,
+ bool seq)
{
uint64_t endlba1, endlba2;
- endlba1 = lba1 + len1 - 1;
+ endlba1 = lba1 + len1 - (seq ? 0 : 1);
endlba2 = lba2 + len2 - 1;
- if ((endlba1 < lba2)
- || (endlba2 < lba1))
+ if ((endlba1 < lba2) || (endlba2 < lba1))
return (CTL_ACTION_PASS);
else
return (CTL_ACTION_BLOCK);
@@ -10801,23 +10814,39 @@ ctl_extent_check_unmap(union ctl_io *io, uint64_t lba2, uint64_t len2)
}
static ctl_action
-ctl_extent_check(union ctl_io *io1, union ctl_io *io2)
+ctl_extent_check(union ctl_io *io1, union ctl_io *io2, bool seq)
{
uint64_t lba1, lba2;
uint64_t len1, len2;
int retval;
- if (ctl_get_lba_len(io1, &lba1, &len1) != 0)
+ if (ctl_get_lba_len(io2, &lba2, &len2) != 0)
return (CTL_ACTION_ERROR);
- retval = ctl_extent_check_unmap(io2, lba1, len1);
+ retval = ctl_extent_check_unmap(io1, lba2, len2);
if (retval != CTL_ACTION_ERROR)
return (retval);
+ if (ctl_get_lba_len(io1, &lba1, &len1) != 0)
+ return (CTL_ACTION_ERROR);
+
+ return (ctl_extent_check_lba(lba1, len1, lba2, len2, seq));
+}
+
+static ctl_action
+ctl_extent_check_seq(union ctl_io *io1, union ctl_io *io2)
+{
+ uint64_t lba1, lba2;
+ uint64_t len1, len2;
+
+ if (ctl_get_lba_len(io1, &lba1, &len1) != 0)
+ return (CTL_ACTION_ERROR);
if (ctl_get_lba_len(io2, &lba2, &len2) != 0)
return (CTL_ACTION_ERROR);
- return (ctl_extent_check_lba(lba1, len1, lba2, len2));
+ if (lba1 + len1 == lba2)
+ return (CTL_ACTION_BLOCK);
+ return (CTL_ACTION_PASS);
}
static ctl_action
@@ -10906,12 +10935,18 @@ ctl_check_for_blockage(struct ctl_lun *lun, union ctl_io *pending_io,
case CTL_SER_BLOCK:
return (CTL_ACTION_BLOCK);
case CTL_SER_EXTENT:
- return (ctl_extent_check(pending_io, ooa_io));
+ return (ctl_extent_check(ooa_io, pending_io,
+ (lun->serseq == CTL_LUN_SERSEQ_ON)));
case CTL_SER_EXTENTOPT:
if ((lun->mode_pages.control_page[CTL_PAGE_CURRENT].queue_flags
& SCP_QUEUE_ALG_MASK) != SCP_QUEUE_ALG_UNRESTRICTED)
- return (ctl_extent_check(pending_io, ooa_io));
- /* FALLTHROUGH */
+ return (ctl_extent_check(ooa_io, pending_io,
+ (lun->serseq == CTL_LUN_SERSEQ_ON)));
+ return (CTL_ACTION_PASS);
+ case CTL_SER_EXTENTSEQ:
+ if (lun->serseq != CTL_LUN_SERSEQ_OFF)
+ return (ctl_extent_check_seq(ooa_io, pending_io));
+ return (CTL_ACTION_PASS);
case CTL_SER_PASS:
return (CTL_ACTION_PASS);
case CTL_SER_BLOCKOPT:
@@ -12442,7 +12477,7 @@ ctl_cmd_pattern_match(struct ctl_scsiio *ctsio, struct ctl_error_desc *desc)
return (CTL_LUN_PAT_NONE);
action = ctl_extent_check_lba(lba1, len1, desc->lba_range.lba,
- desc->lba_range.len);
+ desc->lba_range.len, FALSE);
/*
* A "pass" means that the LBA ranges don't overlap, so
* this doesn't match the user's range criteria.
OpenPOWER on IntegriCloud