diff options
Diffstat (limited to 'sys/cam')
-rw-r--r-- | sys/cam/ctl/ctl.c | 82 | ||||
-rw-r--r-- | sys/cam/ctl/ctl_backend.c | 1 | ||||
-rw-r--r-- | sys/cam/ctl/ctl_cmd_table.c | 1 | ||||
-rw-r--r-- | sys/cam/ctl/ctl_error.c | 1 | ||||
-rw-r--r-- | sys/cam/ctl/ctl_frontend.c | 1 | ||||
-rw-r--r-- | sys/cam/ctl/ctl_frontend_internal.c | 1 | ||||
-rw-r--r-- | sys/cam/ctl/ctl_private.h | 3 |
7 files changed, 84 insertions, 6 deletions
diff --git a/sys/cam/ctl/ctl.c b/sys/cam/ctl/ctl.c index 06920bb0ca41..957ed8068bd1 100644 --- a/sys/cam/ctl/ctl.c +++ b/sys/cam/ctl/ctl.c @@ -959,6 +959,33 @@ ctl_init(void) softc->dev->si_drv1 = softc; + /* + * By default, return a "bad LUN" peripheral qualifier for unknown + * LUNs. The user can override this default using the tunable or + * sysctl. See the comment in ctl_inquiry_std() for more details. + */ + softc->inquiry_pq_no_lun = 1; + TUNABLE_INT_FETCH("kern.cam.ctl.inquiry_pq_no_lun", + &softc->inquiry_pq_no_lun); + sysctl_ctx_init(&softc->sysctl_ctx); + softc->sysctl_tree = SYSCTL_ADD_NODE(&softc->sysctl_ctx, + SYSCTL_STATIC_CHILDREN(_kern_cam), OID_AUTO, "ctl", + CTLFLAG_RD, 0, "CAM Target Layer"); + + if (softc->sysctl_tree == NULL) { + printf("%s: unable to allocate sysctl tree\n", __func__); + destroy_dev(softc->dev); + free(control_softc, M_DEVBUF); + control_softc = NULL; + return; + } + + SYSCTL_ADD_INT(&softc->sysctl_ctx, + SYSCTL_CHILDREN(softc->sysctl_tree), OID_AUTO, + "inquiry_pq_no_lun", CTLFLAG_RW, + &softc->inquiry_pq_no_lun, 0, + "Report no lun possible for invalid LUNs"); + mtx_init(&softc->ctl_lock, "CTL mutex", NULL, MTX_DEF); softc->open_count = 0; @@ -1150,6 +1177,11 @@ ctl_shutdown(void) destroy_dev(softc->dev); + sysctl_ctx_free(&softc->sysctl_ctx); + + free(control_softc, M_DEVBUF); + control_softc = NULL; + printf("ctl: CAM Target Layer unloaded\n"); } @@ -9369,15 +9401,55 @@ ctl_inquiry_std(struct ctl_scsiio *ctsio) memset(inq_ptr, 0, sizeof(*inq_ptr)); /* - * The control device is always connected. The disk device, on the - * other hand, may not be online all the time. If we don't have a - * LUN mapping, we'll just say it's offline. + * If we have a LUN configured, report it as connected. Otherwise, + * report that it is offline or no device is supported, depending + * on the value of inquiry_pq_no_lun. + * + * According to the spec (SPC-4 r34), the peripheral qualifier + * SID_QUAL_LU_OFFLINE (001b) is used in the following scenario: + * + * "A peripheral device having the specified peripheral device type + * is not connected to this logical unit. However, the device + * server is capable of supporting the specified peripheral device + * type on this logical unit." + * + * According to the same spec, the peripheral qualifier + * SID_QUAL_BAD_LU (011b) is used in this scenario: + * + * "The device server is not capable of supporting a peripheral + * device on this logical unit. For this peripheral qualifier the + * peripheral device type shall be set to 1Fh. All other peripheral + * device type values are reserved for this peripheral qualifier." + * + * Given the text, it would seem that we probably want to report that + * the LUN is offline here. There is no LUN connected, but we can + * support a LUN at the given LUN number. + * + * In the real world, though, it sounds like things are a little + * different: + * + * - Linux, when presented with a LUN with the offline peripheral + * qualifier, will create an sg driver instance for it. So when + * you attach it to CTL, you wind up with a ton of sg driver + * instances. (One for every LUN that Linux bothered to probe.) + * Linux does this despite the fact that it issues a REPORT LUNs + * to LUN 0 to get the inventory of supported LUNs. + * + * - There is other anecdotal evidence (from Emulex folks) about + * arrays that use the offline peripheral qualifier for LUNs that + * are on the "passive" path in an active/passive array. + * + * So the solution is provide a hopefully reasonable default + * (return bad/no LUN) and allow the user to change the behavior + * with a tunable/sysctl variable. */ if (lun != NULL) inq_ptr->device = (SID_QUAL_LU_CONNECTED << 5) | lun->be_lun->lun_type; - else + else if (ctl_softc->inquiry_pq_no_lun == 0) inq_ptr->device = (SID_QUAL_LU_OFFLINE << 5) | T_DIRECT; + else + inq_ptr->device = (SID_QUAL_BAD_LU << 5) | T_NODEVICE; /* RMB in byte 2 is 0 */ inq_ptr->version = SCSI_REV_SPC3; @@ -9491,8 +9563,6 @@ ctl_inquiry_std(struct ctl_scsiio *ctsio) break; } } - sprintf((char *)inq_ptr->vendor_specific1, "Copyright (C) 2004, COPAN " - "Systems, Inc. All Rights Reserved."); ctsio->scsi_status = SCSI_STATUS_OK; if (ctsio->kern_data_len > 0) { diff --git a/sys/cam/ctl/ctl_backend.c b/sys/cam/ctl/ctl_backend.c index cd0d6cc06e0e..5234c4a32076 100644 --- a/sys/cam/ctl/ctl_backend.c +++ b/sys/cam/ctl/ctl_backend.c @@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$"); #include <sys/mutex.h> #include <sys/condvar.h> #include <sys/queue.h> +#include <sys/sysctl.h> #include <cam/scsi/scsi_all.h> #include <cam/scsi/scsi_da.h> diff --git a/sys/cam/ctl/ctl_cmd_table.c b/sys/cam/ctl/ctl_cmd_table.c index acd8fecebcc1..b4a53d685c10 100644 --- a/sys/cam/ctl/ctl_cmd_table.c +++ b/sys/cam/ctl/ctl_cmd_table.c @@ -44,6 +44,7 @@ #include <sys/malloc.h> #include <sys/condvar.h> #include <sys/queue.h> +#include <sys/sysctl.h> #include <cam/scsi/scsi_all.h> #include <cam/scsi/scsi_da.h> diff --git a/sys/cam/ctl/ctl_error.c b/sys/cam/ctl/ctl_error.c index bd9321f4ade9..4425b2d608ad 100644 --- a/sys/cam/ctl/ctl_error.c +++ b/sys/cam/ctl/ctl_error.c @@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$"); #include <sys/condvar.h> #include <sys/stddef.h> #include <sys/ctype.h> +#include <sys/sysctl.h> #include <machine/stdarg.h> #include <cam/scsi/scsi_all.h> diff --git a/sys/cam/ctl/ctl_frontend.c b/sys/cam/ctl/ctl_frontend.c index ec0ec3256570..83042ee94ca0 100644 --- a/sys/cam/ctl/ctl_frontend.c +++ b/sys/cam/ctl/ctl_frontend.c @@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$"); #include <sys/condvar.h> #include <sys/endian.h> #include <sys/queue.h> +#include <sys/sysctl.h> #include <cam/scsi/scsi_all.h> #include <cam/scsi/scsi_da.h> diff --git a/sys/cam/ctl/ctl_frontend_internal.c b/sys/cam/ctl/ctl_frontend_internal.c index 6653ed1ab98d..5231564dce4d 100644 --- a/sys/cam/ctl/ctl_frontend_internal.c +++ b/sys/cam/ctl/ctl_frontend_internal.c @@ -60,6 +60,7 @@ __FBSDID("$FreeBSD$"); #include <sys/condvar.h> #include <sys/queue.h> #include <sys/sbuf.h> +#include <sys/sysctl.h> #include <cam/scsi/scsi_all.h> #include <cam/scsi/scsi_da.h> #include <cam/ctl/ctl_io.h> diff --git a/sys/cam/ctl/ctl_private.h b/sys/cam/ctl/ctl_private.h index 133e735d44c3..77611276aa79 100644 --- a/sys/cam/ctl/ctl_private.h +++ b/sys/cam/ctl/ctl_private.h @@ -421,6 +421,9 @@ struct ctl_softc { int num_luns; ctl_gen_flags flags; ctl_ha_mode ha_mode; + int inquiry_pq_no_lun; + struct sysctl_ctx_list sysctl_ctx; + struct sysctl_oid *sysctl_tree; struct ctl_ioctl_info ioctl_info; struct ctl_lun lun; struct ctl_io_pool *internal_pool; |