2005-01-05 22:34:37 +00:00
|
|
|
/*-
|
1998-09-15 06:36:34 +00:00
|
|
|
* Implementation of SCSI Direct Access Peripheral driver for CAM.
|
|
|
|
*
|
|
|
|
* Copyright (c) 1997 Justin T. Gibbs.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions, and the following disclaimer,
|
|
|
|
* without modification, immediately at the beginning of the file.
|
|
|
|
* 2. The name of the author may not be used to endorse or promote products
|
|
|
|
* derived from this software without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
|
|
|
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
2003-06-10 18:14:05 +00:00
|
|
|
#include <sys/cdefs.h>
|
|
|
|
__FBSDID("$FreeBSD$");
|
|
|
|
|
1998-09-15 06:36:34 +00:00
|
|
|
#include <sys/param.h>
|
2000-05-21 23:57:52 +00:00
|
|
|
|
|
|
|
#ifdef _KERNEL
|
1998-09-15 06:36:34 +00:00
|
|
|
#include <sys/systm.h>
|
|
|
|
#include <sys/kernel.h>
|
2000-05-05 09:59:14 +00:00
|
|
|
#include <sys/bio.h>
|
2001-07-09 19:18:00 +00:00
|
|
|
#include <sys/sysctl.h>
|
2003-09-03 12:31:03 +00:00
|
|
|
#include <sys/taskqueue.h>
|
2007-04-15 08:49:19 +00:00
|
|
|
#include <sys/lock.h>
|
|
|
|
#include <sys/mutex.h>
|
1999-10-01 09:34:10 +00:00
|
|
|
#include <sys/conf.h>
|
2007-04-23 18:01:44 +00:00
|
|
|
#include <sys/devicestat.h>
|
1999-08-21 06:24:40 +00:00
|
|
|
#include <sys/eventhandler.h>
|
1998-09-15 06:36:34 +00:00
|
|
|
#include <sys/malloc.h>
|
1999-08-09 10:35:05 +00:00
|
|
|
#include <sys/cons.h>
|
2013-04-26 16:17:04 +00:00
|
|
|
#include <sys/endian.h>
|
2013-06-15 12:46:38 +00:00
|
|
|
#include <sys/proc.h>
|
Plumb device physical path reporting from CAM devices, through GEOM and
DEVFS, and make it accessible via the diskinfo utility.
Extend GEOM's generic attribute query mechanism into generic disk consumers.
sys/geom/geom_disk.c:
sys/geom/geom_disk.h:
sys/cam/scsi/scsi_da.c:
sys/cam/ata/ata_da.c:
- Allow disk providers to implement a new method which can override
the default BIO_GETATTR response, d_getattr(struct bio *). This
function returns -1 if not handled, otherwise it returns 0 or an
errno to be passed to g_io_deliver().
sys/cam/scsi/scsi_da.c:
sys/cam/ata/ata_da.c:
- Don't copy the serial number to dp->d_ident anymore, as the CAM XPT
is now responsible for returning this information via
d_getattr()->(a)dagetattr()->xpt_getatr().
sys/geom/geom_dev.c:
- Implement a new ioctl, DIOCGPHYSPATH, which returns the GEOM
attribute "GEOM::physpath", if possible. If the attribute request
returns a zero-length string, ENOENT is returned.
usr.sbin/diskinfo/diskinfo.c:
- If the DIOCGPHYSPATH ioctl is successful, report physical path
data when diskinfo is executed with the '-v' option.
Submitted by: will
Reviewed by: gibbs
Sponsored by: Spectra Logic Corporation
Add generic attribute change notification support to GEOM.
sys/sys/geom/geom.h:
Add a new attrchanged method field to both g_class
and g_geom.
sys/sys/geom/geom.h:
sys/geom/geom_event.c:
- Provide the g_attr_changed() function that providers
can use to advertise attribute changes.
- Perform delivery of attribute change notifications
from a thread context via the standard GEOM event
mechanism.
sys/geom/geom_subr.c:
Inherit the attrchanged method from class to geom (class instance).
sys/geom/geom_disk.c:
Provide disk_attr_changed() to provide g_attr_changed() access
to consumers of the disk API.
sys/cam/scsi/scsi_pass.c:
sys/cam/scsi/scsi_da.c:
sys/geom/geom_dev.c:
sys/geom/geom_disk.c:
Use attribute changed events to track updates to physical path
information.
sys/cam/scsi/scsi_da.c:
Add AC_ADVINFO_CHANGED to the registered asynchronous CAM
events for this driver. When this event occurs, and
the updated buffer type references our physical path
attribute, emit a GEOM attribute changed event via the
disk_attr_changed() API.
sys/cam/scsi/scsi_pass.c:
Add AC_ADVINFO_CHANGED to the registered asynchronous CAM
events for this driver. When this event occurs, update
the physical patch devfs alias for this pass instance.
Submitted by: gibbs
Sponsored by: Spectra Logic Corporation
2011-06-14 17:10:32 +00:00
|
|
|
#include <geom/geom.h>
|
2003-04-01 15:06:26 +00:00
|
|
|
#include <geom/geom_disk.h>
|
2007-04-23 18:01:44 +00:00
|
|
|
#endif /* _KERNEL */
|
2003-04-01 15:06:26 +00:00
|
|
|
|
2000-05-21 23:57:52 +00:00
|
|
|
#ifndef _KERNEL
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#endif /* _KERNEL */
|
|
|
|
|
1998-09-15 06:36:34 +00:00
|
|
|
#include <cam/cam.h>
|
|
|
|
#include <cam/cam_ccb.h>
|
|
|
|
#include <cam/cam_periph.h>
|
|
|
|
#include <cam/cam_xpt_periph.h>
|
2007-04-15 08:49:19 +00:00
|
|
|
#include <cam/cam_sim.h>
|
1998-09-15 06:36:34 +00:00
|
|
|
|
|
|
|
#include <cam/scsi/scsi_message.h>
|
|
|
|
|
2000-05-21 23:57:52 +00:00
|
|
|
#ifndef _KERNEL
|
|
|
|
#include <cam/scsi/scsi_da.h>
|
|
|
|
#endif /* !_KERNEL */
|
|
|
|
|
|
|
|
#ifdef _KERNEL
|
1998-09-15 06:36:34 +00:00
|
|
|
typedef enum {
|
2013-04-26 16:17:04 +00:00
|
|
|
DA_STATE_PROBE_RC,
|
|
|
|
DA_STATE_PROBE_RC16,
|
|
|
|
DA_STATE_PROBE_LBP,
|
|
|
|
DA_STATE_PROBE_BLK_LIMITS,
|
2013-04-26 16:31:03 +00:00
|
|
|
DA_STATE_PROBE_BDC,
|
2013-04-26 16:17:04 +00:00
|
|
|
DA_STATE_PROBE_ATA,
|
1998-09-15 06:36:34 +00:00
|
|
|
DA_STATE_NORMAL
|
|
|
|
} da_state;
|
|
|
|
|
|
|
|
typedef enum {
|
|
|
|
DA_FLAG_PACK_INVALID = 0x001,
|
|
|
|
DA_FLAG_NEW_PACK = 0x002,
|
|
|
|
DA_FLAG_PACK_LOCKED = 0x004,
|
|
|
|
DA_FLAG_PACK_REMOVABLE = 0x008,
|
|
|
|
DA_FLAG_NEED_OTAG = 0x020,
|
2013-10-24 14:05:44 +00:00
|
|
|
DA_FLAG_WAS_OTAG = 0x040,
|
1998-09-15 06:36:34 +00:00
|
|
|
DA_FLAG_RETRY_UA = 0x080,
|
2003-10-08 07:12:30 +00:00
|
|
|
DA_FLAG_OPEN = 0x100,
|
2011-12-23 19:12:02 +00:00
|
|
|
DA_FLAG_SCTX_INIT = 0x200,
|
2012-04-12 12:58:14 +00:00
|
|
|
DA_FLAG_CAN_RC16 = 0x400,
|
2013-07-27 22:44:55 +00:00
|
|
|
DA_FLAG_PROBED = 0x800,
|
2014-04-30 17:38:26 +00:00
|
|
|
DA_FLAG_DIRTY = 0x1000,
|
|
|
|
DA_FLAG_ANNOUNCED = 0x2000
|
1998-09-15 06:36:34 +00:00
|
|
|
} da_flags;
|
|
|
|
|
1998-10-08 05:46:38 +00:00
|
|
|
typedef enum {
|
|
|
|
DA_Q_NONE = 0x00,
|
1998-12-02 17:35:28 +00:00
|
|
|
DA_Q_NO_SYNC_CACHE = 0x01,
|
2003-08-22 16:35:53 +00:00
|
|
|
DA_Q_NO_6_BYTE = 0x02,
|
2011-12-23 00:10:17 +00:00
|
|
|
DA_Q_NO_PREVENT = 0x04,
|
2013-07-30 13:00:09 +00:00
|
|
|
DA_Q_4K = 0x08,
|
2014-04-23 19:50:35 +00:00
|
|
|
DA_Q_NO_RC16 = 0x10,
|
2015-02-02 20:23:05 +00:00
|
|
|
DA_Q_NO_UNMAP = 0x20,
|
|
|
|
DA_Q_RETRY_BUSY = 0x40
|
1998-10-08 05:46:38 +00:00
|
|
|
} da_quirks;
|
|
|
|
|
2013-05-18 23:36:21 +00:00
|
|
|
#define DA_Q_BIT_STRING \
|
|
|
|
"\020" \
|
|
|
|
"\001NO_SYNC_CACHE" \
|
|
|
|
"\002NO_6_BYTE" \
|
|
|
|
"\003NO_PREVENT" \
|
2013-07-30 13:00:09 +00:00
|
|
|
"\0044K" \
|
2015-02-02 20:23:05 +00:00
|
|
|
"\005NO_RC16" \
|
|
|
|
"\006NO_UNMAP" \
|
|
|
|
"\007RETRY_BUSY"
|
2013-05-18 23:36:21 +00:00
|
|
|
|
1998-09-15 06:36:34 +00:00
|
|
|
typedef enum {
|
2013-04-26 16:17:04 +00:00
|
|
|
DA_CCB_PROBE_RC = 0x01,
|
|
|
|
DA_CCB_PROBE_RC16 = 0x02,
|
|
|
|
DA_CCB_PROBE_LBP = 0x03,
|
|
|
|
DA_CCB_PROBE_BLK_LIMITS = 0x04,
|
2013-04-26 16:31:03 +00:00
|
|
|
DA_CCB_PROBE_BDC = 0x05,
|
|
|
|
DA_CCB_PROBE_ATA = 0x06,
|
|
|
|
DA_CCB_BUFFER_IO = 0x07,
|
|
|
|
DA_CCB_DUMP = 0x0A,
|
|
|
|
DA_CCB_DELETE = 0x0B,
|
|
|
|
DA_CCB_TUR = 0x0C,
|
1998-09-15 06:36:34 +00:00
|
|
|
DA_CCB_TYPE_MASK = 0x0F,
|
|
|
|
DA_CCB_RETRY_UA = 0x10
|
|
|
|
} da_ccb_state;
|
|
|
|
|
2013-04-26 16:17:04 +00:00
|
|
|
/*
|
|
|
|
* Order here is important for method choice
|
|
|
|
*
|
|
|
|
* We prefer ATA_TRIM as tests run against a Sandforce 2281 SSD attached to
|
|
|
|
* LSI 2008 (mps) controller (FW: v12, Drv: v14) resulted 20% quicker deletes
|
|
|
|
* using ATA_TRIM than the corresponding UNMAP results for a real world mysql
|
|
|
|
* import taking 5mins.
|
|
|
|
*
|
|
|
|
*/
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
typedef enum {
|
|
|
|
DA_DELETE_NONE,
|
|
|
|
DA_DELETE_DISABLE,
|
2013-04-26 16:17:04 +00:00
|
|
|
DA_DELETE_ATA_TRIM,
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
DA_DELETE_UNMAP,
|
2013-04-26 16:17:04 +00:00
|
|
|
DA_DELETE_WS16,
|
|
|
|
DA_DELETE_WS10,
|
|
|
|
DA_DELETE_ZERO,
|
2013-05-02 15:03:30 +00:00
|
|
|
DA_DELETE_MIN = DA_DELETE_ATA_TRIM,
|
2013-04-26 16:17:04 +00:00
|
|
|
DA_DELETE_MAX = DA_DELETE_ZERO
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
} da_delete_methods;
|
|
|
|
|
2013-07-12 00:50:25 +00:00
|
|
|
typedef void da_delete_func_t (struct cam_periph *periph, union ccb *ccb,
|
|
|
|
struct bio *bp);
|
|
|
|
static da_delete_func_t da_delete_trim;
|
|
|
|
static da_delete_func_t da_delete_unmap;
|
|
|
|
static da_delete_func_t da_delete_ws;
|
|
|
|
|
2013-07-12 23:20:11 +00:00
|
|
|
static const void * da_delete_functions[] = {
|
2013-07-12 00:50:25 +00:00
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
da_delete_trim,
|
|
|
|
da_delete_unmap,
|
|
|
|
da_delete_ws,
|
|
|
|
da_delete_ws,
|
|
|
|
da_delete_ws
|
|
|
|
};
|
|
|
|
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
static const char *da_delete_method_names[] =
|
2013-05-02 15:03:30 +00:00
|
|
|
{ "NONE", "DISABLE", "ATA_TRIM", "UNMAP", "WS16", "WS10", "ZERO" };
|
2013-04-26 16:17:04 +00:00
|
|
|
static const char *da_delete_method_desc[] =
|
2013-05-02 15:03:30 +00:00
|
|
|
{ "NONE", "DISABLED", "ATA TRIM", "UNMAP", "WRITE SAME(16) with UNMAP",
|
2013-04-26 16:17:04 +00:00
|
|
|
"WRITE SAME(10) with UNMAP", "ZERO" };
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
|
1998-09-15 06:36:34 +00:00
|
|
|
/* Offsets into our private area for storing information */
|
|
|
|
#define ccb_state ppriv_field0
|
|
|
|
#define ccb_bp ppriv_ptr1
|
|
|
|
|
|
|
|
struct disk_params {
|
|
|
|
u_int8_t heads;
|
Add support to CAM for devices with more than 2^32 blocks. (2TB if you're
using 512 byte blocks).
cam_ccb.h: Bump up volume_size and cylinders in ccb_calc_geometry to
64 bits and 32 bits respectively, so we can hold larger
device sizes. cylinders would overflow at about 500GB.
Bump CAM_VERSION for this change. Note that this will
require a recompile of all applications that talk to the
pass(4) driver.
scsi_all.c: Add descriptions for READ/WRITE(16), update READ/WRITE(12)
descriptions, add descriptions for SERVICE ACTION IN/OUT.
Add a new function, scsi_read_capacity_16(), that issues
the read capacity service action. (Necessary for arrays
larger than 2^32 sectors.) Update scsi_read_write() to use
a 64 bit LBA and issue READ(16) or WRITE(16) if necessary.
NOTE the API change. This should be largely transparnet
to most userland applications at compile time, but will
break binary compatibility. The CAM_VERSION bump, above,
also serves the purpose of forcing a recompile for any
applications that talk to CAM.
scsi_all.h: Add 16 byte READ/WRITE structures, structures for 16 byte
READ CAPACITY/SERVICE ACTION IN. Add scsi_u64to8b() and
scsi_8btou64.
scsi_da.c: The da(4) driver probe now has two stages for devices
larger than 2TB. If a standard READ CAPACITY(10) returns
0xffffffff, we issue the 16 byte version of read capacity
to determine the true array capacity. We also do the same
thing in daopen() -- use the 16 byte read capacity if the
device is large enough.
The sysctl/loader code has also been updated to accept
16 bytes as a minimum command size.
2003-04-30 00:35:22 +00:00
|
|
|
u_int32_t cylinders;
|
1998-09-15 06:36:34 +00:00
|
|
|
u_int8_t secs_per_track;
|
|
|
|
u_int32_t secsize; /* Number of bytes/sector */
|
Add support to CAM for devices with more than 2^32 blocks. (2TB if you're
using 512 byte blocks).
cam_ccb.h: Bump up volume_size and cylinders in ccb_calc_geometry to
64 bits and 32 bits respectively, so we can hold larger
device sizes. cylinders would overflow at about 500GB.
Bump CAM_VERSION for this change. Note that this will
require a recompile of all applications that talk to the
pass(4) driver.
scsi_all.c: Add descriptions for READ/WRITE(16), update READ/WRITE(12)
descriptions, add descriptions for SERVICE ACTION IN/OUT.
Add a new function, scsi_read_capacity_16(), that issues
the read capacity service action. (Necessary for arrays
larger than 2^32 sectors.) Update scsi_read_write() to use
a 64 bit LBA and issue READ(16) or WRITE(16) if necessary.
NOTE the API change. This should be largely transparnet
to most userland applications at compile time, but will
break binary compatibility. The CAM_VERSION bump, above,
also serves the purpose of forcing a recompile for any
applications that talk to CAM.
scsi_all.h: Add 16 byte READ/WRITE structures, structures for 16 byte
READ CAPACITY/SERVICE ACTION IN. Add scsi_u64to8b() and
scsi_8btou64.
scsi_da.c: The da(4) driver probe now has two stages for devices
larger than 2TB. If a standard READ CAPACITY(10) returns
0xffffffff, we issue the 16 byte version of read capacity
to determine the true array capacity. We also do the same
thing in daopen() -- use the 16 byte read capacity if the
device is large enough.
The sysctl/loader code has also been updated to accept
16 bytes as a minimum command size.
2003-04-30 00:35:22 +00:00
|
|
|
u_int64_t sectors; /* total number sectors */
|
2011-12-23 00:10:17 +00:00
|
|
|
u_int stripesize;
|
|
|
|
u_int stripeoffset;
|
1998-09-15 06:36:34 +00:00
|
|
|
};
|
|
|
|
|
2013-04-26 16:17:04 +00:00
|
|
|
#define UNMAP_RANGE_MAX 0xffffffff
|
|
|
|
#define UNMAP_HEAD_SIZE 8
|
|
|
|
#define UNMAP_RANGE_SIZE 16
|
|
|
|
#define UNMAP_MAX_RANGES 2048 /* Protocol Max is 4095 */
|
|
|
|
#define UNMAP_BUF_SIZE ((UNMAP_MAX_RANGES * UNMAP_RANGE_SIZE) + \
|
|
|
|
UNMAP_HEAD_SIZE)
|
|
|
|
|
|
|
|
#define WS10_MAX_BLKS 0xffff
|
|
|
|
#define WS16_MAX_BLKS 0xffffffff
|
|
|
|
#define ATA_TRIM_MAX_RANGES ((UNMAP_BUF_SIZE / \
|
|
|
|
(ATA_DSM_RANGE_SIZE * ATA_DSM_BLK_SIZE)) * ATA_DSM_BLK_SIZE)
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
|
1998-09-15 06:36:34 +00:00
|
|
|
struct da_softc {
|
2000-04-15 05:54:02 +00:00
|
|
|
struct bio_queue_head bio_queue;
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
struct bio_queue_head delete_queue;
|
|
|
|
struct bio_queue_head delete_run_queue;
|
2000-05-26 02:09:24 +00:00
|
|
|
LIST_HEAD(, ccb_hdr) pending_ccbs;
|
2013-10-24 14:05:44 +00:00
|
|
|
int tur; /* TEST UNIT READY should be sent */
|
|
|
|
int refcount; /* Active xpt_action() calls */
|
1998-09-15 06:36:34 +00:00
|
|
|
da_state state;
|
|
|
|
da_flags flags;
|
1998-10-08 05:46:38 +00:00
|
|
|
da_quirks quirks;
|
2013-03-29 22:58:15 +00:00
|
|
|
int sort_io_queue;
|
1998-12-02 17:35:28 +00:00
|
|
|
int minimum_cmd_size;
|
Fix a race condition in CAM peripheral free handling, locking
in the CAM XPT bus traversal code, and a number of other periph level
issues.
cam_periph.h,
cam_periph.c: Modify cam_periph_acquire() to test the CAM_PERIPH_INVALID
flag prior to allowing a reference count to be gained
on a peripheral. Callers of this function will receive
CAM_REQ_CMP_ERR status in the situation of attempting to
reference an invalidated periph. This guarantees that
a peripheral scheduled for a deferred free will not
be accessed during its wait for destruction.
Panic during attempts to drop a reference count on
a peripheral that already has a zero reference count.
In cam_periph_list(), use a local sbuf with SBUF_FIXEDLEN
set so that mallocs do not occur while the xpt topology
lock is held, regardless of the allocation policy of the
passed in sbuf.
Add a new routine, cam_periph_release_locked_buses(),
that can be called when the caller already holds
the CAM topology lock.
Add some extra debugging for duplicate peripheral
allocations in cam_periph_alloc().
Treat CAM_DEV_NOT_THERE much the same as a selection
timeout (AC_LOST_DEVICE is emitted), but forgo retries.
cam_xpt.c: Revamp the way the EDT traversal code does locking
and reference counting. This was broken, since it
assumed that the EDT would not change during
traversal, but that assumption is no longer valid.
So, to prevent devices from going away while we
traverse the EDT, make sure we properly lock
everything and hold references on devices that
we are using.
The two peripheral driver traversal routines should
be examined. xptpdperiphtraverse() holds the
topology lock for the entire time it runs.
xptperiphtraverse() is now locked properly, but
only holds the topology lock while it is traversing
the list, and not while the traversal function is
running.
The bus locking code in xptbustraverse() should
also be revisited at a later time, since it is
complex and should probably be simplified.
scsi_da.c: Pay attention to the return value from cam_periph_acquire().
Return 0 always from daclose() even if the disk is now gone.
Add some rudimentary error injection support.
scsi_sg.c: Fix reference counting in the sg(4) driver.
The sg driver was calling cam_periph_release() on close,
but never called cam_periph_acquire() (which increments
the reference count) on open.
The periph code correctly complained that the sg(4)
driver was trying to decrement the refcount when it
was already 0.
Sponsored by: Spectra Logic
MFC after: 2 weeks
2012-01-12 00:41:48 +00:00
|
|
|
int error_inject;
|
2013-04-26 16:17:04 +00:00
|
|
|
int trim_max_ranges;
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
int delete_running;
|
2013-04-26 16:17:04 +00:00
|
|
|
int delete_available; /* Delete methods possibly available */
|
2014-04-30 19:44:31 +00:00
|
|
|
u_int maxio;
|
2013-04-26 16:17:04 +00:00
|
|
|
uint32_t unmap_max_ranges;
|
2014-01-22 22:19:53 +00:00
|
|
|
uint32_t unmap_max_lba; /* Max LBAs in UNMAP req */
|
2013-04-26 16:17:04 +00:00
|
|
|
uint64_t ws_max_blks;
|
2015-10-11 18:26:06 +00:00
|
|
|
da_delete_methods delete_method_pref;
|
2013-04-26 16:17:04 +00:00
|
|
|
da_delete_methods delete_method;
|
2013-07-12 00:50:25 +00:00
|
|
|
da_delete_func_t *delete_func;
|
1998-09-15 06:36:34 +00:00
|
|
|
struct disk_params params;
|
2004-02-18 21:36:53 +00:00
|
|
|
struct disk *disk;
|
1998-09-15 06:36:34 +00:00
|
|
|
union ccb saved_ccb;
|
Move dynamic sysctl(8) variable creation for the cd(4) and da(4) drivers
out of cdregister() and daregister(), which are run from interrupt context.
The sysctl code does blocking mallocs (M_WAITOK), which causes problems
if malloc(9) actually needs to sleep.
The eventual fix for this issue will involve moving the CAM probe process
inside a kernel thread. For now, though, I have fixed the issue by moving
dynamic sysctl variable creation for these two drivers to a task queue
running in a kernel thread.
The existing task queues (taskqueue_swi and taskqueue_swi_giant) run in
software interrupt handlers, which wouldn't fix the problem at hand. So I
have created a new task queue, taskqueue_thread, that runs inside a kernel
thread. (It also runs outside of Giant -- clients must explicitly acquire
and release Giant in their taskqueue functions.)
scsi_cd.c: Remove sysctl variable creation code from cdregister(), and
move it to a new function, cdsysctlinit(). Queue
cdsysctlinit() to the taskqueue_thread taskqueue once we
have fully registered the cd(4) driver instance.
scsi_da.c: Remove sysctl variable creation code from daregister(), and
move it to move it to a new function, dasysctlinit().
Queue dasysctlinit() to the taskqueue_thread taskqueue once
we have fully registered the da(4) instance.
taskqueue.h: Declare the new taskqueue_thread taskqueue, update some
comments.
subr_taskqueue.c:
Create the new kernel thread taskqueue. This taskqueue
runs outside of Giant, so any functions queued to it would
need to explicitly acquire/release Giant if they need it.
cd.4: Update the cd(4) man page to talk about the minimum command
size sysctl/loader tunable. Also note that the changer
variables are available as loader tunables as well.
da.4: Update the da(4) man page to cover the retry_count,
default_timeout and minimum_cmd_size sysctl variables/loader
tunables. Remove references to /dev/r???, they aren't used
any longer.
cd.9: Update the cd(9) man page to describe the CD_Q_10_BYTE_ONLY
quirk.
taskqueue.9: Update the taskqueue(9) man page to describe the new thread
task queue, and the taskqueue_swi_giant queue.
MFC after: 3 days
2003-09-03 04:46:28 +00:00
|
|
|
struct task sysctl_task;
|
Fix ATAPI/USB/Firewire CDROM drive handling in cd(4) and hopefully fix
a number of related problems along the way.
- Automatically detect CDROM drives that can't handle 6 byte mode
sense and mode select, and adjust our command size accordingly.
We have to handle this in the cd(4) driver (where the buffers are
allocated), since the parameter list length is different for the
6 and 10 byte mode sense commands.
- Remove MODE_SENSE and MODE_SELECT translation removed in ATAPICAM
and in the umass(4) driver, since there's no way for that to work
properly.
- Add a quirk entry for CDROM drives that just hang when they get a 6
byte mode sense or mode select. The reason for the quirk must be
documented in a PR, and all quirks must be approved by
ken@FreeBSD.org. This is to make sure that we fully understand why
each quirk is needed. Once the CAM_NEW_TRAN_CODE is finished, we
should be able to remove any such quirks, since we'll know what
protocol the drive speaks (SCSI, ATAPI, etc.) and therefore whether
we should use 6 or 10 byte mode sense/select commands.
- Change the way the da(4) handles the no_6_byte sysctl. There is
now a per-drive sysctl to set the minimum command size for that
particular disk. (Since you could have multiple disks with
multiple requirements in one system.)
- Loader tunable support for all the sysctls in the da(4) and cd(4)
drivers.
- Add a CDIOCCLOSE ioctl for cd(4) (bde pointed this out a long
time ago).
- Add a media validation routine (cdcheckmedia()) to the cd(4)
driver, to fix some problems bde pointed out a long time ago. We
now allow open() to succeed no matter what, but if we don't detect
valid media, the user can only issue CDIOCCLOSE or CDIOCEJECT
ioctls.
- The media validation routine also reads the table of contents off
the drive. We use the table of contents to implement the
CDIOCPLAYTRACKS ioctl using the PLAY AUDIO MSF command. The
PLAY AUDIO TRACK INDEX command that we previously used was
deprecated after SCSI-2. It works in every SCSI CDROM I've tried,
but doesn't seem to work on ATAPI CDROM drives. We still use the
play audio track index command if we don't have a valid TOC, but
I suppose it'll fail anyway in that case.
- Add _len() versions of scsi_mode_sense() and scsi_mode_select() so
that we can specify the minimum command length.
- Fix a couple of formatting problems in the sense printing code.
MFC after: 4 weeks
2003-02-21 06:19:38 +00:00
|
|
|
struct sysctl_ctx_list sysctl_ctx;
|
|
|
|
struct sysctl_oid *sysctl_tree;
|
2007-04-15 08:49:19 +00:00
|
|
|
struct callout sendordered_c;
|
2010-06-07 17:41:34 +00:00
|
|
|
uint64_t wwpn;
|
2013-04-26 16:17:04 +00:00
|
|
|
uint8_t unmap_buf[UNMAP_BUF_SIZE];
|
2012-01-26 18:09:28 +00:00
|
|
|
struct scsi_read_capacity_data_long rcaplong;
|
2012-07-29 11:51:48 +00:00
|
|
|
struct callout mediapoll_c;
|
1998-09-15 06:36:34 +00:00
|
|
|
};
|
|
|
|
|
2013-04-26 16:17:04 +00:00
|
|
|
#define dadeleteflag(softc, delete_method, enable) \
|
|
|
|
if (enable) { \
|
|
|
|
softc->delete_available |= (1 << delete_method); \
|
|
|
|
} else { \
|
|
|
|
softc->delete_available &= ~(1 << delete_method); \
|
|
|
|
}
|
|
|
|
|
1998-10-08 05:46:38 +00:00
|
|
|
struct da_quirk_entry {
|
|
|
|
struct scsi_inquiry_pattern inq_pat;
|
|
|
|
da_quirks quirks;
|
|
|
|
};
|
|
|
|
|
2000-08-29 22:09:23 +00:00
|
|
|
static const char quantum[] = "QUANTUM";
|
|
|
|
static const char microp[] = "MICROP";
|
|
|
|
|
1998-10-08 05:46:38 +00:00
|
|
|
static struct da_quirk_entry da_quirk_table[] =
|
|
|
|
{
|
2003-08-25 18:14:43 +00:00
|
|
|
/* SPI, FC devices */
|
2001-11-17 14:46:22 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Fujitsu M2513A MO drives.
|
|
|
|
* Tested devices: M2513A2 firmware versions 1200 & 1300.
|
|
|
|
* (dip switch selects whether T_DIRECT or T_OPTICAL device)
|
|
|
|
* Reported by: W.Scholten <whs@xs4all.nl>
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "FUJITSU", "M2513A", "*"},
|
|
|
|
/*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* See above. */
|
|
|
|
{T_OPTICAL, SIP_MEDIA_REMOVABLE, "FUJITSU", "M2513A", "*"},
|
|
|
|
/*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
1998-10-08 05:46:38 +00:00
|
|
|
{
|
1998-10-12 17:16:47 +00:00
|
|
|
/*
|
|
|
|
* This particular Fujitsu drive doesn't like the
|
|
|
|
* synchronize cache command.
|
|
|
|
* Reported by: Tom Jackson <toj@gorilla.net>
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_FIXED, "FUJITSU", "M2954*", "*"},
|
|
|
|
/*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* This drive doesn't like the synchronize cache command
|
|
|
|
* either. Reported by: Matthew Jacob <mjacob@feral.com>
|
|
|
|
* in NetBSD PR kern/6027, August 24, 1998.
|
1998-10-08 05:46:38 +00:00
|
|
|
*/
|
2000-08-29 22:09:23 +00:00
|
|
|
{T_DIRECT, SIP_MEDIA_FIXED, microp, "2217*", "*"},
|
1998-10-12 17:16:47 +00:00
|
|
|
/*quirks*/ DA_Q_NO_SYNC_CACHE
|
1998-10-13 23:34:54 +00:00
|
|
|
},
|
1999-01-05 20:43:41 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* This drive doesn't like the synchronize cache command
|
|
|
|
* either. Reported by: Hellmuth Michaelis (hm@kts.org)
|
|
|
|
* (PR 8882).
|
|
|
|
*/
|
2000-08-29 22:09:23 +00:00
|
|
|
{T_DIRECT, SIP_MEDIA_FIXED, microp, "2112*", "*"},
|
1999-01-05 20:43:41 +00:00
|
|
|
/*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
1998-10-13 23:34:54 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Doesn't like the synchronize cache command.
|
|
|
|
* Reported by: Blaz Zupan <blaz@gold.amis.net>
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_FIXED, "NEC", "D3847*", "*"},
|
|
|
|
/*quirks*/ DA_Q_NO_SYNC_CACHE
|
1998-12-02 17:35:28 +00:00
|
|
|
},
|
2000-08-29 22:09:23 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Doesn't like the synchronize cache command.
|
2005-04-14 04:46:46 +00:00
|
|
|
* Reported by: Blaz Zupan <blaz@gold.amis.net>
|
2000-08-29 22:09:23 +00:00
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_FIXED, quantum, "MAVERICK 540S", "*"},
|
|
|
|
/*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Doesn't like the synchronize cache command.
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_FIXED, quantum, "LPS525S", "*"},
|
|
|
|
/*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
2005-04-14 04:05:00 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Doesn't like the synchronize cache command.
|
2005-04-14 04:46:46 +00:00
|
|
|
* Reported by: walter@pelissero.de
|
2005-04-14 04:05:00 +00:00
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_FIXED, quantum, "LPS540S", "*"},
|
|
|
|
/*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
1998-12-02 17:35:28 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Doesn't work correctly with 6 byte reads/writes.
|
|
|
|
* Returns illegal request, and points to byte 9 of the
|
|
|
|
* 6-byte CDB.
|
|
|
|
* Reported by: Adam McDougall <bsdx@spawnet.com>
|
|
|
|
*/
|
2000-08-29 22:09:23 +00:00
|
|
|
{T_DIRECT, SIP_MEDIA_FIXED, quantum, "VIKING 4*", "*"},
|
1998-12-02 17:35:28 +00:00
|
|
|
/*quirks*/ DA_Q_NO_6_BYTE
|
|
|
|
},
|
|
|
|
{
|
2003-08-22 16:35:53 +00:00
|
|
|
/* See above. */
|
2000-08-29 22:09:23 +00:00
|
|
|
{T_DIRECT, SIP_MEDIA_FIXED, quantum, "VIKING 2*", "*"},
|
1998-12-02 17:35:28 +00:00
|
|
|
/*quirks*/ DA_Q_NO_6_BYTE
|
2000-03-15 22:44:03 +00:00
|
|
|
},
|
2005-04-14 04:12:45 +00:00
|
|
|
{
|
2005-04-14 04:46:46 +00:00
|
|
|
/*
|
|
|
|
* Doesn't like the synchronize cache command.
|
|
|
|
* Reported by: walter@pelissero.de
|
|
|
|
*/
|
2005-04-14 04:12:45 +00:00
|
|
|
{T_DIRECT, SIP_MEDIA_FIXED, "CONNER", "CP3500*", "*"},
|
2006-11-26 17:15:54 +00:00
|
|
|
/*quirks*/ DA_Q_NO_SYNC_CACHE
|
2005-04-14 04:12:45 +00:00
|
|
|
},
|
2003-12-08 06:29:38 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* The CISS RAID controllers do not support SYNC_CACHE
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_FIXED, "COMPAQ", "RAID*", "*"},
|
|
|
|
/*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
2014-04-23 19:50:35 +00:00
|
|
|
{
|
|
|
|
/*
|
2014-09-10 21:24:15 +00:00
|
|
|
* The STEC SSDs sometimes hang on UNMAP.
|
2014-04-23 19:50:35 +00:00
|
|
|
*/
|
2014-09-10 21:24:15 +00:00
|
|
|
{T_DIRECT, SIP_MEDIA_FIXED, "STEC", "*", "*"},
|
2014-04-23 19:50:35 +00:00
|
|
|
/*quirks*/ DA_Q_NO_UNMAP
|
|
|
|
},
|
2015-02-02 20:23:05 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* VMware returns BUSY status when storage has transient
|
|
|
|
* connectivity problems, so better wait.
|
|
|
|
*/
|
2015-11-05 09:07:53 +00:00
|
|
|
{T_DIRECT, SIP_MEDIA_FIXED, "VMware*", "*", "*"},
|
2015-02-02 20:23:05 +00:00
|
|
|
/*quirks*/ DA_Q_RETRY_BUSY
|
|
|
|
},
|
2003-08-25 18:14:43 +00:00
|
|
|
/* USB mass storage devices supported by umass(4) */
|
2003-08-22 05:43:30 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* EXATELECOM (Sigmatel) i-Bead 100/105 USB Flash MP3 Player
|
|
|
|
* PR: kern/51675
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "EXATEL", "i-BEAD10*", "*"},
|
|
|
|
/*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
2003-08-22 05:58:23 +00:00
|
|
|
{
|
|
|
|
/*
|
2004-04-19 04:14:09 +00:00
|
|
|
* Power Quotient Int. (PQI) USB flash key
|
|
|
|
* PR: kern/53067
|
2003-08-22 05:58:23 +00:00
|
|
|
*/
|
2004-04-19 04:14:09 +00:00
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "Generic*", "USB Flash Disk*",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
2006-11-26 17:15:54 +00:00
|
|
|
},
|
2003-08-22 16:35:53 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Creative Nomad MUVO mp3 player (USB)
|
|
|
|
* PR: kern/53094
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "CREATIVE", "NOMAD_MUVO", "*"},
|
|
|
|
/*quirks*/ DA_Q_NO_SYNC_CACHE|DA_Q_NO_PREVENT
|
|
|
|
},
|
2004-04-19 04:14:09 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Jungsoft NEXDISK USB flash key
|
|
|
|
* PR: kern/54737
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "JUNGSOFT", "NEXDISK*", "*"},
|
|
|
|
/*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* FreeDik USB Mini Data Drive
|
|
|
|
* PR: kern/54786
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "FreeDik*", "Mini Data Drive",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Sigmatel USB Flash MP3 Player
|
|
|
|
* PR: kern/57046
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "SigmaTel", "MSCN", "*"},
|
|
|
|
/*quirks*/ DA_Q_NO_SYNC_CACHE|DA_Q_NO_PREVENT
|
|
|
|
},
|
2004-05-02 19:24:23 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Neuros USB Digital Audio Computer
|
|
|
|
* PR: kern/63645
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "NEUROS", "dig. audio comp.",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
2004-07-18 05:39:14 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* SEAGRAND NP-900 MP3 Player
|
|
|
|
* PR: kern/64563
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "SEAGRAND", "NP-900*", "*"},
|
|
|
|
/*quirks*/ DA_Q_NO_SYNC_CACHE|DA_Q_NO_PREVENT
|
|
|
|
},
|
2004-08-08 09:08:37 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* iRiver iFP MP3 player (with UMS Firmware)
|
|
|
|
* PR: kern/54881, i386/63941, kern/66124
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "iRiver", "iFP*", "*"},
|
|
|
|
/*quirks*/ DA_Q_NO_SYNC_CACHE
|
2004-08-12 23:17:09 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Frontier Labs NEX IA+ Digital Audio Player, rev 1.10/0.01
|
|
|
|
* PR: kern/70158
|
|
|
|
*/
|
2005-04-14 03:59:48 +00:00
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "FL" , "Nex*", "*"},
|
2004-08-12 23:17:09 +00:00
|
|
|
/*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
2005-04-14 04:31:48 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* ZICPlay USB MP3 Player with FM
|
|
|
|
* PR: kern/75057
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "ACTIONS*" , "USB DISK*", "*"},
|
|
|
|
/*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
2005-05-05 18:48:41 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* TEAC USB floppy mechanisms
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "TEAC" , "FD-05*", "*"},
|
|
|
|
/*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
2005-06-09 17:35:04 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Kingston DataTraveler II+ USB Pen-Drive.
|
|
|
|
* Reported by: Pawel Jakub Dawidek <pjd@FreeBSD.org>
|
|
|
|
*/
|
2005-12-19 03:43:48 +00:00
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "Kingston" , "DataTraveler II+",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
2005-06-09 17:35:04 +00:00
|
|
|
},
|
2012-10-15 12:33:53 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* USB DISK Pro PMAP
|
|
|
|
* Reported by: jhs
|
|
|
|
* PR: usb/96381
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, " ", "USB DISK Pro", "PMAP"},
|
|
|
|
/*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
2005-12-19 03:27:28 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Motorola E398 Mobile Phone (TransFlash memory card).
|
|
|
|
* Reported by: Wojciech A. Koszek <dunstan@FreeBSD.czest.pl>
|
|
|
|
* PR: usb/89889
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "Motorola" , "Motorola Phone",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
2006-01-13 11:33:40 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Qware BeatZkey! Pro
|
|
|
|
* PR: usb/79164
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "GENERIC", "USB DISK DEVICE",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Time DPA20B 1GB MP3 Player
|
|
|
|
* PR: usb/81846
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "USB2.0*", "(FS) FLASH DISK*",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
Add Product IDs :
- Sandisk Cruzer Micro 128MB [5]
- DANE-ELEC zMate 512MB USB flash drive [7]
- Attache 256MB USB 2.0 Flash Drive [8]
- Sandisk Cruzer Micro 256MB [9]
Add scsi_da.c quirks :
- Samsung USB key 128Mb [1]
- Kingston DataTraveler 2.0 [2]
- Creative MuVo Slim [3]
- United MP 5512 Portable MP3 Player [4]
- Sandisk Cruzer Micro 128MB [5], [9]
- PNY USB Flash keys [6], [7], [8]
Add umass.c quirks :
- Sandisk Cruzer Micro 128MB [5]
- DANE-ELEC zMate 512MB USB flash drive [7]
- Attache 256MB USB 2.0 Flash Drive [8]
- Sandisk Cruzer Micro 256MB [9]
PR: usb/90081 [1],
usb/89196 [2],
kern/86131 [3],
usb/80487 [4],
usb/75970 [5],
usb/75578 [6],
usb/72344 [7],
usb/65436 [8],
usb/70835 [9]
Submitted by: Henri-Pierre CHARLES <hpc@prism.uvsq.fr> [1],
Andrey Simonenko <simon@comsys.ntu-kpi.kiev.ua> [2],
Erich Rickheit KSC <rickheit-fbp@numachi.com> [3],
tnu@chania.di.uoa.gr [4],
Bram Abbekerk <bram@abbekerk.demon.nl> [5],
Thomas Pornin <pornin@bolet.org> [6],
parv <parv@pair.com> [7],
Peter D. Quilty <pdquilty@adelphia.net> [8],
Raymundo M. Vega <rvega@ms-smtp-03-eri0.socal.rr.com> [9]
Approved by: iedowse
MFC after: 3 days
2006-01-26 00:35:54 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Samsung USB key 128Mb
|
|
|
|
* PR: usb/90081
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "USB-DISK", "FreeDik-FlashUsb",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Kingston DataTraveler 2.0 USB Flash memory.
|
|
|
|
* PR: usb/89196
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "Kingston", "DataTraveler 2.0",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Creative MUVO Slim mp3 player (USB)
|
|
|
|
* PR: usb/86131
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "CREATIVE", "MuVo Slim",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE|DA_Q_NO_PREVENT
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* United MP5512 Portable MP3 Player (2-in-1 USB DISK/MP3)
|
|
|
|
* PR: usb/80487
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "Generic*", "MUSIC DISK",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* SanDisk Micro Cruzer 128MB
|
|
|
|
* PR: usb/75970
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "SanDisk" , "Micro Cruzer",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
2006-03-13 22:26:33 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* TOSHIBA TransMemory USB sticks
|
2006-03-18 21:13:14 +00:00
|
|
|
* PR: kern/94660
|
2006-03-13 22:26:33 +00:00
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "TOSHIBA", "TransMemory",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
2014-09-15 19:48:27 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* PNY USB 3.0 Flash Drives
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "PNY", "USB 3.0 FD*",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE | DA_Q_NO_RC16
|
|
|
|
},
|
Add Product IDs :
- Sandisk Cruzer Micro 128MB [5]
- DANE-ELEC zMate 512MB USB flash drive [7]
- Attache 256MB USB 2.0 Flash Drive [8]
- Sandisk Cruzer Micro 256MB [9]
Add scsi_da.c quirks :
- Samsung USB key 128Mb [1]
- Kingston DataTraveler 2.0 [2]
- Creative MuVo Slim [3]
- United MP 5512 Portable MP3 Player [4]
- Sandisk Cruzer Micro 128MB [5], [9]
- PNY USB Flash keys [6], [7], [8]
Add umass.c quirks :
- Sandisk Cruzer Micro 128MB [5]
- DANE-ELEC zMate 512MB USB flash drive [7]
- Attache 256MB USB 2.0 Flash Drive [8]
- Sandisk Cruzer Micro 256MB [9]
PR: usb/90081 [1],
usb/89196 [2],
kern/86131 [3],
usb/80487 [4],
usb/75970 [5],
usb/75578 [6],
usb/72344 [7],
usb/65436 [8],
usb/70835 [9]
Submitted by: Henri-Pierre CHARLES <hpc@prism.uvsq.fr> [1],
Andrey Simonenko <simon@comsys.ntu-kpi.kiev.ua> [2],
Erich Rickheit KSC <rickheit-fbp@numachi.com> [3],
tnu@chania.di.uoa.gr [4],
Bram Abbekerk <bram@abbekerk.demon.nl> [5],
Thomas Pornin <pornin@bolet.org> [6],
parv <parv@pair.com> [7],
Peter D. Quilty <pdquilty@adelphia.net> [8],
Raymundo M. Vega <rvega@ms-smtp-03-eri0.socal.rr.com> [9]
Approved by: iedowse
MFC after: 3 days
2006-01-26 00:35:54 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* PNY USB Flash keys
|
|
|
|
* PR: usb/75578, usb/72344, usb/65436
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "*" , "USB DISK*",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
2006-01-30 20:27:44 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Genesys 6-in-1 Card Reader
|
2006-03-18 18:28:13 +00:00
|
|
|
* PR: usb/94647
|
2006-01-30 20:27:44 +00:00
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "Generic*", "STORAGE DEVICE*",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
2006-10-07 19:04:23 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Rekam Digital CAMERA
|
|
|
|
* PR: usb/98713
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "CAMERA*", "4MP-9J6*",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
2006-10-07 18:28:55 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* iRiver H10 MP3 player
|
|
|
|
* PR: usb/102547
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "iriver", "H10*",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
2006-11-26 17:15:54 +00:00
|
|
|
},
|
2007-06-28 06:12:55 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* iRiver U10 MP3 player
|
|
|
|
* PR: usb/92306
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "iriver", "U10*",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
2006-11-26 17:13:24 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* X-Micro Flash Disk
|
|
|
|
* PR: usb/96901
|
|
|
|
*/
|
2006-11-26 17:18:31 +00:00
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "X-Micro", "Flash Disk",
|
2006-11-26 17:13:24 +00:00
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
2007-01-22 04:34:03 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* EasyMP3 EM732X USB 2.0 Flash MP3 Player
|
|
|
|
* PR: usb/96546
|
|
|
|
*/
|
2007-01-23 17:29:31 +00:00
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "EM732X", "MP3 Player*",
|
2008-01-12 19:24:55 +00:00
|
|
|
"1.00"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
2007-01-22 04:34:03 +00:00
|
|
|
},
|
2007-06-28 04:51:19 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Denver MP3 player
|
|
|
|
* PR: usb/107101
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "DENVER", "MP3 PLAYER",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
2007-06-30 04:34:45 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Philips USB Key Audio KEY013
|
|
|
|
* PR: usb/68412
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "PHILIPS", "Key*", "*"},
|
|
|
|
/*quirks*/ DA_Q_NO_SYNC_CACHE | DA_Q_NO_PREVENT
|
|
|
|
},
|
2007-06-30 05:03:03 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* JNC MP3 Player
|
|
|
|
* PR: usb/94439
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "JNC*" , "MP3 Player*",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
2007-06-30 05:21:18 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* SAMSUNG MP0402H
|
|
|
|
* PR: usb/108427
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_FIXED, "SAMSUNG", "MP0402H", "*"},
|
|
|
|
/*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
2007-06-30 05:24:25 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* I/O Magic USB flash - Giga Bank
|
|
|
|
* PR: usb/108810
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_FIXED, "GS-Magic", "stor*", "*"},
|
|
|
|
/*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
2007-06-30 14:41:30 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* JoyFly 128mb USB Flash Drive
|
|
|
|
* PR: 96133
|
|
|
|
*/
|
2007-07-01 17:42:07 +00:00
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "USB 2.0", "Flash Disk*",
|
2007-06-30 14:41:30 +00:00
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
2007-06-30 14:44:09 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* ChipsBnk usb stick
|
|
|
|
* PR: 103702
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "ChipsBnk", "USB*",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
2008-12-23 09:11:05 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Storcase (Kingston) InfoStation IFS FC2/SATA-R 201A
|
|
|
|
* PR: 129858
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_FIXED, "IFS", "FC2/SATA-R*",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
2008-07-09 17:00:14 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Samsung YP-U3 mp3-player
|
|
|
|
* PR: 125398
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "Samsung", "YP-U3",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
2007-12-11 06:41:38 +00:00
|
|
|
{
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "Netac", "OnlyDisk*",
|
|
|
|
"2000"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
2009-08-26 21:14:28 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Sony Cyber-Shot DSC cameras
|
|
|
|
* PR: usb/137035
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "Sony", "Sony DSC", "*"},
|
|
|
|
/*quirks*/ DA_Q_NO_SYNC_CACHE | DA_Q_NO_PREVENT
|
2011-12-23 00:10:17 +00:00
|
|
|
},
|
2013-02-22 17:45:32 +00:00
|
|
|
{
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "Kingston", "DataTraveler G3",
|
|
|
|
"1.00"}, /*quirks*/ DA_Q_NO_PREVENT
|
|
|
|
},
|
2013-07-30 13:00:09 +00:00
|
|
|
{
|
|
|
|
/* At least several Transcent USB sticks lie on RC16. */
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "JetFlash", "Transcend*",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_RC16
|
|
|
|
},
|
2011-12-23 00:10:17 +00:00
|
|
|
/* ATA/SATA devices over SAS/USB/... */
|
|
|
|
{
|
|
|
|
/* Hitachi Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "Hitachi", "H??????????E3*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Samsung Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "SAMSUNG HD155UI*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Samsung Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "SAMSUNG", "HD155UI*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Samsung Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "SAMSUNG HD204UI*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Samsung Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "SAMSUNG", "HD204UI*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Seagate Barracuda Green Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "ST????DL*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Seagate Barracuda Green Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ST????DL", "*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Seagate Barracuda Green Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "ST???DM*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Seagate Barracuda Green Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ST???DM*", "*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Seagate Barracuda Green Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "ST????DM*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Seagate Barracuda Green Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ST????DM", "*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Seagate Momentus Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "ST9500423AS*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Seagate Momentus Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ST950042", "3AS*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Seagate Momentus Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "ST9500424AS*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Seagate Momentus Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ST950042", "4AS*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Seagate Momentus Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "ST9640423AS*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Seagate Momentus Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ST964042", "3AS*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Seagate Momentus Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "ST9640424AS*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Seagate Momentus Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ST964042", "4AS*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Seagate Momentus Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "ST9750420AS*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Seagate Momentus Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ST975042", "0AS*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Seagate Momentus Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "ST9750422AS*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Seagate Momentus Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ST975042", "2AS*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Seagate Momentus Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "ST9750423AS*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Seagate Momentus Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ST975042", "3AS*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Seagate Momentus Thin Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "ST???LT*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Seagate Momentus Thin Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ST???LT*", "*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* WDC Caviar Green Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "WDC WD????RS*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* WDC Caviar Green Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "WDC WD??", "??RS*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* WDC Caviar Green Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "WDC WD????RX*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* WDC Caviar Green Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "WDC WD??", "??RX*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* WDC Caviar Green Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "WDC WD??????RS*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* WDC Caviar Green Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "WDC WD??", "????RS*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* WDC Caviar Green Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "WDC WD??????RX*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* WDC Caviar Green Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "WDC WD??", "????RX*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* WDC Scorpio Black Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "WDC WD???PKT*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* WDC Scorpio Black Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "WDC WD??", "?PKT*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* WDC Scorpio Black Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "WDC WD?????PKT*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* WDC Scorpio Black Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "WDC WD??", "???PKT*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* WDC Scorpio Blue Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "WDC WD???PVT*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* WDC Scorpio Blue Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "WDC WD??", "?PVT*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* WDC Scorpio Blue Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "WDC WD?????PVT*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* WDC Scorpio Blue Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "WDC WD??", "???PVT*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
2012-04-29 22:28:15 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Olympus FE-210 camera
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "OLYMPUS", "FE210*",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* LG UP3S MP3 player
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "LG", "UP3S",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Laser MP3-2GA13 MP3 player
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "USB 2.0", "(HS) Flash Disk",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
2012-10-16 17:49:14 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* LaCie external 250GB Hard drive des by Porsche
|
|
|
|
* Submitted by: Ben Stuyts <ben@altesco.nl>
|
|
|
|
* PR: 121474
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_FIXED, "SAMSUNG", "HM250JI", "*"},
|
|
|
|
/*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
2013-05-28 14:44:37 +00:00
|
|
|
/* SATA SSDs */
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Corsair Force 2 SSDs
|
|
|
|
* 4k optimised & trim only works in 4k requests + 4k aligned
|
|
|
|
*/
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "Corsair CSSD-F*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Corsair Force 3 SSDs
|
|
|
|
* 4k optimised & trim only works in 4k requests + 4k aligned
|
|
|
|
*/
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "Corsair Force 3*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
2013-10-15 17:03:02 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Corsair Neutron GTX SSDs
|
|
|
|
* 4k optimised & trim only works in 4k requests + 4k aligned
|
|
|
|
*/
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "*", "Corsair Neutron GTX*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
2013-05-28 14:44:37 +00:00
|
|
|
{
|
|
|
|
/*
|
2014-08-14 13:57:17 +00:00
|
|
|
* Corsair Force GT & GS SSDs
|
2013-05-28 14:44:37 +00:00
|
|
|
* 4k optimised & trim only works in 4k requests + 4k aligned
|
|
|
|
*/
|
2014-08-14 13:57:17 +00:00
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "Corsair Force G*", "*" },
|
2013-05-28 14:44:37 +00:00
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Crucial M4 SSDs
|
|
|
|
* 4k optimised & trim only works in 4k requests + 4k aligned
|
|
|
|
*/
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "M4-CT???M4SSD2*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Crucial RealSSD C300 SSDs
|
|
|
|
* 4k optimised
|
|
|
|
*/
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "C300-CTFDDAC???MAG*",
|
|
|
|
"*" }, /*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Intel 320 Series SSDs
|
|
|
|
* 4k optimised & trim only works in 4k requests + 4k aligned
|
|
|
|
*/
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "INTEL SSDSA2CW*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Intel 330 Series SSDs
|
|
|
|
* 4k optimised & trim only works in 4k requests + 4k aligned
|
|
|
|
*/
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "INTEL SSDSC2CT*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Intel 510 Series SSDs
|
|
|
|
* 4k optimised & trim only works in 4k requests + 4k aligned
|
|
|
|
*/
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "INTEL SSDSC2MH*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Intel 520 Series SSDs
|
|
|
|
* 4k optimised & trim only works in 4k requests + 4k aligned
|
|
|
|
*/
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "INTEL SSDSC2BW*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
2013-08-14 15:18:28 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Intel X25-M Series SSDs
|
|
|
|
* 4k optimised & trim only works in 4k requests + 4k aligned
|
|
|
|
*/
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "INTEL SSDSA2M*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
2013-05-28 14:44:37 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Kingston E100 Series SSDs
|
|
|
|
* 4k optimised & trim only works in 4k requests + 4k aligned
|
|
|
|
*/
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "KINGSTON SE100S3*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Kingston HyperX 3k SSDs
|
|
|
|
* 4k optimised & trim only works in 4k requests + 4k aligned
|
|
|
|
*/
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "KINGSTON SH103S3*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
2013-08-14 15:18:28 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Marvell SSDs (entry taken from OpenSolaris)
|
|
|
|
* 4k optimised & trim only works in 4k requests + 4k aligned
|
|
|
|
*/
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "MARVELL SD88SA02*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* OCZ Agility 2 SSDs
|
|
|
|
* 4k optimised & trim only works in 4k requests + 4k aligned
|
|
|
|
*/
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "*", "OCZ-AGILITY2*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
2013-05-28 14:44:37 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* OCZ Agility 3 SSDs
|
|
|
|
* 4k optimised & trim only works in 4k requests + 4k aligned
|
|
|
|
*/
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "OCZ-AGILITY3*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* OCZ Deneva R Series SSDs
|
|
|
|
* 4k optimised & trim only works in 4k requests + 4k aligned
|
|
|
|
*/
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "DENRSTE251M45*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* OCZ Vertex 2 SSDs (inc pro series)
|
|
|
|
* 4k optimised & trim only works in 4k requests + 4k aligned
|
|
|
|
*/
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "OCZ?VERTEX2*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* OCZ Vertex 3 SSDs
|
|
|
|
* 4k optimised & trim only works in 4k requests + 4k aligned
|
|
|
|
*/
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "OCZ-VERTEX3*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
2013-07-09 10:41:17 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* OCZ Vertex 4 SSDs
|
|
|
|
* 4k optimised & trim only works in 4k requests + 4k aligned
|
|
|
|
*/
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "OCZ-VERTEX4*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
2013-05-28 14:44:37 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Samsung 830 Series SSDs
|
|
|
|
* 4k optimised & trim only works in 4k requests + 4k aligned
|
|
|
|
*/
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "SAMSUNG SSD 830 Series*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
2014-08-14 13:57:17 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Samsung 840 SSDs
|
|
|
|
* 4k optimised & trim only works in 4k requests + 4k aligned
|
|
|
|
*/
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "Samsung SSD 840*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
2014-08-21 21:05:58 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Samsung 843T Series SSDs
|
|
|
|
* 4k optimised
|
|
|
|
*/
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "SAMSUNG MZ7WD*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
2014-10-19 16:46:36 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Samsung 850 SSDs
|
|
|
|
* 4k optimised & trim only works in 4k requests + 4k aligned
|
|
|
|
*/
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "Samsung SSD 850*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
2014-10-16 20:33:04 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Samsung PM853T Series SSDs
|
|
|
|
* 4k optimised
|
|
|
|
*/
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "SAMSUNG MZ7GE*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
2016-03-24 14:20:33 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Samsung SM863 Series SSDs
|
|
|
|
* 4k optimised
|
|
|
|
*/
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "SAMSUNG MZ7KM*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
2013-05-28 14:44:37 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* SuperTalent TeraDrive CT SSDs
|
|
|
|
* 4k optimised & trim only works in 4k requests + 4k aligned
|
|
|
|
*/
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "FTM??CT25H*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* XceedIOPS SATA SSDs
|
|
|
|
* 4k optimised
|
|
|
|
*/
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "SG9XCS2D*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
2015-03-07 17:18:06 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Hama Innostor USB-Stick
|
|
|
|
*/
|
|
|
|
{ T_DIRECT, SIP_MEDIA_REMOVABLE, "Innostor", "Innostor*", "*" },
|
|
|
|
/*quirks*/DA_Q_NO_RC16
|
|
|
|
},
|
2015-03-25 13:28:13 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* MX-ES USB Drive by Mach Xtreme
|
|
|
|
*/
|
2015-04-21 22:55:52 +00:00
|
|
|
{ T_DIRECT, SIP_MEDIA_REMOVABLE, "MX", "MXUB3*", "*"},
|
2015-03-25 13:28:13 +00:00
|
|
|
/*quirks*/DA_Q_NO_RC16
|
|
|
|
},
|
1998-10-08 05:46:38 +00:00
|
|
|
};
|
|
|
|
|
2003-02-25 22:06:21 +00:00
|
|
|
static disk_strategy_t dastrategy;
|
2003-02-21 19:00:48 +00:00
|
|
|
static dumper_t dadump;
|
1998-09-15 06:36:34 +00:00
|
|
|
static periph_init_t dainit;
|
|
|
|
static void daasync(void *callback_arg, u_int32_t code,
|
|
|
|
struct cam_path *path, void *arg);
|
Move dynamic sysctl(8) variable creation for the cd(4) and da(4) drivers
out of cdregister() and daregister(), which are run from interrupt context.
The sysctl code does blocking mallocs (M_WAITOK), which causes problems
if malloc(9) actually needs to sleep.
The eventual fix for this issue will involve moving the CAM probe process
inside a kernel thread. For now, though, I have fixed the issue by moving
dynamic sysctl variable creation for these two drivers to a task queue
running in a kernel thread.
The existing task queues (taskqueue_swi and taskqueue_swi_giant) run in
software interrupt handlers, which wouldn't fix the problem at hand. So I
have created a new task queue, taskqueue_thread, that runs inside a kernel
thread. (It also runs outside of Giant -- clients must explicitly acquire
and release Giant in their taskqueue functions.)
scsi_cd.c: Remove sysctl variable creation code from cdregister(), and
move it to a new function, cdsysctlinit(). Queue
cdsysctlinit() to the taskqueue_thread taskqueue once we
have fully registered the cd(4) driver instance.
scsi_da.c: Remove sysctl variable creation code from daregister(), and
move it to move it to a new function, dasysctlinit().
Queue dasysctlinit() to the taskqueue_thread taskqueue once
we have fully registered the da(4) instance.
taskqueue.h: Declare the new taskqueue_thread taskqueue, update some
comments.
subr_taskqueue.c:
Create the new kernel thread taskqueue. This taskqueue
runs outside of Giant, so any functions queued to it would
need to explicitly acquire/release Giant if they need it.
cd.4: Update the cd(4) man page to talk about the minimum command
size sysctl/loader tunable. Also note that the changer
variables are available as loader tunables as well.
da.4: Update the da(4) man page to cover the retry_count,
default_timeout and minimum_cmd_size sysctl variables/loader
tunables. Remove references to /dev/r???, they aren't used
any longer.
cd.9: Update the cd(9) man page to describe the CD_Q_10_BYTE_ONLY
quirk.
taskqueue.9: Update the taskqueue(9) man page to describe the new thread
task queue, and the taskqueue_swi_giant queue.
MFC after: 3 days
2003-09-03 04:46:28 +00:00
|
|
|
static void dasysctlinit(void *context, int pending);
|
Add support to CAM for devices with more than 2^32 blocks. (2TB if you're
using 512 byte blocks).
cam_ccb.h: Bump up volume_size and cylinders in ccb_calc_geometry to
64 bits and 32 bits respectively, so we can hold larger
device sizes. cylinders would overflow at about 500GB.
Bump CAM_VERSION for this change. Note that this will
require a recompile of all applications that talk to the
pass(4) driver.
scsi_all.c: Add descriptions for READ/WRITE(16), update READ/WRITE(12)
descriptions, add descriptions for SERVICE ACTION IN/OUT.
Add a new function, scsi_read_capacity_16(), that issues
the read capacity service action. (Necessary for arrays
larger than 2^32 sectors.) Update scsi_read_write() to use
a 64 bit LBA and issue READ(16) or WRITE(16) if necessary.
NOTE the API change. This should be largely transparnet
to most userland applications at compile time, but will
break binary compatibility. The CAM_VERSION bump, above,
also serves the purpose of forcing a recompile for any
applications that talk to CAM.
scsi_all.h: Add 16 byte READ/WRITE structures, structures for 16 byte
READ CAPACITY/SERVICE ACTION IN. Add scsi_u64to8b() and
scsi_8btou64.
scsi_da.c: The da(4) driver probe now has two stages for devices
larger than 2TB. If a standard READ CAPACITY(10) returns
0xffffffff, we issue the 16 byte version of read capacity
to determine the true array capacity. We also do the same
thing in daopen() -- use the 16 byte read capacity if the
device is large enough.
The sysctl/loader code has also been updated to accept
16 bytes as a minimum command size.
2003-04-30 00:35:22 +00:00
|
|
|
static int dacmdsizesysctl(SYSCTL_HANDLER_ARGS);
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
static int dadeletemethodsysctl(SYSCTL_HANDLER_ARGS);
|
2013-04-26 16:22:54 +00:00
|
|
|
static int dadeletemaxsysctl(SYSCTL_HANDLER_ARGS);
|
2013-04-26 15:31:52 +00:00
|
|
|
static void dadeletemethodset(struct da_softc *softc,
|
2013-01-10 11:57:46 +00:00
|
|
|
da_delete_methods delete_method);
|
2013-04-26 16:22:54 +00:00
|
|
|
static off_t dadeletemaxsize(struct da_softc *softc,
|
|
|
|
da_delete_methods delete_method);
|
2013-04-26 16:17:04 +00:00
|
|
|
static void dadeletemethodchoose(struct da_softc *softc,
|
|
|
|
da_delete_methods default_method);
|
2013-05-02 14:37:23 +00:00
|
|
|
static void daprobedone(struct cam_periph *periph, union ccb *ccb);
|
2013-04-26 16:17:04 +00:00
|
|
|
|
1998-09-15 06:36:34 +00:00
|
|
|
static periph_ctor_t daregister;
|
|
|
|
static periph_dtor_t dacleanup;
|
|
|
|
static periph_start_t dastart;
|
Fix a problem with the way we handled device invalidation when attaching
to a device failed.
In theory, the same steps that happen when we get an AC_LOST_DEVICE async
notification should have been taken when a driver fails to attach. In
practice, that wasn't the case.
This only affected the da, cd and ch drivers, but the fix affects all
peripheral drivers.
There were several possible problems:
- In the da driver, we didn't remove the peripheral's softc from the da
driver's linked list of softcs. Once the peripheral and softc got
removed, we'd get a kernel panic the next time the timeout routine
called dasendorderedtag().
- In the da, cd and possibly ch drivers, we didn't remove the
peripheral's devstat structure from the devstat queue. Once the
peripheral and softc were removed, this could cause a panic if anyone
tried to access device statistics. (one component of the linked list
wouldn't exist anymore)
- In the cd driver, we didn't take the peripheral off the changer run
queue if it was scheduled to run. In practice, it's highly unlikely,
and maybe impossible that the peripheral would have been on the
changer run queue at that stage of the probe process.
The fix is:
- Add a new peripheral callback function (the "oninvalidate" function)
that is called the first time cam_periph_invalidate() is called for a
peripheral.
- Create new foooninvalidate() routines for each peripheral driver. This
routine is always called at splsoftcam(), and contains all the stuff
that used to be in the AC_LOST_DEVICE case of the async callback
handler.
- Move the devstat cleanup call to the destructor/cleanup routines, since
some of the drivers do I/O in their close routines.
- Make sure that when we're flushing the buffer queue, we traverse it at
splbio().
- Add a check for the invalid flag in the pt driver's open routine.
Reviewed by: gibbs
1998-10-22 22:16:56 +00:00
|
|
|
static periph_oninv_t daoninvalidate;
|
1998-09-15 06:36:34 +00:00
|
|
|
static void dadone(struct cam_periph *periph,
|
|
|
|
union ccb *done_ccb);
|
|
|
|
static int daerror(union ccb *ccb, u_int32_t cam_flags,
|
|
|
|
u_int32_t sense_flags);
|
|
|
|
static void daprevent(struct cam_periph *periph, int action);
|
2012-04-12 12:58:14 +00:00
|
|
|
static void dareprobe(struct cam_periph *periph);
|
Add support to CAM for devices with more than 2^32 blocks. (2TB if you're
using 512 byte blocks).
cam_ccb.h: Bump up volume_size and cylinders in ccb_calc_geometry to
64 bits and 32 bits respectively, so we can hold larger
device sizes. cylinders would overflow at about 500GB.
Bump CAM_VERSION for this change. Note that this will
require a recompile of all applications that talk to the
pass(4) driver.
scsi_all.c: Add descriptions for READ/WRITE(16), update READ/WRITE(12)
descriptions, add descriptions for SERVICE ACTION IN/OUT.
Add a new function, scsi_read_capacity_16(), that issues
the read capacity service action. (Necessary for arrays
larger than 2^32 sectors.) Update scsi_read_write() to use
a 64 bit LBA and issue READ(16) or WRITE(16) if necessary.
NOTE the API change. This should be largely transparnet
to most userland applications at compile time, but will
break binary compatibility. The CAM_VERSION bump, above,
also serves the purpose of forcing a recompile for any
applications that talk to CAM.
scsi_all.h: Add 16 byte READ/WRITE structures, structures for 16 byte
READ CAPACITY/SERVICE ACTION IN. Add scsi_u64to8b() and
scsi_8btou64.
scsi_da.c: The da(4) driver probe now has two stages for devices
larger than 2TB. If a standard READ CAPACITY(10) returns
0xffffffff, we issue the 16 byte version of read capacity
to determine the true array capacity. We also do the same
thing in daopen() -- use the 16 byte read capacity if the
device is large enough.
The sysctl/loader code has also been updated to accept
16 bytes as a minimum command size.
2003-04-30 00:35:22 +00:00
|
|
|
static void dasetgeom(struct cam_periph *periph, uint32_t block_len,
|
2012-01-26 18:09:28 +00:00
|
|
|
uint64_t maxsector,
|
|
|
|
struct scsi_read_capacity_data_long *rcaplong,
|
|
|
|
size_t rcap_size);
|
1998-09-15 06:36:34 +00:00
|
|
|
static timeout_t dasendorderedtag;
|
1999-08-21 06:24:40 +00:00
|
|
|
static void dashutdown(void *arg, int howto);
|
2012-07-29 11:51:48 +00:00
|
|
|
static timeout_t damediapoll;
|
|
|
|
|
|
|
|
#ifndef DA_DEFAULT_POLL_PERIOD
|
|
|
|
#define DA_DEFAULT_POLL_PERIOD 3
|
|
|
|
#endif
|
1998-09-15 06:36:34 +00:00
|
|
|
|
|
|
|
#ifndef DA_DEFAULT_TIMEOUT
|
|
|
|
#define DA_DEFAULT_TIMEOUT 60 /* Timeout in seconds */
|
|
|
|
#endif
|
|
|
|
|
2001-07-09 19:18:00 +00:00
|
|
|
#ifndef DA_DEFAULT_RETRY
|
|
|
|
#define DA_DEFAULT_RETRY 4
|
|
|
|
#endif
|
|
|
|
|
2006-11-02 21:12:37 +00:00
|
|
|
#ifndef DA_DEFAULT_SEND_ORDERED
|
|
|
|
#define DA_DEFAULT_SEND_ORDERED 1
|
|
|
|
#endif
|
|
|
|
|
2013-03-29 22:58:15 +00:00
|
|
|
#define DA_SIO (softc->sort_io_queue >= 0 ? \
|
|
|
|
softc->sort_io_queue : cam_sort_io_queues)
|
2006-11-02 21:12:37 +00:00
|
|
|
|
2012-07-29 11:51:48 +00:00
|
|
|
static int da_poll_period = DA_DEFAULT_POLL_PERIOD;
|
2001-07-09 19:18:00 +00:00
|
|
|
static int da_retry_count = DA_DEFAULT_RETRY;
|
|
|
|
static int da_default_timeout = DA_DEFAULT_TIMEOUT;
|
2006-11-02 21:12:37 +00:00
|
|
|
static int da_send_ordered = DA_DEFAULT_SEND_ORDERED;
|
2001-07-09 19:18:00 +00:00
|
|
|
|
2011-11-07 15:43:11 +00:00
|
|
|
static SYSCTL_NODE(_kern_cam, OID_AUTO, da, CTLFLAG_RD, 0,
|
2001-07-09 19:18:00 +00:00
|
|
|
"CAM Direct Access Disk driver");
|
2014-06-28 03:56:17 +00:00
|
|
|
SYSCTL_INT(_kern_cam_da, OID_AUTO, poll_period, CTLFLAG_RWTUN,
|
2012-07-29 11:51:48 +00:00
|
|
|
&da_poll_period, 0, "Media polling period in seconds");
|
2014-06-28 03:56:17 +00:00
|
|
|
SYSCTL_INT(_kern_cam_da, OID_AUTO, retry_count, CTLFLAG_RWTUN,
|
2001-07-09 19:18:00 +00:00
|
|
|
&da_retry_count, 0, "Normal I/O retry count");
|
2014-06-28 03:56:17 +00:00
|
|
|
SYSCTL_INT(_kern_cam_da, OID_AUTO, default_timeout, CTLFLAG_RWTUN,
|
2001-07-09 19:18:00 +00:00
|
|
|
&da_default_timeout, 0, "Normal I/O timeout (in seconds)");
|
2014-06-28 03:56:17 +00:00
|
|
|
SYSCTL_INT(_kern_cam_da, OID_AUTO, send_ordered, CTLFLAG_RWTUN,
|
2006-11-02 21:12:37 +00:00
|
|
|
&da_send_ordered, 0, "Send Ordered Tags");
|
2001-07-09 19:18:00 +00:00
|
|
|
|
1998-09-15 06:36:34 +00:00
|
|
|
/*
|
|
|
|
* DA_ORDEREDTAG_INTERVAL determines how often, relative
|
|
|
|
* to the default timeout, we check to see whether an ordered
|
|
|
|
* tagged transaction is appropriate to prevent simple tag
|
|
|
|
* starvation. Since we'd like to ensure that there is at least
|
|
|
|
* 1/2 of the timeout length left for a starved transaction to
|
|
|
|
* complete after we've sent an ordered tag, we must poll at least
|
|
|
|
* four times in every timeout period. This takes care of the worst
|
|
|
|
* case where a starved transaction starts during an interval that
|
|
|
|
* meets the requirement "don't send an ordered tag" test so it takes
|
|
|
|
* us two intervals to determine that a tag must be sent.
|
|
|
|
*/
|
|
|
|
#ifndef DA_ORDEREDTAG_INTERVAL
|
|
|
|
#define DA_ORDEREDTAG_INTERVAL 4
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static struct periph_driver dadriver =
|
|
|
|
{
|
|
|
|
dainit, "da",
|
|
|
|
TAILQ_HEAD_INITIALIZER(dadriver.units), /* generation */ 0
|
|
|
|
};
|
|
|
|
|
2001-02-07 07:05:59 +00:00
|
|
|
PERIPHDRIVER_DECLARE(da, dadriver);
|
1998-09-15 06:36:34 +00:00
|
|
|
|
2011-11-07 06:44:47 +00:00
|
|
|
static MALLOC_DEFINE(M_SCSIDA, "scsi_da", "scsi_da buffers");
|
2007-05-14 21:48:53 +00:00
|
|
|
|
1998-09-15 06:36:34 +00:00
|
|
|
static int
|
2003-02-25 22:06:21 +00:00
|
|
|
daopen(struct disk *dp)
|
1998-09-15 06:36:34 +00:00
|
|
|
{
|
|
|
|
struct cam_periph *periph;
|
|
|
|
struct da_softc *softc;
|
|
|
|
int error;
|
|
|
|
|
2003-02-25 22:06:21 +00:00
|
|
|
periph = (struct cam_periph *)dp->d_drv1;
|
2007-04-15 08:49:19 +00:00
|
|
|
if (cam_periph_acquire(periph) != CAM_REQ_CMP) {
|
Fix a race condition in CAM peripheral free handling, locking
in the CAM XPT bus traversal code, and a number of other periph level
issues.
cam_periph.h,
cam_periph.c: Modify cam_periph_acquire() to test the CAM_PERIPH_INVALID
flag prior to allowing a reference count to be gained
on a peripheral. Callers of this function will receive
CAM_REQ_CMP_ERR status in the situation of attempting to
reference an invalidated periph. This guarantees that
a peripheral scheduled for a deferred free will not
be accessed during its wait for destruction.
Panic during attempts to drop a reference count on
a peripheral that already has a zero reference count.
In cam_periph_list(), use a local sbuf with SBUF_FIXEDLEN
set so that mallocs do not occur while the xpt topology
lock is held, regardless of the allocation policy of the
passed in sbuf.
Add a new routine, cam_periph_release_locked_buses(),
that can be called when the caller already holds
the CAM topology lock.
Add some extra debugging for duplicate peripheral
allocations in cam_periph_alloc().
Treat CAM_DEV_NOT_THERE much the same as a selection
timeout (AC_LOST_DEVICE is emitted), but forgo retries.
cam_xpt.c: Revamp the way the EDT traversal code does locking
and reference counting. This was broken, since it
assumed that the EDT would not change during
traversal, but that assumption is no longer valid.
So, to prevent devices from going away while we
traverse the EDT, make sure we properly lock
everything and hold references on devices that
we are using.
The two peripheral driver traversal routines should
be examined. xptpdperiphtraverse() holds the
topology lock for the entire time it runs.
xptperiphtraverse() is now locked properly, but
only holds the topology lock while it is traversing
the list, and not while the traversal function is
running.
The bus locking code in xptbustraverse() should
also be revisited at a later time, since it is
complex and should probably be simplified.
scsi_da.c: Pay attention to the return value from cam_periph_acquire().
Return 0 always from daclose() even if the disk is now gone.
Add some rudimentary error injection support.
scsi_sg.c: Fix reference counting in the sg(4) driver.
The sg driver was calling cam_periph_release() on close,
but never called cam_periph_acquire() (which increments
the reference count) on open.
The periph code correctly complained that the sg(4)
driver was trying to decrement the refcount when it
was already 0.
Sponsored by: Spectra Logic
MFC after: 2 weeks
2012-01-12 00:41:48 +00:00
|
|
|
return (ENXIO);
|
2007-04-15 08:49:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
cam_periph_lock(periph);
|
|
|
|
if ((error = cam_periph_hold(periph, PRIBIO|PCATCH)) != 0) {
|
|
|
|
cam_periph_unlock(periph);
|
|
|
|
cam_periph_release(periph);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2012-06-05 09:45:42 +00:00
|
|
|
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE | CAM_DEBUG_PERIPH,
|
|
|
|
("daopen\n"));
|
1998-09-15 06:36:34 +00:00
|
|
|
|
2013-04-27 12:46:04 +00:00
|
|
|
softc = (struct da_softc *)periph->softc;
|
2012-04-12 12:58:14 +00:00
|
|
|
dareprobe(periph);
|
1998-09-15 06:36:34 +00:00
|
|
|
|
2012-04-12 12:58:14 +00:00
|
|
|
/* Wait for the disk size update. */
|
2013-04-04 19:07:37 +00:00
|
|
|
error = cam_periph_sleep(periph, &softc->disk->d_mediasize, PRIBIO,
|
2012-04-12 12:58:14 +00:00
|
|
|
"dareprobe", 0);
|
|
|
|
if (error != 0)
|
2014-01-04 17:52:43 +00:00
|
|
|
xpt_print(periph->path, "unable to retrieve capacity data\n");
|
1998-10-07 02:57:57 +00:00
|
|
|
|
2013-05-03 11:53:06 +00:00
|
|
|
if (periph->flags & CAM_PERIPH_INVALID)
|
2012-04-12 12:58:14 +00:00
|
|
|
error = ENXIO;
|
2008-08-29 04:39:46 +00:00
|
|
|
|
2012-04-12 12:58:14 +00:00
|
|
|
if (error == 0 && (softc->flags & DA_FLAG_PACK_REMOVABLE) != 0 &&
|
|
|
|
(softc->quirks & DA_Q_NO_PREVENT) == 0)
|
|
|
|
daprevent(periph, PR_PREVENT);
|
2008-08-29 04:39:46 +00:00
|
|
|
|
2013-05-03 11:53:06 +00:00
|
|
|
if (error == 0) {
|
|
|
|
softc->flags &= ~DA_FLAG_PACK_INVALID;
|
|
|
|
softc->flags |= DA_FLAG_OPEN;
|
|
|
|
}
|
2012-07-29 11:51:48 +00:00
|
|
|
|
2007-04-15 08:49:19 +00:00
|
|
|
cam_periph_unhold(periph);
|
1998-09-15 06:36:34 +00:00
|
|
|
cam_periph_unlock(periph);
|
2008-08-29 04:39:46 +00:00
|
|
|
|
2013-05-03 11:53:06 +00:00
|
|
|
if (error != 0)
|
2008-08-29 04:39:46 +00:00
|
|
|
cam_periph_release(periph);
|
2012-04-12 12:58:14 +00:00
|
|
|
|
1998-09-15 06:36:34 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2003-02-25 22:06:21 +00:00
|
|
|
daclose(struct disk *dp)
|
1998-09-15 06:36:34 +00:00
|
|
|
{
|
|
|
|
struct cam_periph *periph;
|
|
|
|
struct da_softc *softc;
|
Merge CAM locking changes from the projects/camlock branch to radically
reduce lock congestion and improve SMP scalability of the SCSI/ATA stack,
preparing the ground for the coming next GEOM direct dispatch support.
Replace big per-SIM locks with bunch of smaller ones:
- per-LUN locks to protect device and peripheral drivers state;
- per-target locks to protect list of LUNs on target;
- per-bus locks to protect reference counting;
- per-send queue locks to protect queue of CCBs to be sent;
- per-done queue locks to protect queue of completed CCBs;
- remaining per-SIM locks now protect only HBA driver internals.
While holding LUN lock it is allowed (while not recommended for performance
reasons) to take SIM lock. The opposite acquisition order is forbidden.
All the other locks are leaf locks, that can be taken anywhere, but should
not be cascaded. Many functions, such as: xpt_action(), xpt_done(),
xpt_async(), xpt_create_path(), etc. are no longer require (but allow) SIM
lock to be held.
To keep compatibility and solve cases where SIM lock can't be dropped, all
xpt_async() calls in addition to xpt_done() calls are queued to completion
threads for async processing in clean environment without SIM lock held.
Instead of single CAM SWI thread, used for commands completion processing
before, use multiple (depending on number of CPUs) threads. Load balanced
between them using "hash" of the device B:T:L address.
HBA drivers that can drop SIM lock during completion processing and have
sufficient number of completion threads to efficiently scale to multiple
CPUs can use new function xpt_done_direct() to avoid extra context switch.
Make ahci(4) driver to use this mechanism depending on hardware setup.
Sponsored by: iXsystems, Inc.
MFC after: 2 months
2013-10-21 12:00:26 +00:00
|
|
|
union ccb *ccb;
|
2013-07-27 22:44:55 +00:00
|
|
|
int error;
|
1998-09-15 06:36:34 +00:00
|
|
|
|
2003-02-25 22:06:21 +00:00
|
|
|
periph = (struct cam_periph *)dp->d_drv1;
|
2007-04-15 08:49:19 +00:00
|
|
|
softc = (struct da_softc *)periph->softc;
|
Merge CAM locking changes from the projects/camlock branch to radically
reduce lock congestion and improve SMP scalability of the SCSI/ATA stack,
preparing the ground for the coming next GEOM direct dispatch support.
Replace big per-SIM locks with bunch of smaller ones:
- per-LUN locks to protect device and peripheral drivers state;
- per-target locks to protect list of LUNs on target;
- per-bus locks to protect reference counting;
- per-send queue locks to protect queue of CCBs to be sent;
- per-done queue locks to protect queue of completed CCBs;
- remaining per-SIM locks now protect only HBA driver internals.
While holding LUN lock it is allowed (while not recommended for performance
reasons) to take SIM lock. The opposite acquisition order is forbidden.
All the other locks are leaf locks, that can be taken anywhere, but should
not be cascaded. Many functions, such as: xpt_action(), xpt_done(),
xpt_async(), xpt_create_path(), etc. are no longer require (but allow) SIM
lock to be held.
To keep compatibility and solve cases where SIM lock can't be dropped, all
xpt_async() calls in addition to xpt_done() calls are queued to completion
threads for async processing in clean environment without SIM lock held.
Instead of single CAM SWI thread, used for commands completion processing
before, use multiple (depending on number of CPUs) threads. Load balanced
between them using "hash" of the device B:T:L address.
HBA drivers that can drop SIM lock during completion processing and have
sufficient number of completion threads to efficiently scale to multiple
CPUs can use new function xpt_done_direct() to avoid extra context switch.
Make ahci(4) driver to use this mechanism depending on hardware setup.
Sponsored by: iXsystems, Inc.
MFC after: 2 months
2013-10-21 12:00:26 +00:00
|
|
|
cam_periph_lock(periph);
|
2012-06-05 09:45:42 +00:00
|
|
|
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE | CAM_DEBUG_PERIPH,
|
|
|
|
("daclose\n"));
|
|
|
|
|
Merge CAM locking changes from the projects/camlock branch to radically
reduce lock congestion and improve SMP scalability of the SCSI/ATA stack,
preparing the ground for the coming next GEOM direct dispatch support.
Replace big per-SIM locks with bunch of smaller ones:
- per-LUN locks to protect device and peripheral drivers state;
- per-target locks to protect list of LUNs on target;
- per-bus locks to protect reference counting;
- per-send queue locks to protect queue of CCBs to be sent;
- per-done queue locks to protect queue of completed CCBs;
- remaining per-SIM locks now protect only HBA driver internals.
While holding LUN lock it is allowed (while not recommended for performance
reasons) to take SIM lock. The opposite acquisition order is forbidden.
All the other locks are leaf locks, that can be taken anywhere, but should
not be cascaded. Many functions, such as: xpt_action(), xpt_done(),
xpt_async(), xpt_create_path(), etc. are no longer require (but allow) SIM
lock to be held.
To keep compatibility and solve cases where SIM lock can't be dropped, all
xpt_async() calls in addition to xpt_done() calls are queued to completion
threads for async processing in clean environment without SIM lock held.
Instead of single CAM SWI thread, used for commands completion processing
before, use multiple (depending on number of CPUs) threads. Load balanced
between them using "hash" of the device B:T:L address.
HBA drivers that can drop SIM lock during completion processing and have
sufficient number of completion threads to efficiently scale to multiple
CPUs can use new function xpt_done_direct() to avoid extra context switch.
Make ahci(4) driver to use this mechanism depending on hardware setup.
Sponsored by: iXsystems, Inc.
MFC after: 2 months
2013-10-21 12:00:26 +00:00
|
|
|
if (cam_periph_hold(periph, PRIBIO) == 0) {
|
|
|
|
|
|
|
|
/* Flush disk cache. */
|
|
|
|
if ((softc->flags & DA_FLAG_DIRTY) != 0 &&
|
|
|
|
(softc->quirks & DA_Q_NO_SYNC_CACHE) == 0 &&
|
|
|
|
(softc->flags & DA_FLAG_PACK_INVALID) == 0) {
|
|
|
|
ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
|
|
|
|
scsi_synchronize_cache(&ccb->csio, /*retries*/1,
|
|
|
|
/*cbfcnp*/dadone, MSG_SIMPLE_Q_TAG,
|
|
|
|
/*begin_lba*/0, /*lb_count*/0, SSD_FULL_SIZE,
|
|
|
|
5 * 60 * 1000);
|
|
|
|
error = cam_periph_runccb(ccb, daerror, /*cam_flags*/0,
|
|
|
|
/*sense_flags*/SF_RETRY_UA | SF_QUIET_IR,
|
|
|
|
softc->disk->d_devstat);
|
|
|
|
if (error == 0)
|
|
|
|
softc->flags &= ~DA_FLAG_DIRTY;
|
|
|
|
xpt_release_ccb(ccb);
|
|
|
|
}
|
1998-10-08 05:46:38 +00:00
|
|
|
|
Merge CAM locking changes from the projects/camlock branch to radically
reduce lock congestion and improve SMP scalability of the SCSI/ATA stack,
preparing the ground for the coming next GEOM direct dispatch support.
Replace big per-SIM locks with bunch of smaller ones:
- per-LUN locks to protect device and peripheral drivers state;
- per-target locks to protect list of LUNs on target;
- per-bus locks to protect reference counting;
- per-send queue locks to protect queue of CCBs to be sent;
- per-done queue locks to protect queue of completed CCBs;
- remaining per-SIM locks now protect only HBA driver internals.
While holding LUN lock it is allowed (while not recommended for performance
reasons) to take SIM lock. The opposite acquisition order is forbidden.
All the other locks are leaf locks, that can be taken anywhere, but should
not be cascaded. Many functions, such as: xpt_action(), xpt_done(),
xpt_async(), xpt_create_path(), etc. are no longer require (but allow) SIM
lock to be held.
To keep compatibility and solve cases where SIM lock can't be dropped, all
xpt_async() calls in addition to xpt_done() calls are queued to completion
threads for async processing in clean environment without SIM lock held.
Instead of single CAM SWI thread, used for commands completion processing
before, use multiple (depending on number of CPUs) threads. Load balanced
between them using "hash" of the device B:T:L address.
HBA drivers that can drop SIM lock during completion processing and have
sufficient number of completion threads to efficiently scale to multiple
CPUs can use new function xpt_done_direct() to avoid extra context switch.
Make ahci(4) driver to use this mechanism depending on hardware setup.
Sponsored by: iXsystems, Inc.
MFC after: 2 months
2013-10-21 12:00:26 +00:00
|
|
|
/* Allow medium removal. */
|
|
|
|
if ((softc->flags & DA_FLAG_PACK_REMOVABLE) != 0 &&
|
|
|
|
(softc->quirks & DA_Q_NO_PREVENT) == 0)
|
|
|
|
daprevent(periph, PR_ALLOW);
|
1998-10-08 05:46:38 +00:00
|
|
|
|
Merge CAM locking changes from the projects/camlock branch to radically
reduce lock congestion and improve SMP scalability of the SCSI/ATA stack,
preparing the ground for the coming next GEOM direct dispatch support.
Replace big per-SIM locks with bunch of smaller ones:
- per-LUN locks to protect device and peripheral drivers state;
- per-target locks to protect list of LUNs on target;
- per-bus locks to protect reference counting;
- per-send queue locks to protect queue of CCBs to be sent;
- per-done queue locks to protect queue of completed CCBs;
- remaining per-SIM locks now protect only HBA driver internals.
While holding LUN lock it is allowed (while not recommended for performance
reasons) to take SIM lock. The opposite acquisition order is forbidden.
All the other locks are leaf locks, that can be taken anywhere, but should
not be cascaded. Many functions, such as: xpt_action(), xpt_done(),
xpt_async(), xpt_create_path(), etc. are no longer require (but allow) SIM
lock to be held.
To keep compatibility and solve cases where SIM lock can't be dropped, all
xpt_async() calls in addition to xpt_done() calls are queued to completion
threads for async processing in clean environment without SIM lock held.
Instead of single CAM SWI thread, used for commands completion processing
before, use multiple (depending on number of CPUs) threads. Load balanced
between them using "hash" of the device B:T:L address.
HBA drivers that can drop SIM lock during completion processing and have
sufficient number of completion threads to efficiently scale to multiple
CPUs can use new function xpt_done_direct() to avoid extra context switch.
Make ahci(4) driver to use this mechanism depending on hardware setup.
Sponsored by: iXsystems, Inc.
MFC after: 2 months
2013-10-21 12:00:26 +00:00
|
|
|
cam_periph_unhold(periph);
|
1998-10-08 05:46:38 +00:00
|
|
|
}
|
1998-09-19 04:59:35 +00:00
|
|
|
|
Merge CAM locking changes from the projects/camlock branch to radically
reduce lock congestion and improve SMP scalability of the SCSI/ATA stack,
preparing the ground for the coming next GEOM direct dispatch support.
Replace big per-SIM locks with bunch of smaller ones:
- per-LUN locks to protect device and peripheral drivers state;
- per-target locks to protect list of LUNs on target;
- per-bus locks to protect reference counting;
- per-send queue locks to protect queue of CCBs to be sent;
- per-done queue locks to protect queue of completed CCBs;
- remaining per-SIM locks now protect only HBA driver internals.
While holding LUN lock it is allowed (while not recommended for performance
reasons) to take SIM lock. The opposite acquisition order is forbidden.
All the other locks are leaf locks, that can be taken anywhere, but should
not be cascaded. Many functions, such as: xpt_action(), xpt_done(),
xpt_async(), xpt_create_path(), etc. are no longer require (but allow) SIM
lock to be held.
To keep compatibility and solve cases where SIM lock can't be dropped, all
xpt_async() calls in addition to xpt_done() calls are queued to completion
threads for async processing in clean environment without SIM lock held.
Instead of single CAM SWI thread, used for commands completion processing
before, use multiple (depending on number of CPUs) threads. Load balanced
between them using "hash" of the device B:T:L address.
HBA drivers that can drop SIM lock during completion processing and have
sufficient number of completion threads to efficiently scale to multiple
CPUs can use new function xpt_done_direct() to avoid extra context switch.
Make ahci(4) driver to use this mechanism depending on hardware setup.
Sponsored by: iXsystems, Inc.
MFC after: 2 months
2013-10-21 12:00:26 +00:00
|
|
|
/*
|
|
|
|
* If we've got removeable media, mark the blocksize as
|
|
|
|
* unavailable, since it could change when new media is
|
|
|
|
* inserted.
|
|
|
|
*/
|
|
|
|
if ((softc->flags & DA_FLAG_PACK_REMOVABLE) != 0)
|
2004-02-18 21:36:53 +00:00
|
|
|
softc->disk->d_devstat->flags |= DEVSTAT_BS_UNAVAILABLE;
|
1998-09-15 06:36:34 +00:00
|
|
|
|
|
|
|
softc->flags &= ~DA_FLAG_OPEN;
|
Merge CAM locking changes from the projects/camlock branch to radically
reduce lock congestion and improve SMP scalability of the SCSI/ATA stack,
preparing the ground for the coming next GEOM direct dispatch support.
Replace big per-SIM locks with bunch of smaller ones:
- per-LUN locks to protect device and peripheral drivers state;
- per-target locks to protect list of LUNs on target;
- per-bus locks to protect reference counting;
- per-send queue locks to protect queue of CCBs to be sent;
- per-done queue locks to protect queue of completed CCBs;
- remaining per-SIM locks now protect only HBA driver internals.
While holding LUN lock it is allowed (while not recommended for performance
reasons) to take SIM lock. The opposite acquisition order is forbidden.
All the other locks are leaf locks, that can be taken anywhere, but should
not be cascaded. Many functions, such as: xpt_action(), xpt_done(),
xpt_async(), xpt_create_path(), etc. are no longer require (but allow) SIM
lock to be held.
To keep compatibility and solve cases where SIM lock can't be dropped, all
xpt_async() calls in addition to xpt_done() calls are queued to completion
threads for async processing in clean environment without SIM lock held.
Instead of single CAM SWI thread, used for commands completion processing
before, use multiple (depending on number of CPUs) threads. Load balanced
between them using "hash" of the device B:T:L address.
HBA drivers that can drop SIM lock during completion processing and have
sufficient number of completion threads to efficiently scale to multiple
CPUs can use new function xpt_done_direct() to avoid extra context switch.
Make ahci(4) driver to use this mechanism depending on hardware setup.
Sponsored by: iXsystems, Inc.
MFC after: 2 months
2013-10-21 12:00:26 +00:00
|
|
|
while (softc->refcount != 0)
|
|
|
|
cam_periph_sleep(periph, &softc->refcount, PRIBIO, "daclose", 1);
|
2008-12-17 10:49:03 +00:00
|
|
|
cam_periph_unlock(periph);
|
2008-12-19 14:31:40 +00:00
|
|
|
cam_periph_release(periph);
|
Merge CAM locking changes from the projects/camlock branch to radically
reduce lock congestion and improve SMP scalability of the SCSI/ATA stack,
preparing the ground for the coming next GEOM direct dispatch support.
Replace big per-SIM locks with bunch of smaller ones:
- per-LUN locks to protect device and peripheral drivers state;
- per-target locks to protect list of LUNs on target;
- per-bus locks to protect reference counting;
- per-send queue locks to protect queue of CCBs to be sent;
- per-done queue locks to protect queue of completed CCBs;
- remaining per-SIM locks now protect only HBA driver internals.
While holding LUN lock it is allowed (while not recommended for performance
reasons) to take SIM lock. The opposite acquisition order is forbidden.
All the other locks are leaf locks, that can be taken anywhere, but should
not be cascaded. Many functions, such as: xpt_action(), xpt_done(),
xpt_async(), xpt_create_path(), etc. are no longer require (but allow) SIM
lock to be held.
To keep compatibility and solve cases where SIM lock can't be dropped, all
xpt_async() calls in addition to xpt_done() calls are queued to completion
threads for async processing in clean environment without SIM lock held.
Instead of single CAM SWI thread, used for commands completion processing
before, use multiple (depending on number of CPUs) threads. Load balanced
between them using "hash" of the device B:T:L address.
HBA drivers that can drop SIM lock during completion processing and have
sufficient number of completion threads to efficiently scale to multiple
CPUs can use new function xpt_done_direct() to avoid extra context switch.
Make ahci(4) driver to use this mechanism depending on hardware setup.
Sponsored by: iXsystems, Inc.
MFC after: 2 months
2013-10-21 12:00:26 +00:00
|
|
|
return (0);
|
1998-09-15 06:36:34 +00:00
|
|
|
}
|
|
|
|
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
static void
|
|
|
|
daschedule(struct cam_periph *periph)
|
|
|
|
{
|
|
|
|
struct da_softc *softc = (struct da_softc *)periph->softc;
|
|
|
|
|
2013-01-11 16:10:11 +00:00
|
|
|
if (softc->state != DA_STATE_NORMAL)
|
|
|
|
return;
|
|
|
|
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
/* Check if we have more work to do. */
|
|
|
|
if (bioq_first(&softc->bio_queue) ||
|
2012-07-29 11:51:48 +00:00
|
|
|
(!softc->delete_running && bioq_first(&softc->delete_queue)) ||
|
|
|
|
softc->tur) {
|
Merge CAM locking changes from the projects/camlock branch to radically
reduce lock congestion and improve SMP scalability of the SCSI/ATA stack,
preparing the ground for the coming next GEOM direct dispatch support.
Replace big per-SIM locks with bunch of smaller ones:
- per-LUN locks to protect device and peripheral drivers state;
- per-target locks to protect list of LUNs on target;
- per-bus locks to protect reference counting;
- per-send queue locks to protect queue of CCBs to be sent;
- per-done queue locks to protect queue of completed CCBs;
- remaining per-SIM locks now protect only HBA driver internals.
While holding LUN lock it is allowed (while not recommended for performance
reasons) to take SIM lock. The opposite acquisition order is forbidden.
All the other locks are leaf locks, that can be taken anywhere, but should
not be cascaded. Many functions, such as: xpt_action(), xpt_done(),
xpt_async(), xpt_create_path(), etc. are no longer require (but allow) SIM
lock to be held.
To keep compatibility and solve cases where SIM lock can't be dropped, all
xpt_async() calls in addition to xpt_done() calls are queued to completion
threads for async processing in clean environment without SIM lock held.
Instead of single CAM SWI thread, used for commands completion processing
before, use multiple (depending on number of CPUs) threads. Load balanced
between them using "hash" of the device B:T:L address.
HBA drivers that can drop SIM lock during completion processing and have
sufficient number of completion threads to efficiently scale to multiple
CPUs can use new function xpt_done_direct() to avoid extra context switch.
Make ahci(4) driver to use this mechanism depending on hardware setup.
Sponsored by: iXsystems, Inc.
MFC after: 2 months
2013-10-21 12:00:26 +00:00
|
|
|
xpt_schedule(periph, CAM_PRIORITY_NORMAL);
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-09-15 06:36:34 +00:00
|
|
|
/*
|
|
|
|
* Actually translate the requested transfer into one the physical driver
|
|
|
|
* can understand. The transfer is described by a buf and will include
|
|
|
|
* only one physical transfer.
|
|
|
|
*/
|
|
|
|
static void
|
2000-04-15 05:54:02 +00:00
|
|
|
dastrategy(struct bio *bp)
|
1998-09-15 06:36:34 +00:00
|
|
|
{
|
|
|
|
struct cam_periph *periph;
|
|
|
|
struct da_softc *softc;
|
|
|
|
|
2003-02-25 22:06:21 +00:00
|
|
|
periph = (struct cam_periph *)bp->bio_disk->d_drv1;
|
1998-09-15 06:36:34 +00:00
|
|
|
softc = (struct da_softc *)periph->softc;
|
2007-04-15 08:49:19 +00:00
|
|
|
|
|
|
|
cam_periph_lock(periph);
|
|
|
|
|
1998-09-15 06:36:34 +00:00
|
|
|
/*
|
|
|
|
* If the device has been made invalid, error out
|
|
|
|
*/
|
|
|
|
if ((softc->flags & DA_FLAG_PACK_INVALID)) {
|
2007-04-15 08:49:19 +00:00
|
|
|
cam_periph_unlock(periph);
|
2001-05-08 08:30:48 +00:00
|
|
|
biofinish(bp, NULL, ENXIO);
|
|
|
|
return;
|
1998-09-15 06:36:34 +00:00
|
|
|
}
|
2012-06-05 09:45:42 +00:00
|
|
|
|
|
|
|
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("dastrategy(%p)\n", bp));
|
|
|
|
|
1998-09-15 06:36:34 +00:00
|
|
|
/*
|
|
|
|
* Place it in the queue of disk activities for this disk
|
2007-06-16 18:20:29 +00:00
|
|
|
*/
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
if (bp->bio_cmd == BIO_DELETE) {
|
2014-06-05 17:13:42 +00:00
|
|
|
bioq_disksort(&softc->delete_queue, bp);
|
2013-03-29 22:58:15 +00:00
|
|
|
} else if (DA_SIO) {
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
bioq_disksort(&softc->bio_queue, bp);
|
2013-03-29 22:58:15 +00:00
|
|
|
} else {
|
|
|
|
bioq_insert_tail(&softc->bio_queue, bp);
|
|
|
|
}
|
1998-09-15 06:36:34 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Schedule ourselves for performing the work.
|
|
|
|
*/
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
daschedule(periph);
|
2007-04-15 08:49:19 +00:00
|
|
|
cam_periph_unlock(periph);
|
1998-09-15 06:36:34 +00:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2003-02-21 19:00:48 +00:00
|
|
|
dadump(void *arg, void *virtual, vm_offset_t physical, off_t offset, size_t length)
|
1998-09-15 06:36:34 +00:00
|
|
|
{
|
1998-12-11 03:54:43 +00:00
|
|
|
struct cam_periph *periph;
|
|
|
|
struct da_softc *softc;
|
1999-10-01 09:34:10 +00:00
|
|
|
u_int secsize;
|
1998-12-11 03:54:43 +00:00
|
|
|
struct ccb_scsiio csio;
|
2003-02-21 19:00:48 +00:00
|
|
|
struct disk *dp;
|
One more major cam_periph_error() rewrite to improve error handling and
reporting. It includes:
- removing of error messages controlled by bootverbose, replacing them
with more universal and informative debugging on CAM_DEBUG_INFO level,
that is now built into the kernel by default;
- more close following to the arguments submitted by caller, such as
SF_PRINT_ALWAYS, SF_QUIET_IR and SF_NO_PRINT; consumer knows better which
errors are usual/expected at this point and which are really informative;
- adding two new flags SF_NO_RECOVERY and SF_NO_RETRY to allow caller
specify how much assistance it needs at this point; previously consumers
controlled that by not calling cam_periph_error() at all, but that made
behavior inconsistent and debugging complicated;
- tuning debug messages and taken actions order to make debugging output
more readable and cause-effect relationships visible;
- making camperiphdone() (common device recovery completion handler) to
also use cam_periph_error() in most cases, instead of own dumb code;
- removing manual sense fetching code from cam_periph_error(); I was told
by number of people that it is SIM obligation to fetch sense data, so this
code is useless and only significantly complicates recovery logic;
- making ada, da and pass driver to use cam_periph_error() with new limited
recovery options to handle error recovery and debugging in common way;
as one of results, CAM_REQUEUE_REQ and other retrying statuses are now
working fine with pass driver, that caused many problems before.
- reverting r186891 by raj@ to avoid burning few seconds in tight DELAY()
loops on device probe, while device simply loads media; I think that problem
may already be fixed in other way, and even if it is not, solution must be
different.
Sponsored by: iXsystems, Inc.
MFC after: 2 weeks
2012-06-09 13:07:44 +00:00
|
|
|
int error = 0;
|
1998-09-15 06:36:34 +00:00
|
|
|
|
2003-02-21 19:00:48 +00:00
|
|
|
dp = arg;
|
2003-02-25 22:06:21 +00:00
|
|
|
periph = dp->d_drv1;
|
1998-09-15 06:36:34 +00:00
|
|
|
softc = (struct da_softc *)periph->softc;
|
2007-04-18 05:14:16 +00:00
|
|
|
cam_periph_lock(periph);
|
2002-03-31 22:28:03 +00:00
|
|
|
secsize = softc->params.secsize;
|
1998-09-15 06:36:34 +00:00
|
|
|
|
2007-04-18 05:14:16 +00:00
|
|
|
if ((softc->flags & DA_FLAG_PACK_INVALID) != 0) {
|
|
|
|
cam_periph_unlock(periph);
|
1998-09-15 06:36:34 +00:00
|
|
|
return (ENXIO);
|
2007-04-18 05:14:16 +00:00
|
|
|
}
|
1998-09-15 06:36:34 +00:00
|
|
|
|
2002-03-31 22:28:03 +00:00
|
|
|
if (length > 0) {
|
2009-10-23 08:27:55 +00:00
|
|
|
xpt_setup_ccb(&csio.ccb_h, periph->path, CAM_PRIORITY_NORMAL);
|
1998-09-15 06:36:34 +00:00
|
|
|
csio.ccb_h.ccb_state = DA_CCB_DUMP;
|
|
|
|
scsi_read_write(&csio,
|
One more major cam_periph_error() rewrite to improve error handling and
reporting. It includes:
- removing of error messages controlled by bootverbose, replacing them
with more universal and informative debugging on CAM_DEBUG_INFO level,
that is now built into the kernel by default;
- more close following to the arguments submitted by caller, such as
SF_PRINT_ALWAYS, SF_QUIET_IR and SF_NO_PRINT; consumer knows better which
errors are usual/expected at this point and which are really informative;
- adding two new flags SF_NO_RECOVERY and SF_NO_RETRY to allow caller
specify how much assistance it needs at this point; previously consumers
controlled that by not calling cam_periph_error() at all, but that made
behavior inconsistent and debugging complicated;
- tuning debug messages and taken actions order to make debugging output
more readable and cause-effect relationships visible;
- making camperiphdone() (common device recovery completion handler) to
also use cam_periph_error() in most cases, instead of own dumb code;
- removing manual sense fetching code from cam_periph_error(); I was told
by number of people that it is SIM obligation to fetch sense data, so this
code is useless and only significantly complicates recovery logic;
- making ada, da and pass driver to use cam_periph_error() with new limited
recovery options to handle error recovery and debugging in common way;
as one of results, CAM_REQUEUE_REQ and other retrying statuses are now
working fine with pass driver, that caused many problems before.
- reverting r186891 by raj@ to avoid burning few seconds in tight DELAY()
loops on device probe, while device simply loads media; I think that problem
may already be fixed in other way, and even if it is not, solution must be
different.
Sponsored by: iXsystems, Inc.
MFC after: 2 weeks
2012-06-09 13:07:44 +00:00
|
|
|
/*retries*/0,
|
1998-09-15 06:36:34 +00:00
|
|
|
dadone,
|
|
|
|
MSG_ORDERED_Q_TAG,
|
2013-03-19 15:01:50 +00:00
|
|
|
/*read*/SCSI_RW_WRITE,
|
1998-09-15 06:36:34 +00:00
|
|
|
/*byte2*/0,
|
1998-12-02 17:35:28 +00:00
|
|
|
/*minimum_cmd_size*/ softc->minimum_cmd_size,
|
2002-03-31 22:28:03 +00:00
|
|
|
offset / secsize,
|
|
|
|
length / secsize,
|
|
|
|
/*data_ptr*/(u_int8_t *) virtual,
|
|
|
|
/*dxfer_len*/length,
|
1998-09-15 06:36:34 +00:00
|
|
|
/*sense_len*/SSD_FULL_SIZE,
|
2012-02-02 19:02:15 +00:00
|
|
|
da_default_timeout * 1000);
|
1998-09-15 06:36:34 +00:00
|
|
|
xpt_polled_action((union ccb *)&csio);
|
|
|
|
|
One more major cam_periph_error() rewrite to improve error handling and
reporting. It includes:
- removing of error messages controlled by bootverbose, replacing them
with more universal and informative debugging on CAM_DEBUG_INFO level,
that is now built into the kernel by default;
- more close following to the arguments submitted by caller, such as
SF_PRINT_ALWAYS, SF_QUIET_IR and SF_NO_PRINT; consumer knows better which
errors are usual/expected at this point and which are really informative;
- adding two new flags SF_NO_RECOVERY and SF_NO_RETRY to allow caller
specify how much assistance it needs at this point; previously consumers
controlled that by not calling cam_periph_error() at all, but that made
behavior inconsistent and debugging complicated;
- tuning debug messages and taken actions order to make debugging output
more readable and cause-effect relationships visible;
- making camperiphdone() (common device recovery completion handler) to
also use cam_periph_error() in most cases, instead of own dumb code;
- removing manual sense fetching code from cam_periph_error(); I was told
by number of people that it is SIM obligation to fetch sense data, so this
code is useless and only significantly complicates recovery logic;
- making ada, da and pass driver to use cam_periph_error() with new limited
recovery options to handle error recovery and debugging in common way;
as one of results, CAM_REQUEUE_REQ and other retrying statuses are now
working fine with pass driver, that caused many problems before.
- reverting r186891 by raj@ to avoid burning few seconds in tight DELAY()
loops on device probe, while device simply loads media; I think that problem
may already be fixed in other way, and even if it is not, solution must be
different.
Sponsored by: iXsystems, Inc.
MFC after: 2 weeks
2012-06-09 13:07:44 +00:00
|
|
|
error = cam_periph_error((union ccb *)&csio,
|
|
|
|
0, SF_NO_RECOVERY | SF_NO_RETRY, NULL);
|
|
|
|
if ((csio.ccb_h.status & CAM_DEV_QFRZN) != 0)
|
|
|
|
cam_release_devq(csio.ccb_h.path, /*relsim_flags*/0,
|
|
|
|
/*reduction*/0, /*timeout*/0, /*getcount_only*/0);
|
|
|
|
if (error != 0)
|
1998-10-08 05:46:38 +00:00
|
|
|
printf("Aborting dump due to I/O error.\n");
|
One more major cam_periph_error() rewrite to improve error handling and
reporting. It includes:
- removing of error messages controlled by bootverbose, replacing them
with more universal and informative debugging on CAM_DEBUG_INFO level,
that is now built into the kernel by default;
- more close following to the arguments submitted by caller, such as
SF_PRINT_ALWAYS, SF_QUIET_IR and SF_NO_PRINT; consumer knows better which
errors are usual/expected at this point and which are really informative;
- adding two new flags SF_NO_RECOVERY and SF_NO_RETRY to allow caller
specify how much assistance it needs at this point; previously consumers
controlled that by not calling cam_periph_error() at all, but that made
behavior inconsistent and debugging complicated;
- tuning debug messages and taken actions order to make debugging output
more readable and cause-effect relationships visible;
- making camperiphdone() (common device recovery completion handler) to
also use cam_periph_error() in most cases, instead of own dumb code;
- removing manual sense fetching code from cam_periph_error(); I was told
by number of people that it is SIM obligation to fetch sense data, so this
code is useless and only significantly complicates recovery logic;
- making ada, da and pass driver to use cam_periph_error() with new limited
recovery options to handle error recovery and debugging in common way;
as one of results, CAM_REQUEUE_REQ and other retrying statuses are now
working fine with pass driver, that caused many problems before.
- reverting r186891 by raj@ to avoid burning few seconds in tight DELAY()
loops on device probe, while device simply loads media; I think that problem
may already be fixed in other way, and even if it is not, solution must be
different.
Sponsored by: iXsystems, Inc.
MFC after: 2 weeks
2012-06-09 13:07:44 +00:00
|
|
|
cam_periph_unlock(periph);
|
|
|
|
return (error);
|
2007-04-15 08:49:19 +00:00
|
|
|
}
|
1998-09-15 06:36:34 +00:00
|
|
|
|
1998-10-08 05:46:38 +00:00
|
|
|
/*
|
|
|
|
* Sync the disk cache contents to the physical media.
|
|
|
|
*/
|
|
|
|
if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0) {
|
|
|
|
|
2009-10-23 08:27:55 +00:00
|
|
|
xpt_setup_ccb(&csio.ccb_h, periph->path, CAM_PRIORITY_NORMAL);
|
1998-10-08 05:46:38 +00:00
|
|
|
csio.ccb_h.ccb_state = DA_CCB_DUMP;
|
|
|
|
scsi_synchronize_cache(&csio,
|
One more major cam_periph_error() rewrite to improve error handling and
reporting. It includes:
- removing of error messages controlled by bootverbose, replacing them
with more universal and informative debugging on CAM_DEBUG_INFO level,
that is now built into the kernel by default;
- more close following to the arguments submitted by caller, such as
SF_PRINT_ALWAYS, SF_QUIET_IR and SF_NO_PRINT; consumer knows better which
errors are usual/expected at this point and which are really informative;
- adding two new flags SF_NO_RECOVERY and SF_NO_RETRY to allow caller
specify how much assistance it needs at this point; previously consumers
controlled that by not calling cam_periph_error() at all, but that made
behavior inconsistent and debugging complicated;
- tuning debug messages and taken actions order to make debugging output
more readable and cause-effect relationships visible;
- making camperiphdone() (common device recovery completion handler) to
also use cam_periph_error() in most cases, instead of own dumb code;
- removing manual sense fetching code from cam_periph_error(); I was told
by number of people that it is SIM obligation to fetch sense data, so this
code is useless and only significantly complicates recovery logic;
- making ada, da and pass driver to use cam_periph_error() with new limited
recovery options to handle error recovery and debugging in common way;
as one of results, CAM_REQUEUE_REQ and other retrying statuses are now
working fine with pass driver, that caused many problems before.
- reverting r186891 by raj@ to avoid burning few seconds in tight DELAY()
loops on device probe, while device simply loads media; I think that problem
may already be fixed in other way, and even if it is not, solution must be
different.
Sponsored by: iXsystems, Inc.
MFC after: 2 weeks
2012-06-09 13:07:44 +00:00
|
|
|
/*retries*/0,
|
1998-10-08 05:46:38 +00:00
|
|
|
/*cbfcnp*/dadone,
|
|
|
|
MSG_SIMPLE_Q_TAG,
|
|
|
|
/*begin_lba*/0,/* Cover the whole disk */
|
|
|
|
/*lb_count*/0,
|
|
|
|
SSD_FULL_SIZE,
|
|
|
|
5 * 60 * 1000);
|
|
|
|
xpt_polled_action((union ccb *)&csio);
|
|
|
|
|
One more major cam_periph_error() rewrite to improve error handling and
reporting. It includes:
- removing of error messages controlled by bootverbose, replacing them
with more universal and informative debugging on CAM_DEBUG_INFO level,
that is now built into the kernel by default;
- more close following to the arguments submitted by caller, such as
SF_PRINT_ALWAYS, SF_QUIET_IR and SF_NO_PRINT; consumer knows better which
errors are usual/expected at this point and which are really informative;
- adding two new flags SF_NO_RECOVERY and SF_NO_RETRY to allow caller
specify how much assistance it needs at this point; previously consumers
controlled that by not calling cam_periph_error() at all, but that made
behavior inconsistent and debugging complicated;
- tuning debug messages and taken actions order to make debugging output
more readable and cause-effect relationships visible;
- making camperiphdone() (common device recovery completion handler) to
also use cam_periph_error() in most cases, instead of own dumb code;
- removing manual sense fetching code from cam_periph_error(); I was told
by number of people that it is SIM obligation to fetch sense data, so this
code is useless and only significantly complicates recovery logic;
- making ada, da and pass driver to use cam_periph_error() with new limited
recovery options to handle error recovery and debugging in common way;
as one of results, CAM_REQUEUE_REQ and other retrying statuses are now
working fine with pass driver, that caused many problems before.
- reverting r186891 by raj@ to avoid burning few seconds in tight DELAY()
loops on device probe, while device simply loads media; I think that problem
may already be fixed in other way, and even if it is not, solution must be
different.
Sponsored by: iXsystems, Inc.
MFC after: 2 weeks
2012-06-09 13:07:44 +00:00
|
|
|
error = cam_periph_error((union ccb *)&csio,
|
|
|
|
0, SF_NO_RECOVERY | SF_NO_RETRY | SF_QUIET_IR, NULL);
|
|
|
|
if ((csio.ccb_h.status & CAM_DEV_QFRZN) != 0)
|
|
|
|
cam_release_devq(csio.ccb_h.path, /*relsim_flags*/0,
|
|
|
|
/*reduction*/0, /*timeout*/0, /*getcount_only*/0);
|
|
|
|
if (error != 0)
|
|
|
|
xpt_print(periph->path, "Synchronize cache failed\n");
|
1998-10-08 05:46:38 +00:00
|
|
|
}
|
2007-04-18 05:14:16 +00:00
|
|
|
cam_periph_unlock(periph);
|
One more major cam_periph_error() rewrite to improve error handling and
reporting. It includes:
- removing of error messages controlled by bootverbose, replacing them
with more universal and informative debugging on CAM_DEBUG_INFO level,
that is now built into the kernel by default;
- more close following to the arguments submitted by caller, such as
SF_PRINT_ALWAYS, SF_QUIET_IR and SF_NO_PRINT; consumer knows better which
errors are usual/expected at this point and which are really informative;
- adding two new flags SF_NO_RECOVERY and SF_NO_RETRY to allow caller
specify how much assistance it needs at this point; previously consumers
controlled that by not calling cam_periph_error() at all, but that made
behavior inconsistent and debugging complicated;
- tuning debug messages and taken actions order to make debugging output
more readable and cause-effect relationships visible;
- making camperiphdone() (common device recovery completion handler) to
also use cam_periph_error() in most cases, instead of own dumb code;
- removing manual sense fetching code from cam_periph_error(); I was told
by number of people that it is SIM obligation to fetch sense data, so this
code is useless and only significantly complicates recovery logic;
- making ada, da and pass driver to use cam_periph_error() with new limited
recovery options to handle error recovery and debugging in common way;
as one of results, CAM_REQUEUE_REQ and other retrying statuses are now
working fine with pass driver, that caused many problems before.
- reverting r186891 by raj@ to avoid burning few seconds in tight DELAY()
loops on device probe, while device simply loads media; I think that problem
may already be fixed in other way, and even if it is not, solution must be
different.
Sponsored by: iXsystems, Inc.
MFC after: 2 weeks
2012-06-09 13:07:44 +00:00
|
|
|
return (error);
|
1998-09-15 06:36:34 +00:00
|
|
|
}
|
|
|
|
|
Plumb device physical path reporting from CAM devices, through GEOM and
DEVFS, and make it accessible via the diskinfo utility.
Extend GEOM's generic attribute query mechanism into generic disk consumers.
sys/geom/geom_disk.c:
sys/geom/geom_disk.h:
sys/cam/scsi/scsi_da.c:
sys/cam/ata/ata_da.c:
- Allow disk providers to implement a new method which can override
the default BIO_GETATTR response, d_getattr(struct bio *). This
function returns -1 if not handled, otherwise it returns 0 or an
errno to be passed to g_io_deliver().
sys/cam/scsi/scsi_da.c:
sys/cam/ata/ata_da.c:
- Don't copy the serial number to dp->d_ident anymore, as the CAM XPT
is now responsible for returning this information via
d_getattr()->(a)dagetattr()->xpt_getatr().
sys/geom/geom_dev.c:
- Implement a new ioctl, DIOCGPHYSPATH, which returns the GEOM
attribute "GEOM::physpath", if possible. If the attribute request
returns a zero-length string, ENOENT is returned.
usr.sbin/diskinfo/diskinfo.c:
- If the DIOCGPHYSPATH ioctl is successful, report physical path
data when diskinfo is executed with the '-v' option.
Submitted by: will
Reviewed by: gibbs
Sponsored by: Spectra Logic Corporation
Add generic attribute change notification support to GEOM.
sys/sys/geom/geom.h:
Add a new attrchanged method field to both g_class
and g_geom.
sys/sys/geom/geom.h:
sys/geom/geom_event.c:
- Provide the g_attr_changed() function that providers
can use to advertise attribute changes.
- Perform delivery of attribute change notifications
from a thread context via the standard GEOM event
mechanism.
sys/geom/geom_subr.c:
Inherit the attrchanged method from class to geom (class instance).
sys/geom/geom_disk.c:
Provide disk_attr_changed() to provide g_attr_changed() access
to consumers of the disk API.
sys/cam/scsi/scsi_pass.c:
sys/cam/scsi/scsi_da.c:
sys/geom/geom_dev.c:
sys/geom/geom_disk.c:
Use attribute changed events to track updates to physical path
information.
sys/cam/scsi/scsi_da.c:
Add AC_ADVINFO_CHANGED to the registered asynchronous CAM
events for this driver. When this event occurs, and
the updated buffer type references our physical path
attribute, emit a GEOM attribute changed event via the
disk_attr_changed() API.
sys/cam/scsi/scsi_pass.c:
Add AC_ADVINFO_CHANGED to the registered asynchronous CAM
events for this driver. When this event occurs, update
the physical patch devfs alias for this pass instance.
Submitted by: gibbs
Sponsored by: Spectra Logic Corporation
2011-06-14 17:10:32 +00:00
|
|
|
static int
|
|
|
|
dagetattr(struct bio *bp)
|
|
|
|
{
|
2012-10-12 17:18:24 +00:00
|
|
|
int ret;
|
Plumb device physical path reporting from CAM devices, through GEOM and
DEVFS, and make it accessible via the diskinfo utility.
Extend GEOM's generic attribute query mechanism into generic disk consumers.
sys/geom/geom_disk.c:
sys/geom/geom_disk.h:
sys/cam/scsi/scsi_da.c:
sys/cam/ata/ata_da.c:
- Allow disk providers to implement a new method which can override
the default BIO_GETATTR response, d_getattr(struct bio *). This
function returns -1 if not handled, otherwise it returns 0 or an
errno to be passed to g_io_deliver().
sys/cam/scsi/scsi_da.c:
sys/cam/ata/ata_da.c:
- Don't copy the serial number to dp->d_ident anymore, as the CAM XPT
is now responsible for returning this information via
d_getattr()->(a)dagetattr()->xpt_getatr().
sys/geom/geom_dev.c:
- Implement a new ioctl, DIOCGPHYSPATH, which returns the GEOM
attribute "GEOM::physpath", if possible. If the attribute request
returns a zero-length string, ENOENT is returned.
usr.sbin/diskinfo/diskinfo.c:
- If the DIOCGPHYSPATH ioctl is successful, report physical path
data when diskinfo is executed with the '-v' option.
Submitted by: will
Reviewed by: gibbs
Sponsored by: Spectra Logic Corporation
Add generic attribute change notification support to GEOM.
sys/sys/geom/geom.h:
Add a new attrchanged method field to both g_class
and g_geom.
sys/sys/geom/geom.h:
sys/geom/geom_event.c:
- Provide the g_attr_changed() function that providers
can use to advertise attribute changes.
- Perform delivery of attribute change notifications
from a thread context via the standard GEOM event
mechanism.
sys/geom/geom_subr.c:
Inherit the attrchanged method from class to geom (class instance).
sys/geom/geom_disk.c:
Provide disk_attr_changed() to provide g_attr_changed() access
to consumers of the disk API.
sys/cam/scsi/scsi_pass.c:
sys/cam/scsi/scsi_da.c:
sys/geom/geom_dev.c:
sys/geom/geom_disk.c:
Use attribute changed events to track updates to physical path
information.
sys/cam/scsi/scsi_da.c:
Add AC_ADVINFO_CHANGED to the registered asynchronous CAM
events for this driver. When this event occurs, and
the updated buffer type references our physical path
attribute, emit a GEOM attribute changed event via the
disk_attr_changed() API.
sys/cam/scsi/scsi_pass.c:
Add AC_ADVINFO_CHANGED to the registered asynchronous CAM
events for this driver. When this event occurs, update
the physical patch devfs alias for this pass instance.
Submitted by: gibbs
Sponsored by: Spectra Logic Corporation
2011-06-14 17:10:32 +00:00
|
|
|
struct cam_periph *periph;
|
|
|
|
|
|
|
|
periph = (struct cam_periph *)bp->bio_disk->d_drv1;
|
2012-10-12 17:18:24 +00:00
|
|
|
cam_periph_lock(periph);
|
Plumb device physical path reporting from CAM devices, through GEOM and
DEVFS, and make it accessible via the diskinfo utility.
Extend GEOM's generic attribute query mechanism into generic disk consumers.
sys/geom/geom_disk.c:
sys/geom/geom_disk.h:
sys/cam/scsi/scsi_da.c:
sys/cam/ata/ata_da.c:
- Allow disk providers to implement a new method which can override
the default BIO_GETATTR response, d_getattr(struct bio *). This
function returns -1 if not handled, otherwise it returns 0 or an
errno to be passed to g_io_deliver().
sys/cam/scsi/scsi_da.c:
sys/cam/ata/ata_da.c:
- Don't copy the serial number to dp->d_ident anymore, as the CAM XPT
is now responsible for returning this information via
d_getattr()->(a)dagetattr()->xpt_getatr().
sys/geom/geom_dev.c:
- Implement a new ioctl, DIOCGPHYSPATH, which returns the GEOM
attribute "GEOM::physpath", if possible. If the attribute request
returns a zero-length string, ENOENT is returned.
usr.sbin/diskinfo/diskinfo.c:
- If the DIOCGPHYSPATH ioctl is successful, report physical path
data when diskinfo is executed with the '-v' option.
Submitted by: will
Reviewed by: gibbs
Sponsored by: Spectra Logic Corporation
Add generic attribute change notification support to GEOM.
sys/sys/geom/geom.h:
Add a new attrchanged method field to both g_class
and g_geom.
sys/sys/geom/geom.h:
sys/geom/geom_event.c:
- Provide the g_attr_changed() function that providers
can use to advertise attribute changes.
- Perform delivery of attribute change notifications
from a thread context via the standard GEOM event
mechanism.
sys/geom/geom_subr.c:
Inherit the attrchanged method from class to geom (class instance).
sys/geom/geom_disk.c:
Provide disk_attr_changed() to provide g_attr_changed() access
to consumers of the disk API.
sys/cam/scsi/scsi_pass.c:
sys/cam/scsi/scsi_da.c:
sys/geom/geom_dev.c:
sys/geom/geom_disk.c:
Use attribute changed events to track updates to physical path
information.
sys/cam/scsi/scsi_da.c:
Add AC_ADVINFO_CHANGED to the registered asynchronous CAM
events for this driver. When this event occurs, and
the updated buffer type references our physical path
attribute, emit a GEOM attribute changed event via the
disk_attr_changed() API.
sys/cam/scsi/scsi_pass.c:
Add AC_ADVINFO_CHANGED to the registered asynchronous CAM
events for this driver. When this event occurs, update
the physical patch devfs alias for this pass instance.
Submitted by: gibbs
Sponsored by: Spectra Logic Corporation
2011-06-14 17:10:32 +00:00
|
|
|
ret = xpt_getattr(bp->bio_data, bp->bio_length, bp->bio_attribute,
|
|
|
|
periph->path);
|
2012-10-12 17:18:24 +00:00
|
|
|
cam_periph_unlock(periph);
|
Plumb device physical path reporting from CAM devices, through GEOM and
DEVFS, and make it accessible via the diskinfo utility.
Extend GEOM's generic attribute query mechanism into generic disk consumers.
sys/geom/geom_disk.c:
sys/geom/geom_disk.h:
sys/cam/scsi/scsi_da.c:
sys/cam/ata/ata_da.c:
- Allow disk providers to implement a new method which can override
the default BIO_GETATTR response, d_getattr(struct bio *). This
function returns -1 if not handled, otherwise it returns 0 or an
errno to be passed to g_io_deliver().
sys/cam/scsi/scsi_da.c:
sys/cam/ata/ata_da.c:
- Don't copy the serial number to dp->d_ident anymore, as the CAM XPT
is now responsible for returning this information via
d_getattr()->(a)dagetattr()->xpt_getatr().
sys/geom/geom_dev.c:
- Implement a new ioctl, DIOCGPHYSPATH, which returns the GEOM
attribute "GEOM::physpath", if possible. If the attribute request
returns a zero-length string, ENOENT is returned.
usr.sbin/diskinfo/diskinfo.c:
- If the DIOCGPHYSPATH ioctl is successful, report physical path
data when diskinfo is executed with the '-v' option.
Submitted by: will
Reviewed by: gibbs
Sponsored by: Spectra Logic Corporation
Add generic attribute change notification support to GEOM.
sys/sys/geom/geom.h:
Add a new attrchanged method field to both g_class
and g_geom.
sys/sys/geom/geom.h:
sys/geom/geom_event.c:
- Provide the g_attr_changed() function that providers
can use to advertise attribute changes.
- Perform delivery of attribute change notifications
from a thread context via the standard GEOM event
mechanism.
sys/geom/geom_subr.c:
Inherit the attrchanged method from class to geom (class instance).
sys/geom/geom_disk.c:
Provide disk_attr_changed() to provide g_attr_changed() access
to consumers of the disk API.
sys/cam/scsi/scsi_pass.c:
sys/cam/scsi/scsi_da.c:
sys/geom/geom_dev.c:
sys/geom/geom_disk.c:
Use attribute changed events to track updates to physical path
information.
sys/cam/scsi/scsi_da.c:
Add AC_ADVINFO_CHANGED to the registered asynchronous CAM
events for this driver. When this event occurs, and
the updated buffer type references our physical path
attribute, emit a GEOM attribute changed event via the
disk_attr_changed() API.
sys/cam/scsi/scsi_pass.c:
Add AC_ADVINFO_CHANGED to the registered asynchronous CAM
events for this driver. When this event occurs, update
the physical patch devfs alias for this pass instance.
Submitted by: gibbs
Sponsored by: Spectra Logic Corporation
2011-06-14 17:10:32 +00:00
|
|
|
if (ret == 0)
|
|
|
|
bp->bio_completed = bp->bio_length;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
1998-09-15 06:36:34 +00:00
|
|
|
static void
|
|
|
|
dainit(void)
|
|
|
|
{
|
|
|
|
cam_status status;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Install a global async callback. This callback will
|
|
|
|
* receive async callbacks like "new device found".
|
|
|
|
*/
|
2007-05-16 16:54:23 +00:00
|
|
|
status = xpt_register_async(AC_FOUND_DEVICE, daasync, NULL, NULL);
|
1998-09-15 06:36:34 +00:00
|
|
|
|
|
|
|
if (status != CAM_REQ_CMP) {
|
|
|
|
printf("da: Failed to attach master async callback "
|
|
|
|
"due to status 0x%x!\n", status);
|
2006-11-02 21:12:37 +00:00
|
|
|
} else if (da_send_ordered) {
|
1998-10-08 05:46:38 +00:00
|
|
|
|
1999-08-21 06:24:40 +00:00
|
|
|
/* Register our shutdown event handler */
|
|
|
|
if ((EVENTHANDLER_REGISTER(shutdown_post_sync, dashutdown,
|
2003-01-06 19:30:21 +00:00
|
|
|
NULL, SHUTDOWN_PRI_DEFAULT)) == NULL)
|
1999-08-21 06:24:40 +00:00
|
|
|
printf("dainit: shutdown event registration failed!\n");
|
1998-09-15 06:36:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Fix a bug which causes a panic in daopen(). The panic is caused by
a da(4) instance going away while GEOM is still probing it.
In this case, the GEOM disk class instance has been created by
disk_create(), and the taste of the disk is queued in the GEOM
event queue.
While that event is queued, the da(4) instance goes away. When the
open call comes into the da(4) driver, it dereferences the freed
(but non-NULL) peripheral pointer provided by GEOM, which results
in a panic.
The solution is to add a callback to the GEOM disk code that is
called when all of its resources are cleaned up. This is
implemented inside GEOM by adding an optional callback that is
called when all consumers have detached from a provider, and the
provider is about to be deleted.
scsi_cd.c,
scsi_da.c: In the register routine for the cd(4) and da(4)
routines, acquire a reference to the CAM peripheral
instance just before we call disk_create().
Use the new GEOM disk d_gone() callback to register
a callback (dadiskgonecb()/cddiskgonecb()) that
decrements the peripheral reference count once GEOM
has finished cleaning up its resources.
In the cd(4) driver, clean up open and close
behavior slightly. GEOM makes sure we only get one
open() and one close call, so there is no need to
set an open flag and decrement the reference count
if we are not the first open.
In the cd(4) driver, use cam_periph_release_locked()
in a couple of error scenarios to avoid extra mutex
calls.
geom.h: Add a new, optional, providergone callback that
is called when a provider is about to be deleted.
geom_disk.h: Add a new d_gone() callback to the GEOM disk
interface.
Bump the DISK_VERSION to version 2. This probably
should have been done after a couple of previous
changes, especially the addition of the d_getattr()
callback.
geom_disk.c: Add a providergone callback for the disk class,
g_disk_providergone(), that calls the user's
d_gone() callback if it exists.
Bump the DISK_VERSION to 2.
geom_subr.c: In g_destroy_provider(), call the providergone
callback if it has been provided.
In g_new_geomf(), propagate the class's
providergone callback to the new geom instance.
blkfront.c: Callers of disk_create() are supposed to pass in
DISK_VERSION, not an explicit disk API version
number. Update the blkfront driver to do that.
disk.9: Update the disk(9) man page to include information
on the new d_gone() callback, as well as the
previously added d_getattr() callback, d_descr
field, and HBA PCI ID fields.
MFC after: 5 days
2012-06-24 04:29:03 +00:00
|
|
|
/*
|
|
|
|
* Callback from GEOM, called when it has finished cleaning up its
|
|
|
|
* resources.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
dadiskgonecb(struct disk *dp)
|
|
|
|
{
|
|
|
|
struct cam_periph *periph;
|
|
|
|
|
|
|
|
periph = (struct cam_periph *)dp->d_drv1;
|
|
|
|
cam_periph_release(periph);
|
|
|
|
}
|
|
|
|
|
Fix a problem with the way we handled device invalidation when attaching
to a device failed.
In theory, the same steps that happen when we get an AC_LOST_DEVICE async
notification should have been taken when a driver fails to attach. In
practice, that wasn't the case.
This only affected the da, cd and ch drivers, but the fix affects all
peripheral drivers.
There were several possible problems:
- In the da driver, we didn't remove the peripheral's softc from the da
driver's linked list of softcs. Once the peripheral and softc got
removed, we'd get a kernel panic the next time the timeout routine
called dasendorderedtag().
- In the da, cd and possibly ch drivers, we didn't remove the
peripheral's devstat structure from the devstat queue. Once the
peripheral and softc were removed, this could cause a panic if anyone
tried to access device statistics. (one component of the linked list
wouldn't exist anymore)
- In the cd driver, we didn't take the peripheral off the changer run
queue if it was scheduled to run. In practice, it's highly unlikely,
and maybe impossible that the peripheral would have been on the
changer run queue at that stage of the probe process.
The fix is:
- Add a new peripheral callback function (the "oninvalidate" function)
that is called the first time cam_periph_invalidate() is called for a
peripheral.
- Create new foooninvalidate() routines for each peripheral driver. This
routine is always called at splsoftcam(), and contains all the stuff
that used to be in the AC_LOST_DEVICE case of the async callback
handler.
- Move the devstat cleanup call to the destructor/cleanup routines, since
some of the drivers do I/O in their close routines.
- Make sure that when we're flushing the buffer queue, we traverse it at
splbio().
- Add a check for the invalid flag in the pt driver's open routine.
Reviewed by: gibbs
1998-10-22 22:16:56 +00:00
|
|
|
static void
|
|
|
|
daoninvalidate(struct cam_periph *periph)
|
|
|
|
{
|
|
|
|
struct da_softc *softc;
|
|
|
|
|
|
|
|
softc = (struct da_softc *)periph->softc;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* De-register any async callbacks.
|
|
|
|
*/
|
2007-05-16 16:54:23 +00:00
|
|
|
xpt_register_async(0, daasync, periph, periph->path);
|
Fix a problem with the way we handled device invalidation when attaching
to a device failed.
In theory, the same steps that happen when we get an AC_LOST_DEVICE async
notification should have been taken when a driver fails to attach. In
practice, that wasn't the case.
This only affected the da, cd and ch drivers, but the fix affects all
peripheral drivers.
There were several possible problems:
- In the da driver, we didn't remove the peripheral's softc from the da
driver's linked list of softcs. Once the peripheral and softc got
removed, we'd get a kernel panic the next time the timeout routine
called dasendorderedtag().
- In the da, cd and possibly ch drivers, we didn't remove the
peripheral's devstat structure from the devstat queue. Once the
peripheral and softc were removed, this could cause a panic if anyone
tried to access device statistics. (one component of the linked list
wouldn't exist anymore)
- In the cd driver, we didn't take the peripheral off the changer run
queue if it was scheduled to run. In practice, it's highly unlikely,
and maybe impossible that the peripheral would have been on the
changer run queue at that stage of the probe process.
The fix is:
- Add a new peripheral callback function (the "oninvalidate" function)
that is called the first time cam_periph_invalidate() is called for a
peripheral.
- Create new foooninvalidate() routines for each peripheral driver. This
routine is always called at splsoftcam(), and contains all the stuff
that used to be in the AC_LOST_DEVICE case of the async callback
handler.
- Move the devstat cleanup call to the destructor/cleanup routines, since
some of the drivers do I/O in their close routines.
- Make sure that when we're flushing the buffer queue, we traverse it at
splbio().
- Add a check for the invalid flag in the pt driver's open routine.
Reviewed by: gibbs
1998-10-22 22:16:56 +00:00
|
|
|
|
|
|
|
softc->flags |= DA_FLAG_PACK_INVALID;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return all queued I/O with ENXIO.
|
2010-08-20 17:20:05 +00:00
|
|
|
* XXX Handle any transactions queued to the card
|
|
|
|
* with XPT_ABORT_CCB.
|
Fix a problem with the way we handled device invalidation when attaching
to a device failed.
In theory, the same steps that happen when we get an AC_LOST_DEVICE async
notification should have been taken when a driver fails to attach. In
practice, that wasn't the case.
This only affected the da, cd and ch drivers, but the fix affects all
peripheral drivers.
There were several possible problems:
- In the da driver, we didn't remove the peripheral's softc from the da
driver's linked list of softcs. Once the peripheral and softc got
removed, we'd get a kernel panic the next time the timeout routine
called dasendorderedtag().
- In the da, cd and possibly ch drivers, we didn't remove the
peripheral's devstat structure from the devstat queue. Once the
peripheral and softc were removed, this could cause a panic if anyone
tried to access device statistics. (one component of the linked list
wouldn't exist anymore)
- In the cd driver, we didn't take the peripheral off the changer run
queue if it was scheduled to run. In practice, it's highly unlikely,
and maybe impossible that the peripheral would have been on the
changer run queue at that stage of the probe process.
The fix is:
- Add a new peripheral callback function (the "oninvalidate" function)
that is called the first time cam_periph_invalidate() is called for a
peripheral.
- Create new foooninvalidate() routines for each peripheral driver. This
routine is always called at splsoftcam(), and contains all the stuff
that used to be in the AC_LOST_DEVICE case of the async callback
handler.
- Move the devstat cleanup call to the destructor/cleanup routines, since
some of the drivers do I/O in their close routines.
- Make sure that when we're flushing the buffer queue, we traverse it at
splbio().
- Add a check for the invalid flag in the pt driver's open routine.
Reviewed by: gibbs
1998-10-22 22:16:56 +00:00
|
|
|
*/
|
2003-04-01 15:06:26 +00:00
|
|
|
bioq_flush(&softc->bio_queue, NULL, ENXIO);
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
bioq_flush(&softc->delete_queue, NULL, ENXIO);
|
Fix a problem with the way we handled device invalidation when attaching
to a device failed.
In theory, the same steps that happen when we get an AC_LOST_DEVICE async
notification should have been taken when a driver fails to attach. In
practice, that wasn't the case.
This only affected the da, cd and ch drivers, but the fix affects all
peripheral drivers.
There were several possible problems:
- In the da driver, we didn't remove the peripheral's softc from the da
driver's linked list of softcs. Once the peripheral and softc got
removed, we'd get a kernel panic the next time the timeout routine
called dasendorderedtag().
- In the da, cd and possibly ch drivers, we didn't remove the
peripheral's devstat structure from the devstat queue. Once the
peripheral and softc were removed, this could cause a panic if anyone
tried to access device statistics. (one component of the linked list
wouldn't exist anymore)
- In the cd driver, we didn't take the peripheral off the changer run
queue if it was scheduled to run. In practice, it's highly unlikely,
and maybe impossible that the peripheral would have been on the
changer run queue at that stage of the probe process.
The fix is:
- Add a new peripheral callback function (the "oninvalidate" function)
that is called the first time cam_periph_invalidate() is called for a
peripheral.
- Create new foooninvalidate() routines for each peripheral driver. This
routine is always called at splsoftcam(), and contains all the stuff
that used to be in the AC_LOST_DEVICE case of the async callback
handler.
- Move the devstat cleanup call to the destructor/cleanup routines, since
some of the drivers do I/O in their close routines.
- Make sure that when we're flushing the buffer queue, we traverse it at
splbio().
- Add a check for the invalid flag in the pt driver's open routine.
Reviewed by: gibbs
1998-10-22 22:16:56 +00:00
|
|
|
|
Fix a bug which causes a panic in daopen(). The panic is caused by
a da(4) instance going away while GEOM is still probing it.
In this case, the GEOM disk class instance has been created by
disk_create(), and the taste of the disk is queued in the GEOM
event queue.
While that event is queued, the da(4) instance goes away. When the
open call comes into the da(4) driver, it dereferences the freed
(but non-NULL) peripheral pointer provided by GEOM, which results
in a panic.
The solution is to add a callback to the GEOM disk code that is
called when all of its resources are cleaned up. This is
implemented inside GEOM by adding an optional callback that is
called when all consumers have detached from a provider, and the
provider is about to be deleted.
scsi_cd.c,
scsi_da.c: In the register routine for the cd(4) and da(4)
routines, acquire a reference to the CAM peripheral
instance just before we call disk_create().
Use the new GEOM disk d_gone() callback to register
a callback (dadiskgonecb()/cddiskgonecb()) that
decrements the peripheral reference count once GEOM
has finished cleaning up its resources.
In the cd(4) driver, clean up open and close
behavior slightly. GEOM makes sure we only get one
open() and one close call, so there is no need to
set an open flag and decrement the reference count
if we are not the first open.
In the cd(4) driver, use cam_periph_release_locked()
in a couple of error scenarios to avoid extra mutex
calls.
geom.h: Add a new, optional, providergone callback that
is called when a provider is about to be deleted.
geom_disk.h: Add a new d_gone() callback to the GEOM disk
interface.
Bump the DISK_VERSION to version 2. This probably
should have been done after a couple of previous
changes, especially the addition of the d_getattr()
callback.
geom_disk.c: Add a providergone callback for the disk class,
g_disk_providergone(), that calls the user's
d_gone() callback if it exists.
Bump the DISK_VERSION to 2.
geom_subr.c: In g_destroy_provider(), call the providergone
callback if it has been provided.
In g_new_geomf(), propagate the class's
providergone callback to the new geom instance.
blkfront.c: Callers of disk_create() are supposed to pass in
DISK_VERSION, not an explicit disk API version
number. Update the blkfront driver to do that.
disk.9: Update the disk(9) man page to include information
on the new d_gone() callback, as well as the
previously added d_getattr() callback, d_descr
field, and HBA PCI ID fields.
MFC after: 5 days
2012-06-24 04:29:03 +00:00
|
|
|
/*
|
|
|
|
* Tell GEOM that we've gone away, we'll get a callback when it is
|
|
|
|
* done cleaning up its resources.
|
|
|
|
*/
|
Fix a bug that caused some /dev entries to continue to exist after
the underlying drive had been hot-unplugged from the system. Here
is a specific example. Filesystem code had opened /dev/da1s1e.
Subsequently, the drive was hot-unplugged. This (correctly) caused
all of the associated /dev/da1* entries to be deleted. When the
filesystem later realized that the drive was gone it closed the
device, reducing the write-access counts to 0 on the geom providers
for da1s1e, da1s1, and da1. This caused geom to re-taste the
providers, resulting in the devices being created again. When the
drive was hot-plugged back in, it resulted in duplicate /dev entries
for da1s1e, da1s1, and da1.
This fix adds a new disk_gone() function which is called by CAM when a
drive goes away. It orphans all of the providers associated with the
drive, setting an error condition of ENXIO in each one. In addition,
we prevent a re-taste on last close for writing if an error condition
has been set in the provider.
Sponsored by: Isilon Systems
Reviewed by: phk
MFC after: 1 week
2005-11-18 02:43:49 +00:00
|
|
|
disk_gone(softc->disk);
|
Fix a problem with the way we handled device invalidation when attaching
to a device failed.
In theory, the same steps that happen when we get an AC_LOST_DEVICE async
notification should have been taken when a driver fails to attach. In
practice, that wasn't the case.
This only affected the da, cd and ch drivers, but the fix affects all
peripheral drivers.
There were several possible problems:
- In the da driver, we didn't remove the peripheral's softc from the da
driver's linked list of softcs. Once the peripheral and softc got
removed, we'd get a kernel panic the next time the timeout routine
called dasendorderedtag().
- In the da, cd and possibly ch drivers, we didn't remove the
peripheral's devstat structure from the devstat queue. Once the
peripheral and softc were removed, this could cause a panic if anyone
tried to access device statistics. (one component of the linked list
wouldn't exist anymore)
- In the cd driver, we didn't take the peripheral off the changer run
queue if it was scheduled to run. In practice, it's highly unlikely,
and maybe impossible that the peripheral would have been on the
changer run queue at that stage of the probe process.
The fix is:
- Add a new peripheral callback function (the "oninvalidate" function)
that is called the first time cam_periph_invalidate() is called for a
peripheral.
- Create new foooninvalidate() routines for each peripheral driver. This
routine is always called at splsoftcam(), and contains all the stuff
that used to be in the AC_LOST_DEVICE case of the async callback
handler.
- Move the devstat cleanup call to the destructor/cleanup routines, since
some of the drivers do I/O in their close routines.
- Make sure that when we're flushing the buffer queue, we traverse it at
splbio().
- Add a check for the invalid flag in the pt driver's open routine.
Reviewed by: gibbs
1998-10-22 22:16:56 +00:00
|
|
|
}
|
|
|
|
|
1998-09-15 06:36:34 +00:00
|
|
|
static void
|
|
|
|
dacleanup(struct cam_periph *periph)
|
|
|
|
{
|
Fix a problem with the way we handled device invalidation when attaching
to a device failed.
In theory, the same steps that happen when we get an AC_LOST_DEVICE async
notification should have been taken when a driver fails to attach. In
practice, that wasn't the case.
This only affected the da, cd and ch drivers, but the fix affects all
peripheral drivers.
There were several possible problems:
- In the da driver, we didn't remove the peripheral's softc from the da
driver's linked list of softcs. Once the peripheral and softc got
removed, we'd get a kernel panic the next time the timeout routine
called dasendorderedtag().
- In the da, cd and possibly ch drivers, we didn't remove the
peripheral's devstat structure from the devstat queue. Once the
peripheral and softc were removed, this could cause a panic if anyone
tried to access device statistics. (one component of the linked list
wouldn't exist anymore)
- In the cd driver, we didn't take the peripheral off the changer run
queue if it was scheduled to run. In practice, it's highly unlikely,
and maybe impossible that the peripheral would have been on the
changer run queue at that stage of the probe process.
The fix is:
- Add a new peripheral callback function (the "oninvalidate" function)
that is called the first time cam_periph_invalidate() is called for a
peripheral.
- Create new foooninvalidate() routines for each peripheral driver. This
routine is always called at splsoftcam(), and contains all the stuff
that used to be in the AC_LOST_DEVICE case of the async callback
handler.
- Move the devstat cleanup call to the destructor/cleanup routines, since
some of the drivers do I/O in their close routines.
- Make sure that when we're flushing the buffer queue, we traverse it at
splbio().
- Add a check for the invalid flag in the pt driver's open routine.
Reviewed by: gibbs
1998-10-22 22:16:56 +00:00
|
|
|
struct da_softc *softc;
|
|
|
|
|
|
|
|
softc = (struct da_softc *)periph->softc;
|
|
|
|
|
2009-02-11 22:29:09 +00:00
|
|
|
cam_periph_unlock(periph);
|
|
|
|
|
2003-03-26 04:38:39 +00:00
|
|
|
/*
|
|
|
|
* If we can't free the sysctl tree, oh well...
|
|
|
|
*/
|
2003-10-08 07:12:30 +00:00
|
|
|
if ((softc->flags & DA_FLAG_SCTX_INIT) != 0
|
|
|
|
&& sysctl_ctx_free(&softc->sysctl_ctx) != 0) {
|
2006-12-05 07:45:28 +00:00
|
|
|
xpt_print(periph->path, "can't remove sysctl context\n");
|
2003-03-26 04:38:39 +00:00
|
|
|
}
|
2007-04-15 08:49:19 +00:00
|
|
|
|
2012-07-29 11:51:48 +00:00
|
|
|
callout_drain(&softc->mediapoll_c);
|
2007-04-16 19:41:14 +00:00
|
|
|
disk_destroy(softc->disk);
|
2007-04-15 08:49:19 +00:00
|
|
|
callout_drain(&softc->sendordered_c);
|
Fix a problem with the way we handled device invalidation when attaching
to a device failed.
In theory, the same steps that happen when we get an AC_LOST_DEVICE async
notification should have been taken when a driver fails to attach. In
practice, that wasn't the case.
This only affected the da, cd and ch drivers, but the fix affects all
peripheral drivers.
There were several possible problems:
- In the da driver, we didn't remove the peripheral's softc from the da
driver's linked list of softcs. Once the peripheral and softc got
removed, we'd get a kernel panic the next time the timeout routine
called dasendorderedtag().
- In the da, cd and possibly ch drivers, we didn't remove the
peripheral's devstat structure from the devstat queue. Once the
peripheral and softc were removed, this could cause a panic if anyone
tried to access device statistics. (one component of the linked list
wouldn't exist anymore)
- In the cd driver, we didn't take the peripheral off the changer run
queue if it was scheduled to run. In practice, it's highly unlikely,
and maybe impossible that the peripheral would have been on the
changer run queue at that stage of the probe process.
The fix is:
- Add a new peripheral callback function (the "oninvalidate" function)
that is called the first time cam_periph_invalidate() is called for a
peripheral.
- Create new foooninvalidate() routines for each peripheral driver. This
routine is always called at splsoftcam(), and contains all the stuff
that used to be in the AC_LOST_DEVICE case of the async callback
handler.
- Move the devstat cleanup call to the destructor/cleanup routines, since
some of the drivers do I/O in their close routines.
- Make sure that when we're flushing the buffer queue, we traverse it at
splbio().
- Add a check for the invalid flag in the pt driver's open routine.
Reviewed by: gibbs
1998-10-22 22:16:56 +00:00
|
|
|
free(softc, M_DEVBUF);
|
2009-02-11 22:29:09 +00:00
|
|
|
cam_periph_lock(periph);
|
1998-09-15 06:36:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
daasync(void *callback_arg, u_int32_t code,
|
|
|
|
struct cam_path *path, void *arg)
|
|
|
|
{
|
|
|
|
struct cam_periph *periph;
|
2012-07-29 11:51:48 +00:00
|
|
|
struct da_softc *softc;
|
1998-09-15 06:36:34 +00:00
|
|
|
|
|
|
|
periph = (struct cam_periph *)callback_arg;
|
|
|
|
switch (code) {
|
|
|
|
case AC_FOUND_DEVICE:
|
|
|
|
{
|
|
|
|
struct ccb_getdev *cgd;
|
|
|
|
cam_status status;
|
|
|
|
|
|
|
|
cgd = (struct ccb_getdev *)arg;
|
2001-07-04 05:22:42 +00:00
|
|
|
if (cgd == NULL)
|
|
|
|
break;
|
1998-09-15 06:36:34 +00:00
|
|
|
|
Separate the parallel scsi knowledge out of the core of the XPT, and
modularize it so that new transports can be created.
Add a transport for SATA
Add a periph+protocol layer for ATA
Add a driver for AHCI-compliant hardware.
Add a maxio field to CAM so that drivers can advertise their max
I/O capability. Modify various drivers so that they are insulated
from the value of MAXPHYS.
The new ATA/SATA code supports AHCI-compliant hardware, and will override
the classic ATA driver if it is loaded as a module at boot time or compiled
into the kernel. The stack now support NCQ (tagged queueing) for increased
performance on modern SATA drives. It also supports port multipliers.
ATA drives are accessed via 'ada' device nodes. ATAPI drives are
accessed via 'cd' device nodes. They can all be enumerated and manipulated
via camcontrol, just like SCSI drives. SCSI commands are not translated to
their ATA equivalents; ATA native commands are used throughout the entire
stack, including camcontrol. See the camcontrol manpage for further
details. Testing this code may require that you update your fstab, and
possibly modify your BIOS to enable AHCI functionality, if available.
This code is very experimental at the moment. The userland ABI/API has
changed, so applications will need to be recompiled. It may change
further in the near future. The 'ada' device name may also change as
more infrastructure is completed in this project. The goal is to
eventually put all CAM busses and devices until newbus, allowing for
interesting topology and management options.
Few functional changes will be seen with existing SCSI/SAS/FC drivers,
though the userland ABI has still changed. In the future, transports
specific modules for SAS and FC may appear in order to better support
the topologies and capabilities of these technologies.
The modularization of CAM and the addition of the ATA/SATA modules is
meant to break CAM out of the mold of being specific to SCSI, letting it
grow to be a framework for arbitrary transports and protocols. It also
allows drivers to be written to support discrete hardware without
jeopardizing the stability of non-related hardware. While only an AHCI
driver is provided now, a Silicon Image driver is also in the works.
Drivers for ICH1-4, ICH5-6, PIIX, classic IDE, and any other hardware
is possible and encouraged. Help with new transports is also encouraged.
Submitted by: scottl, mav
Approved by: re
2009-07-10 08:18:08 +00:00
|
|
|
if (cgd->protocol != PROTO_SCSI)
|
|
|
|
break;
|
2015-08-29 11:21:20 +00:00
|
|
|
if (SID_QUAL(&cgd->inq_data) != SID_QUAL_LU_CONNECTED)
|
|
|
|
break;
|
2000-01-17 06:27:37 +00:00
|
|
|
if (SID_TYPE(&cgd->inq_data) != T_DIRECT
|
2002-02-21 11:58:47 +00:00
|
|
|
&& SID_TYPE(&cgd->inq_data) != T_RBC
|
2000-01-17 06:27:37 +00:00
|
|
|
&& SID_TYPE(&cgd->inq_data) != T_OPTICAL)
|
1998-09-15 06:36:34 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Allocate a peripheral instance for
|
|
|
|
* this device and start the probe
|
|
|
|
* process.
|
|
|
|
*/
|
Fix a problem with the way we handled device invalidation when attaching
to a device failed.
In theory, the same steps that happen when we get an AC_LOST_DEVICE async
notification should have been taken when a driver fails to attach. In
practice, that wasn't the case.
This only affected the da, cd and ch drivers, but the fix affects all
peripheral drivers.
There were several possible problems:
- In the da driver, we didn't remove the peripheral's softc from the da
driver's linked list of softcs. Once the peripheral and softc got
removed, we'd get a kernel panic the next time the timeout routine
called dasendorderedtag().
- In the da, cd and possibly ch drivers, we didn't remove the
peripheral's devstat structure from the devstat queue. Once the
peripheral and softc were removed, this could cause a panic if anyone
tried to access device statistics. (one component of the linked list
wouldn't exist anymore)
- In the cd driver, we didn't take the peripheral off the changer run
queue if it was scheduled to run. In practice, it's highly unlikely,
and maybe impossible that the peripheral would have been on the
changer run queue at that stage of the probe process.
The fix is:
- Add a new peripheral callback function (the "oninvalidate" function)
that is called the first time cam_periph_invalidate() is called for a
peripheral.
- Create new foooninvalidate() routines for each peripheral driver. This
routine is always called at splsoftcam(), and contains all the stuff
that used to be in the AC_LOST_DEVICE case of the async callback
handler.
- Move the devstat cleanup call to the destructor/cleanup routines, since
some of the drivers do I/O in their close routines.
- Make sure that when we're flushing the buffer queue, we traverse it at
splbio().
- Add a check for the invalid flag in the pt driver's open routine.
Reviewed by: gibbs
1998-10-22 22:16:56 +00:00
|
|
|
status = cam_periph_alloc(daregister, daoninvalidate,
|
|
|
|
dacleanup, dastart,
|
|
|
|
"da", CAM_PERIPH_BIO,
|
Merge CAM locking changes from the projects/camlock branch to radically
reduce lock congestion and improve SMP scalability of the SCSI/ATA stack,
preparing the ground for the coming next GEOM direct dispatch support.
Replace big per-SIM locks with bunch of smaller ones:
- per-LUN locks to protect device and peripheral drivers state;
- per-target locks to protect list of LUNs on target;
- per-bus locks to protect reference counting;
- per-send queue locks to protect queue of CCBs to be sent;
- per-done queue locks to protect queue of completed CCBs;
- remaining per-SIM locks now protect only HBA driver internals.
While holding LUN lock it is allowed (while not recommended for performance
reasons) to take SIM lock. The opposite acquisition order is forbidden.
All the other locks are leaf locks, that can be taken anywhere, but should
not be cascaded. Many functions, such as: xpt_action(), xpt_done(),
xpt_async(), xpt_create_path(), etc. are no longer require (but allow) SIM
lock to be held.
To keep compatibility and solve cases where SIM lock can't be dropped, all
xpt_async() calls in addition to xpt_done() calls are queued to completion
threads for async processing in clean environment without SIM lock held.
Instead of single CAM SWI thread, used for commands completion processing
before, use multiple (depending on number of CPUs) threads. Load balanced
between them using "hash" of the device B:T:L address.
HBA drivers that can drop SIM lock during completion processing and have
sufficient number of completion threads to efficiently scale to multiple
CPUs can use new function xpt_done_direct() to avoid extra context switch.
Make ahci(4) driver to use this mechanism depending on hardware setup.
Sponsored by: iXsystems, Inc.
MFC after: 2 months
2013-10-21 12:00:26 +00:00
|
|
|
path, daasync,
|
Fix a problem with the way we handled device invalidation when attaching
to a device failed.
In theory, the same steps that happen when we get an AC_LOST_DEVICE async
notification should have been taken when a driver fails to attach. In
practice, that wasn't the case.
This only affected the da, cd and ch drivers, but the fix affects all
peripheral drivers.
There were several possible problems:
- In the da driver, we didn't remove the peripheral's softc from the da
driver's linked list of softcs. Once the peripheral and softc got
removed, we'd get a kernel panic the next time the timeout routine
called dasendorderedtag().
- In the da, cd and possibly ch drivers, we didn't remove the
peripheral's devstat structure from the devstat queue. Once the
peripheral and softc were removed, this could cause a panic if anyone
tried to access device statistics. (one component of the linked list
wouldn't exist anymore)
- In the cd driver, we didn't take the peripheral off the changer run
queue if it was scheduled to run. In practice, it's highly unlikely,
and maybe impossible that the peripheral would have been on the
changer run queue at that stage of the probe process.
The fix is:
- Add a new peripheral callback function (the "oninvalidate" function)
that is called the first time cam_periph_invalidate() is called for a
peripheral.
- Create new foooninvalidate() routines for each peripheral driver. This
routine is always called at splsoftcam(), and contains all the stuff
that used to be in the AC_LOST_DEVICE case of the async callback
handler.
- Move the devstat cleanup call to the destructor/cleanup routines, since
some of the drivers do I/O in their close routines.
- Make sure that when we're flushing the buffer queue, we traverse it at
splbio().
- Add a check for the invalid flag in the pt driver's open routine.
Reviewed by: gibbs
1998-10-22 22:16:56 +00:00
|
|
|
AC_FOUND_DEVICE, cgd);
|
1998-09-15 06:36:34 +00:00
|
|
|
|
|
|
|
if (status != CAM_REQ_CMP
|
|
|
|
&& status != CAM_REQ_INPROG)
|
|
|
|
printf("daasync: Unable to attach to new device "
|
|
|
|
"due to status 0x%x\n", status);
|
Plumb device physical path reporting from CAM devices, through GEOM and
DEVFS, and make it accessible via the diskinfo utility.
Extend GEOM's generic attribute query mechanism into generic disk consumers.
sys/geom/geom_disk.c:
sys/geom/geom_disk.h:
sys/cam/scsi/scsi_da.c:
sys/cam/ata/ata_da.c:
- Allow disk providers to implement a new method which can override
the default BIO_GETATTR response, d_getattr(struct bio *). This
function returns -1 if not handled, otherwise it returns 0 or an
errno to be passed to g_io_deliver().
sys/cam/scsi/scsi_da.c:
sys/cam/ata/ata_da.c:
- Don't copy the serial number to dp->d_ident anymore, as the CAM XPT
is now responsible for returning this information via
d_getattr()->(a)dagetattr()->xpt_getatr().
sys/geom/geom_dev.c:
- Implement a new ioctl, DIOCGPHYSPATH, which returns the GEOM
attribute "GEOM::physpath", if possible. If the attribute request
returns a zero-length string, ENOENT is returned.
usr.sbin/diskinfo/diskinfo.c:
- If the DIOCGPHYSPATH ioctl is successful, report physical path
data when diskinfo is executed with the '-v' option.
Submitted by: will
Reviewed by: gibbs
Sponsored by: Spectra Logic Corporation
Add generic attribute change notification support to GEOM.
sys/sys/geom/geom.h:
Add a new attrchanged method field to both g_class
and g_geom.
sys/sys/geom/geom.h:
sys/geom/geom_event.c:
- Provide the g_attr_changed() function that providers
can use to advertise attribute changes.
- Perform delivery of attribute change notifications
from a thread context via the standard GEOM event
mechanism.
sys/geom/geom_subr.c:
Inherit the attrchanged method from class to geom (class instance).
sys/geom/geom_disk.c:
Provide disk_attr_changed() to provide g_attr_changed() access
to consumers of the disk API.
sys/cam/scsi/scsi_pass.c:
sys/cam/scsi/scsi_da.c:
sys/geom/geom_dev.c:
sys/geom/geom_disk.c:
Use attribute changed events to track updates to physical path
information.
sys/cam/scsi/scsi_da.c:
Add AC_ADVINFO_CHANGED to the registered asynchronous CAM
events for this driver. When this event occurs, and
the updated buffer type references our physical path
attribute, emit a GEOM attribute changed event via the
disk_attr_changed() API.
sys/cam/scsi/scsi_pass.c:
Add AC_ADVINFO_CHANGED to the registered asynchronous CAM
events for this driver. When this event occurs, update
the physical patch devfs alias for this pass instance.
Submitted by: gibbs
Sponsored by: Spectra Logic Corporation
2011-06-14 17:10:32 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
case AC_ADVINFO_CHANGED:
|
|
|
|
{
|
|
|
|
uintptr_t buftype;
|
|
|
|
|
|
|
|
buftype = (uintptr_t)arg;
|
|
|
|
if (buftype == CDAI_TYPE_PHYS_PATH) {
|
|
|
|
struct da_softc *softc;
|
|
|
|
|
|
|
|
softc = periph->softc;
|
|
|
|
disk_attr_changed(softc->disk, "GEOM::physpath",
|
|
|
|
M_NOWAIT);
|
|
|
|
}
|
1998-09-15 06:36:34 +00:00
|
|
|
break;
|
|
|
|
}
|
2012-07-29 11:51:48 +00:00
|
|
|
case AC_UNIT_ATTENTION:
|
|
|
|
{
|
|
|
|
union ccb *ccb;
|
|
|
|
int error_code, sense_key, asc, ascq;
|
|
|
|
|
|
|
|
softc = (struct da_softc *)periph->softc;
|
|
|
|
ccb = (union ccb *)arg;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Handle all UNIT ATTENTIONs except our own,
|
|
|
|
* as they will be handled by daerror().
|
|
|
|
*/
|
|
|
|
if (xpt_path_periph(ccb->ccb_h.path) != periph &&
|
|
|
|
scsi_extract_sense_ccb(ccb,
|
|
|
|
&error_code, &sense_key, &asc, &ascq)) {
|
|
|
|
if (asc == 0x2A && ascq == 0x09) {
|
|
|
|
xpt_print(ccb->ccb_h.path,
|
2014-04-30 17:38:26 +00:00
|
|
|
"Capacity data has changed\n");
|
|
|
|
softc->flags &= ~DA_FLAG_PROBED;
|
2012-07-29 11:51:48 +00:00
|
|
|
dareprobe(periph);
|
2014-04-30 17:38:26 +00:00
|
|
|
} else if (asc == 0x28 && ascq == 0x00) {
|
|
|
|
softc->flags &= ~DA_FLAG_PROBED;
|
2012-07-29 11:51:48 +00:00
|
|
|
disk_media_changed(softc->disk, M_NOWAIT);
|
2014-04-30 17:38:26 +00:00
|
|
|
} else if (asc == 0x3F && ascq == 0x03) {
|
|
|
|
xpt_print(ccb->ccb_h.path,
|
|
|
|
"INQUIRY data has changed\n");
|
|
|
|
softc->flags &= ~DA_FLAG_PROBED;
|
|
|
|
dareprobe(periph);
|
|
|
|
}
|
2012-07-29 11:51:48 +00:00
|
|
|
}
|
|
|
|
cam_periph_async(periph, code, path, arg);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case AC_SCSI_AEN:
|
|
|
|
softc = (struct da_softc *)periph->softc;
|
2013-01-11 16:10:11 +00:00
|
|
|
if (!softc->tur) {
|
2012-07-29 11:51:48 +00:00
|
|
|
if (cam_periph_acquire(periph) == CAM_REQ_CMP) {
|
|
|
|
softc->tur = 1;
|
2013-01-11 16:10:11 +00:00
|
|
|
daschedule(periph);
|
2012-07-29 11:51:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/* FALLTHROUGH */
|
1998-09-15 06:36:34 +00:00
|
|
|
case AC_SENT_BDR:
|
|
|
|
case AC_BUS_RESET:
|
|
|
|
{
|
|
|
|
struct ccb_hdr *ccbh;
|
|
|
|
|
|
|
|
softc = (struct da_softc *)periph->softc;
|
|
|
|
/*
|
|
|
|
* Don't fail on the expected unit attention
|
|
|
|
* that will occur.
|
|
|
|
*/
|
|
|
|
softc->flags |= DA_FLAG_RETRY_UA;
|
2001-02-04 13:13:25 +00:00
|
|
|
LIST_FOREACH(ccbh, &softc->pending_ccbs, periph_links.le)
|
1998-09-15 06:36:34 +00:00
|
|
|
ccbh->ccb_state |= DA_CCB_RETRY_UA;
|
2011-06-14 16:05:00 +00:00
|
|
|
break;
|
1998-09-15 06:36:34 +00:00
|
|
|
}
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2011-06-14 16:05:00 +00:00
|
|
|
cam_periph_async(periph, code, path, arg);
|
1998-09-15 06:36:34 +00:00
|
|
|
}
|
|
|
|
|
Move dynamic sysctl(8) variable creation for the cd(4) and da(4) drivers
out of cdregister() and daregister(), which are run from interrupt context.
The sysctl code does blocking mallocs (M_WAITOK), which causes problems
if malloc(9) actually needs to sleep.
The eventual fix for this issue will involve moving the CAM probe process
inside a kernel thread. For now, though, I have fixed the issue by moving
dynamic sysctl variable creation for these two drivers to a task queue
running in a kernel thread.
The existing task queues (taskqueue_swi and taskqueue_swi_giant) run in
software interrupt handlers, which wouldn't fix the problem at hand. So I
have created a new task queue, taskqueue_thread, that runs inside a kernel
thread. (It also runs outside of Giant -- clients must explicitly acquire
and release Giant in their taskqueue functions.)
scsi_cd.c: Remove sysctl variable creation code from cdregister(), and
move it to a new function, cdsysctlinit(). Queue
cdsysctlinit() to the taskqueue_thread taskqueue once we
have fully registered the cd(4) driver instance.
scsi_da.c: Remove sysctl variable creation code from daregister(), and
move it to move it to a new function, dasysctlinit().
Queue dasysctlinit() to the taskqueue_thread taskqueue once
we have fully registered the da(4) instance.
taskqueue.h: Declare the new taskqueue_thread taskqueue, update some
comments.
subr_taskqueue.c:
Create the new kernel thread taskqueue. This taskqueue
runs outside of Giant, so any functions queued to it would
need to explicitly acquire/release Giant if they need it.
cd.4: Update the cd(4) man page to talk about the minimum command
size sysctl/loader tunable. Also note that the changer
variables are available as loader tunables as well.
da.4: Update the da(4) man page to cover the retry_count,
default_timeout and minimum_cmd_size sysctl variables/loader
tunables. Remove references to /dev/r???, they aren't used
any longer.
cd.9: Update the cd(9) man page to describe the CD_Q_10_BYTE_ONLY
quirk.
taskqueue.9: Update the taskqueue(9) man page to describe the new thread
task queue, and the taskqueue_swi_giant queue.
MFC after: 3 days
2003-09-03 04:46:28 +00:00
|
|
|
static void
|
|
|
|
dasysctlinit(void *context, int pending)
|
|
|
|
{
|
|
|
|
struct cam_periph *periph;
|
|
|
|
struct da_softc *softc;
|
|
|
|
char tmpstr[80], tmpstr2[80];
|
2010-06-07 22:43:37 +00:00
|
|
|
struct ccb_trans_settings cts;
|
Move dynamic sysctl(8) variable creation for the cd(4) and da(4) drivers
out of cdregister() and daregister(), which are run from interrupt context.
The sysctl code does blocking mallocs (M_WAITOK), which causes problems
if malloc(9) actually needs to sleep.
The eventual fix for this issue will involve moving the CAM probe process
inside a kernel thread. For now, though, I have fixed the issue by moving
dynamic sysctl variable creation for these two drivers to a task queue
running in a kernel thread.
The existing task queues (taskqueue_swi and taskqueue_swi_giant) run in
software interrupt handlers, which wouldn't fix the problem at hand. So I
have created a new task queue, taskqueue_thread, that runs inside a kernel
thread. (It also runs outside of Giant -- clients must explicitly acquire
and release Giant in their taskqueue functions.)
scsi_cd.c: Remove sysctl variable creation code from cdregister(), and
move it to a new function, cdsysctlinit(). Queue
cdsysctlinit() to the taskqueue_thread taskqueue once we
have fully registered the cd(4) driver instance.
scsi_da.c: Remove sysctl variable creation code from daregister(), and
move it to move it to a new function, dasysctlinit().
Queue dasysctlinit() to the taskqueue_thread taskqueue once
we have fully registered the da(4) instance.
taskqueue.h: Declare the new taskqueue_thread taskqueue, update some
comments.
subr_taskqueue.c:
Create the new kernel thread taskqueue. This taskqueue
runs outside of Giant, so any functions queued to it would
need to explicitly acquire/release Giant if they need it.
cd.4: Update the cd(4) man page to talk about the minimum command
size sysctl/loader tunable. Also note that the changer
variables are available as loader tunables as well.
da.4: Update the da(4) man page to cover the retry_count,
default_timeout and minimum_cmd_size sysctl variables/loader
tunables. Remove references to /dev/r???, they aren't used
any longer.
cd.9: Update the cd(9) man page to describe the CD_Q_10_BYTE_ONLY
quirk.
taskqueue.9: Update the taskqueue(9) man page to describe the new thread
task queue, and the taskqueue_swi_giant queue.
MFC after: 3 days
2003-09-03 04:46:28 +00:00
|
|
|
|
|
|
|
periph = (struct cam_periph *)context;
|
2010-06-08 22:46:44 +00:00
|
|
|
/*
|
|
|
|
* periph was held for us when this task was enqueued
|
|
|
|
*/
|
|
|
|
if (periph->flags & CAM_PERIPH_INVALID) {
|
|
|
|
cam_periph_release(periph);
|
2007-04-15 08:49:19 +00:00
|
|
|
return;
|
2010-06-08 22:46:44 +00:00
|
|
|
}
|
Move dynamic sysctl(8) variable creation for the cd(4) and da(4) drivers
out of cdregister() and daregister(), which are run from interrupt context.
The sysctl code does blocking mallocs (M_WAITOK), which causes problems
if malloc(9) actually needs to sleep.
The eventual fix for this issue will involve moving the CAM probe process
inside a kernel thread. For now, though, I have fixed the issue by moving
dynamic sysctl variable creation for these two drivers to a task queue
running in a kernel thread.
The existing task queues (taskqueue_swi and taskqueue_swi_giant) run in
software interrupt handlers, which wouldn't fix the problem at hand. So I
have created a new task queue, taskqueue_thread, that runs inside a kernel
thread. (It also runs outside of Giant -- clients must explicitly acquire
and release Giant in their taskqueue functions.)
scsi_cd.c: Remove sysctl variable creation code from cdregister(), and
move it to a new function, cdsysctlinit(). Queue
cdsysctlinit() to the taskqueue_thread taskqueue once we
have fully registered the cd(4) driver instance.
scsi_da.c: Remove sysctl variable creation code from daregister(), and
move it to move it to a new function, dasysctlinit().
Queue dasysctlinit() to the taskqueue_thread taskqueue once
we have fully registered the da(4) instance.
taskqueue.h: Declare the new taskqueue_thread taskqueue, update some
comments.
subr_taskqueue.c:
Create the new kernel thread taskqueue. This taskqueue
runs outside of Giant, so any functions queued to it would
need to explicitly acquire/release Giant if they need it.
cd.4: Update the cd(4) man page to talk about the minimum command
size sysctl/loader tunable. Also note that the changer
variables are available as loader tunables as well.
da.4: Update the da(4) man page to cover the retry_count,
default_timeout and minimum_cmd_size sysctl variables/loader
tunables. Remove references to /dev/r???, they aren't used
any longer.
cd.9: Update the cd(9) man page to describe the CD_Q_10_BYTE_ONLY
quirk.
taskqueue.9: Update the taskqueue(9) man page to describe the new thread
task queue, and the taskqueue_swi_giant queue.
MFC after: 3 days
2003-09-03 04:46:28 +00:00
|
|
|
|
2007-04-15 08:49:19 +00:00
|
|
|
softc = (struct da_softc *)periph->softc;
|
Move dynamic sysctl(8) variable creation for the cd(4) and da(4) drivers
out of cdregister() and daregister(), which are run from interrupt context.
The sysctl code does blocking mallocs (M_WAITOK), which causes problems
if malloc(9) actually needs to sleep.
The eventual fix for this issue will involve moving the CAM probe process
inside a kernel thread. For now, though, I have fixed the issue by moving
dynamic sysctl variable creation for these two drivers to a task queue
running in a kernel thread.
The existing task queues (taskqueue_swi and taskqueue_swi_giant) run in
software interrupt handlers, which wouldn't fix the problem at hand. So I
have created a new task queue, taskqueue_thread, that runs inside a kernel
thread. (It also runs outside of Giant -- clients must explicitly acquire
and release Giant in their taskqueue functions.)
scsi_cd.c: Remove sysctl variable creation code from cdregister(), and
move it to a new function, cdsysctlinit(). Queue
cdsysctlinit() to the taskqueue_thread taskqueue once we
have fully registered the cd(4) driver instance.
scsi_da.c: Remove sysctl variable creation code from daregister(), and
move it to move it to a new function, dasysctlinit().
Queue dasysctlinit() to the taskqueue_thread taskqueue once
we have fully registered the da(4) instance.
taskqueue.h: Declare the new taskqueue_thread taskqueue, update some
comments.
subr_taskqueue.c:
Create the new kernel thread taskqueue. This taskqueue
runs outside of Giant, so any functions queued to it would
need to explicitly acquire/release Giant if they need it.
cd.4: Update the cd(4) man page to talk about the minimum command
size sysctl/loader tunable. Also note that the changer
variables are available as loader tunables as well.
da.4: Update the da(4) man page to cover the retry_count,
default_timeout and minimum_cmd_size sysctl variables/loader
tunables. Remove references to /dev/r???, they aren't used
any longer.
cd.9: Update the cd(9) man page to describe the CD_Q_10_BYTE_ONLY
quirk.
taskqueue.9: Update the taskqueue(9) man page to describe the new thread
task queue, and the taskqueue_swi_giant queue.
MFC after: 3 days
2003-09-03 04:46:28 +00:00
|
|
|
snprintf(tmpstr, sizeof(tmpstr), "CAM DA unit %d", periph->unit_number);
|
|
|
|
snprintf(tmpstr2, sizeof(tmpstr2), "%d", periph->unit_number);
|
|
|
|
|
|
|
|
sysctl_ctx_init(&softc->sysctl_ctx);
|
2003-10-08 07:12:30 +00:00
|
|
|
softc->flags |= DA_FLAG_SCTX_INIT;
|
Move dynamic sysctl(8) variable creation for the cd(4) and da(4) drivers
out of cdregister() and daregister(), which are run from interrupt context.
The sysctl code does blocking mallocs (M_WAITOK), which causes problems
if malloc(9) actually needs to sleep.
The eventual fix for this issue will involve moving the CAM probe process
inside a kernel thread. For now, though, I have fixed the issue by moving
dynamic sysctl variable creation for these two drivers to a task queue
running in a kernel thread.
The existing task queues (taskqueue_swi and taskqueue_swi_giant) run in
software interrupt handlers, which wouldn't fix the problem at hand. So I
have created a new task queue, taskqueue_thread, that runs inside a kernel
thread. (It also runs outside of Giant -- clients must explicitly acquire
and release Giant in their taskqueue functions.)
scsi_cd.c: Remove sysctl variable creation code from cdregister(), and
move it to a new function, cdsysctlinit(). Queue
cdsysctlinit() to the taskqueue_thread taskqueue once we
have fully registered the cd(4) driver instance.
scsi_da.c: Remove sysctl variable creation code from daregister(), and
move it to move it to a new function, dasysctlinit().
Queue dasysctlinit() to the taskqueue_thread taskqueue once
we have fully registered the da(4) instance.
taskqueue.h: Declare the new taskqueue_thread taskqueue, update some
comments.
subr_taskqueue.c:
Create the new kernel thread taskqueue. This taskqueue
runs outside of Giant, so any functions queued to it would
need to explicitly acquire/release Giant if they need it.
cd.4: Update the cd(4) man page to talk about the minimum command
size sysctl/loader tunable. Also note that the changer
variables are available as loader tunables as well.
da.4: Update the da(4) man page to cover the retry_count,
default_timeout and minimum_cmd_size sysctl variables/loader
tunables. Remove references to /dev/r???, they aren't used
any longer.
cd.9: Update the cd(9) man page to describe the CD_Q_10_BYTE_ONLY
quirk.
taskqueue.9: Update the taskqueue(9) man page to describe the new thread
task queue, and the taskqueue_swi_giant queue.
MFC after: 3 days
2003-09-03 04:46:28 +00:00
|
|
|
softc->sysctl_tree = SYSCTL_ADD_NODE(&softc->sysctl_ctx,
|
|
|
|
SYSCTL_STATIC_CHILDREN(_kern_cam_da), OID_AUTO, tmpstr2,
|
|
|
|
CTLFLAG_RD, 0, tmpstr);
|
|
|
|
if (softc->sysctl_tree == NULL) {
|
|
|
|
printf("dasysctlinit: unable to allocate sysctl tree\n");
|
2007-04-15 08:49:19 +00:00
|
|
|
cam_periph_release(periph);
|
Move dynamic sysctl(8) variable creation for the cd(4) and da(4) drivers
out of cdregister() and daregister(), which are run from interrupt context.
The sysctl code does blocking mallocs (M_WAITOK), which causes problems
if malloc(9) actually needs to sleep.
The eventual fix for this issue will involve moving the CAM probe process
inside a kernel thread. For now, though, I have fixed the issue by moving
dynamic sysctl variable creation for these two drivers to a task queue
running in a kernel thread.
The existing task queues (taskqueue_swi and taskqueue_swi_giant) run in
software interrupt handlers, which wouldn't fix the problem at hand. So I
have created a new task queue, taskqueue_thread, that runs inside a kernel
thread. (It also runs outside of Giant -- clients must explicitly acquire
and release Giant in their taskqueue functions.)
scsi_cd.c: Remove sysctl variable creation code from cdregister(), and
move it to a new function, cdsysctlinit(). Queue
cdsysctlinit() to the taskqueue_thread taskqueue once we
have fully registered the cd(4) driver instance.
scsi_da.c: Remove sysctl variable creation code from daregister(), and
move it to move it to a new function, dasysctlinit().
Queue dasysctlinit() to the taskqueue_thread taskqueue once
we have fully registered the da(4) instance.
taskqueue.h: Declare the new taskqueue_thread taskqueue, update some
comments.
subr_taskqueue.c:
Create the new kernel thread taskqueue. This taskqueue
runs outside of Giant, so any functions queued to it would
need to explicitly acquire/release Giant if they need it.
cd.4: Update the cd(4) man page to talk about the minimum command
size sysctl/loader tunable. Also note that the changer
variables are available as loader tunables as well.
da.4: Update the da(4) man page to cover the retry_count,
default_timeout and minimum_cmd_size sysctl variables/loader
tunables. Remove references to /dev/r???, they aren't used
any longer.
cd.9: Update the cd(9) man page to describe the CD_Q_10_BYTE_ONLY
quirk.
taskqueue.9: Update the taskqueue(9) man page to describe the new thread
task queue, and the taskqueue_swi_giant queue.
MFC after: 3 days
2003-09-03 04:46:28 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2010-06-07 17:41:34 +00:00
|
|
|
* Now register the sysctl handler, so the user can change the value on
|
Move dynamic sysctl(8) variable creation for the cd(4) and da(4) drivers
out of cdregister() and daregister(), which are run from interrupt context.
The sysctl code does blocking mallocs (M_WAITOK), which causes problems
if malloc(9) actually needs to sleep.
The eventual fix for this issue will involve moving the CAM probe process
inside a kernel thread. For now, though, I have fixed the issue by moving
dynamic sysctl variable creation for these two drivers to a task queue
running in a kernel thread.
The existing task queues (taskqueue_swi and taskqueue_swi_giant) run in
software interrupt handlers, which wouldn't fix the problem at hand. So I
have created a new task queue, taskqueue_thread, that runs inside a kernel
thread. (It also runs outside of Giant -- clients must explicitly acquire
and release Giant in their taskqueue functions.)
scsi_cd.c: Remove sysctl variable creation code from cdregister(), and
move it to a new function, cdsysctlinit(). Queue
cdsysctlinit() to the taskqueue_thread taskqueue once we
have fully registered the cd(4) driver instance.
scsi_da.c: Remove sysctl variable creation code from daregister(), and
move it to move it to a new function, dasysctlinit().
Queue dasysctlinit() to the taskqueue_thread taskqueue once
we have fully registered the da(4) instance.
taskqueue.h: Declare the new taskqueue_thread taskqueue, update some
comments.
subr_taskqueue.c:
Create the new kernel thread taskqueue. This taskqueue
runs outside of Giant, so any functions queued to it would
need to explicitly acquire/release Giant if they need it.
cd.4: Update the cd(4) man page to talk about the minimum command
size sysctl/loader tunable. Also note that the changer
variables are available as loader tunables as well.
da.4: Update the da(4) man page to cover the retry_count,
default_timeout and minimum_cmd_size sysctl variables/loader
tunables. Remove references to /dev/r???, they aren't used
any longer.
cd.9: Update the cd(9) man page to describe the CD_Q_10_BYTE_ONLY
quirk.
taskqueue.9: Update the taskqueue(9) man page to describe the new thread
task queue, and the taskqueue_swi_giant queue.
MFC after: 3 days
2003-09-03 04:46:28 +00:00
|
|
|
* the fly.
|
|
|
|
*/
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
SYSCTL_ADD_PROC(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree),
|
2015-10-11 18:26:06 +00:00
|
|
|
OID_AUTO, "delete_method", CTLTYPE_STRING | CTLFLAG_RWTUN,
|
2013-01-10 11:57:46 +00:00
|
|
|
softc, 0, dadeletemethodsysctl, "A",
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
"BIO_DELETE execution method");
|
2013-04-26 16:22:54 +00:00
|
|
|
SYSCTL_ADD_PROC(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree),
|
|
|
|
OID_AUTO, "delete_max", CTLTYPE_U64 | CTLFLAG_RW,
|
|
|
|
softc, 0, dadeletemaxsysctl, "Q",
|
|
|
|
"Maximum BIO_DELETE size");
|
2010-06-07 17:41:34 +00:00
|
|
|
SYSCTL_ADD_PROC(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree),
|
Move dynamic sysctl(8) variable creation for the cd(4) and da(4) drivers
out of cdregister() and daregister(), which are run from interrupt context.
The sysctl code does blocking mallocs (M_WAITOK), which causes problems
if malloc(9) actually needs to sleep.
The eventual fix for this issue will involve moving the CAM probe process
inside a kernel thread. For now, though, I have fixed the issue by moving
dynamic sysctl variable creation for these two drivers to a task queue
running in a kernel thread.
The existing task queues (taskqueue_swi and taskqueue_swi_giant) run in
software interrupt handlers, which wouldn't fix the problem at hand. So I
have created a new task queue, taskqueue_thread, that runs inside a kernel
thread. (It also runs outside of Giant -- clients must explicitly acquire
and release Giant in their taskqueue functions.)
scsi_cd.c: Remove sysctl variable creation code from cdregister(), and
move it to a new function, cdsysctlinit(). Queue
cdsysctlinit() to the taskqueue_thread taskqueue once we
have fully registered the cd(4) driver instance.
scsi_da.c: Remove sysctl variable creation code from daregister(), and
move it to move it to a new function, dasysctlinit().
Queue dasysctlinit() to the taskqueue_thread taskqueue once
we have fully registered the da(4) instance.
taskqueue.h: Declare the new taskqueue_thread taskqueue, update some
comments.
subr_taskqueue.c:
Create the new kernel thread taskqueue. This taskqueue
runs outside of Giant, so any functions queued to it would
need to explicitly acquire/release Giant if they need it.
cd.4: Update the cd(4) man page to talk about the minimum command
size sysctl/loader tunable. Also note that the changer
variables are available as loader tunables as well.
da.4: Update the da(4) man page to cover the retry_count,
default_timeout and minimum_cmd_size sysctl variables/loader
tunables. Remove references to /dev/r???, they aren't used
any longer.
cd.9: Update the cd(9) man page to describe the CD_Q_10_BYTE_ONLY
quirk.
taskqueue.9: Update the taskqueue(9) man page to describe the new thread
task queue, and the taskqueue_swi_giant queue.
MFC after: 3 days
2003-09-03 04:46:28 +00:00
|
|
|
OID_AUTO, "minimum_cmd_size", CTLTYPE_INT | CTLFLAG_RW,
|
|
|
|
&softc->minimum_cmd_size, 0, dacmdsizesysctl, "I",
|
|
|
|
"Minimum CDB size");
|
2013-03-29 22:58:15 +00:00
|
|
|
SYSCTL_ADD_INT(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree),
|
|
|
|
OID_AUTO, "sort_io_queue", CTLFLAG_RW, &softc->sort_io_queue, 0,
|
|
|
|
"Sort IO queue to try and optimise disk access patterns");
|
Move dynamic sysctl(8) variable creation for the cd(4) and da(4) drivers
out of cdregister() and daregister(), which are run from interrupt context.
The sysctl code does blocking mallocs (M_WAITOK), which causes problems
if malloc(9) actually needs to sleep.
The eventual fix for this issue will involve moving the CAM probe process
inside a kernel thread. For now, though, I have fixed the issue by moving
dynamic sysctl variable creation for these two drivers to a task queue
running in a kernel thread.
The existing task queues (taskqueue_swi and taskqueue_swi_giant) run in
software interrupt handlers, which wouldn't fix the problem at hand. So I
have created a new task queue, taskqueue_thread, that runs inside a kernel
thread. (It also runs outside of Giant -- clients must explicitly acquire
and release Giant in their taskqueue functions.)
scsi_cd.c: Remove sysctl variable creation code from cdregister(), and
move it to a new function, cdsysctlinit(). Queue
cdsysctlinit() to the taskqueue_thread taskqueue once we
have fully registered the cd(4) driver instance.
scsi_da.c: Remove sysctl variable creation code from daregister(), and
move it to move it to a new function, dasysctlinit().
Queue dasysctlinit() to the taskqueue_thread taskqueue once
we have fully registered the da(4) instance.
taskqueue.h: Declare the new taskqueue_thread taskqueue, update some
comments.
subr_taskqueue.c:
Create the new kernel thread taskqueue. This taskqueue
runs outside of Giant, so any functions queued to it would
need to explicitly acquire/release Giant if they need it.
cd.4: Update the cd(4) man page to talk about the minimum command
size sysctl/loader tunable. Also note that the changer
variables are available as loader tunables as well.
da.4: Update the da(4) man page to cover the retry_count,
default_timeout and minimum_cmd_size sysctl variables/loader
tunables. Remove references to /dev/r???, they aren't used
any longer.
cd.9: Update the cd(9) man page to describe the CD_Q_10_BYTE_ONLY
quirk.
taskqueue.9: Update the taskqueue(9) man page to describe the new thread
task queue, and the taskqueue_swi_giant queue.
MFC after: 3 days
2003-09-03 04:46:28 +00:00
|
|
|
|
Fix a race condition in CAM peripheral free handling, locking
in the CAM XPT bus traversal code, and a number of other periph level
issues.
cam_periph.h,
cam_periph.c: Modify cam_periph_acquire() to test the CAM_PERIPH_INVALID
flag prior to allowing a reference count to be gained
on a peripheral. Callers of this function will receive
CAM_REQ_CMP_ERR status in the situation of attempting to
reference an invalidated periph. This guarantees that
a peripheral scheduled for a deferred free will not
be accessed during its wait for destruction.
Panic during attempts to drop a reference count on
a peripheral that already has a zero reference count.
In cam_periph_list(), use a local sbuf with SBUF_FIXEDLEN
set so that mallocs do not occur while the xpt topology
lock is held, regardless of the allocation policy of the
passed in sbuf.
Add a new routine, cam_periph_release_locked_buses(),
that can be called when the caller already holds
the CAM topology lock.
Add some extra debugging for duplicate peripheral
allocations in cam_periph_alloc().
Treat CAM_DEV_NOT_THERE much the same as a selection
timeout (AC_LOST_DEVICE is emitted), but forgo retries.
cam_xpt.c: Revamp the way the EDT traversal code does locking
and reference counting. This was broken, since it
assumed that the EDT would not change during
traversal, but that assumption is no longer valid.
So, to prevent devices from going away while we
traverse the EDT, make sure we properly lock
everything and hold references on devices that
we are using.
The two peripheral driver traversal routines should
be examined. xptpdperiphtraverse() holds the
topology lock for the entire time it runs.
xptperiphtraverse() is now locked properly, but
only holds the topology lock while it is traversing
the list, and not while the traversal function is
running.
The bus locking code in xptbustraverse() should
also be revisited at a later time, since it is
complex and should probably be simplified.
scsi_da.c: Pay attention to the return value from cam_periph_acquire().
Return 0 always from daclose() even if the disk is now gone.
Add some rudimentary error injection support.
scsi_sg.c: Fix reference counting in the sg(4) driver.
The sg driver was calling cam_periph_release() on close,
but never called cam_periph_acquire() (which increments
the reference count) on open.
The periph code correctly complained that the sg(4)
driver was trying to decrement the refcount when it
was already 0.
Sponsored by: Spectra Logic
MFC after: 2 weeks
2012-01-12 00:41:48 +00:00
|
|
|
SYSCTL_ADD_INT(&softc->sysctl_ctx,
|
|
|
|
SYSCTL_CHILDREN(softc->sysctl_tree),
|
|
|
|
OID_AUTO,
|
|
|
|
"error_inject",
|
|
|
|
CTLFLAG_RW,
|
|
|
|
&softc->error_inject,
|
|
|
|
0,
|
|
|
|
"error_inject leaf");
|
|
|
|
|
|
|
|
|
2010-06-07 17:41:34 +00:00
|
|
|
/*
|
|
|
|
* Add some addressing info.
|
|
|
|
*/
|
|
|
|
memset(&cts, 0, sizeof (cts));
|
2012-10-27 09:40:29 +00:00
|
|
|
xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NONE);
|
2010-06-07 17:41:34 +00:00
|
|
|
cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
|
|
|
|
cts.type = CTS_TYPE_CURRENT_SETTINGS;
|
|
|
|
cam_periph_lock(periph);
|
|
|
|
xpt_action((union ccb *)&cts);
|
|
|
|
cam_periph_unlock(periph);
|
|
|
|
if (cts.ccb_h.status != CAM_REQ_CMP) {
|
|
|
|
cam_periph_release(periph);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (cts.protocol == PROTO_SCSI && cts.transport == XPORT_FC) {
|
|
|
|
struct ccb_trans_settings_fc *fc = &cts.xport_specific.fc;
|
|
|
|
if (fc->valid & CTS_FC_VALID_WWPN) {
|
|
|
|
softc->wwpn = fc->wwpn;
|
2011-01-19 17:04:07 +00:00
|
|
|
SYSCTL_ADD_UQUAD(&softc->sysctl_ctx,
|
2010-06-07 17:41:34 +00:00
|
|
|
SYSCTL_CHILDREN(softc->sysctl_tree),
|
2011-01-13 18:20:33 +00:00
|
|
|
OID_AUTO, "wwpn", CTLFLAG_RD,
|
2010-06-07 17:41:34 +00:00
|
|
|
&softc->wwpn, "World Wide Port Name");
|
|
|
|
}
|
|
|
|
}
|
2007-04-15 08:49:19 +00:00
|
|
|
cam_periph_release(periph);
|
Move dynamic sysctl(8) variable creation for the cd(4) and da(4) drivers
out of cdregister() and daregister(), which are run from interrupt context.
The sysctl code does blocking mallocs (M_WAITOK), which causes problems
if malloc(9) actually needs to sleep.
The eventual fix for this issue will involve moving the CAM probe process
inside a kernel thread. For now, though, I have fixed the issue by moving
dynamic sysctl variable creation for these two drivers to a task queue
running in a kernel thread.
The existing task queues (taskqueue_swi and taskqueue_swi_giant) run in
software interrupt handlers, which wouldn't fix the problem at hand. So I
have created a new task queue, taskqueue_thread, that runs inside a kernel
thread. (It also runs outside of Giant -- clients must explicitly acquire
and release Giant in their taskqueue functions.)
scsi_cd.c: Remove sysctl variable creation code from cdregister(), and
move it to a new function, cdsysctlinit(). Queue
cdsysctlinit() to the taskqueue_thread taskqueue once we
have fully registered the cd(4) driver instance.
scsi_da.c: Remove sysctl variable creation code from daregister(), and
move it to move it to a new function, dasysctlinit().
Queue dasysctlinit() to the taskqueue_thread taskqueue once
we have fully registered the da(4) instance.
taskqueue.h: Declare the new taskqueue_thread taskqueue, update some
comments.
subr_taskqueue.c:
Create the new kernel thread taskqueue. This taskqueue
runs outside of Giant, so any functions queued to it would
need to explicitly acquire/release Giant if they need it.
cd.4: Update the cd(4) man page to talk about the minimum command
size sysctl/loader tunable. Also note that the changer
variables are available as loader tunables as well.
da.4: Update the da(4) man page to cover the retry_count,
default_timeout and minimum_cmd_size sysctl variables/loader
tunables. Remove references to /dev/r???, they aren't used
any longer.
cd.9: Update the cd(9) man page to describe the CD_Q_10_BYTE_ONLY
quirk.
taskqueue.9: Update the taskqueue(9) man page to describe the new thread
task queue, and the taskqueue_swi_giant queue.
MFC after: 3 days
2003-09-03 04:46:28 +00:00
|
|
|
}
|
|
|
|
|
2013-04-26 16:22:54 +00:00
|
|
|
static int
|
|
|
|
dadeletemaxsysctl(SYSCTL_HANDLER_ARGS)
|
|
|
|
{
|
|
|
|
int error;
|
|
|
|
uint64_t value;
|
|
|
|
struct da_softc *softc;
|
|
|
|
|
|
|
|
softc = (struct da_softc *)arg1;
|
|
|
|
|
|
|
|
value = softc->disk->d_delmaxsize;
|
|
|
|
error = sysctl_handle_64(oidp, &value, 0, req);
|
|
|
|
if ((error != 0) || (req->newptr == NULL))
|
|
|
|
return (error);
|
|
|
|
|
|
|
|
/* only accept values smaller than the calculated value */
|
2013-07-03 23:46:30 +00:00
|
|
|
if (value > dadeletemaxsize(softc, softc->delete_method)) {
|
2013-04-26 16:22:54 +00:00
|
|
|
return (EINVAL);
|
|
|
|
}
|
|
|
|
softc->disk->d_delmaxsize = value;
|
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
Fix ATAPI/USB/Firewire CDROM drive handling in cd(4) and hopefully fix
a number of related problems along the way.
- Automatically detect CDROM drives that can't handle 6 byte mode
sense and mode select, and adjust our command size accordingly.
We have to handle this in the cd(4) driver (where the buffers are
allocated), since the parameter list length is different for the
6 and 10 byte mode sense commands.
- Remove MODE_SENSE and MODE_SELECT translation removed in ATAPICAM
and in the umass(4) driver, since there's no way for that to work
properly.
- Add a quirk entry for CDROM drives that just hang when they get a 6
byte mode sense or mode select. The reason for the quirk must be
documented in a PR, and all quirks must be approved by
ken@FreeBSD.org. This is to make sure that we fully understand why
each quirk is needed. Once the CAM_NEW_TRAN_CODE is finished, we
should be able to remove any such quirks, since we'll know what
protocol the drive speaks (SCSI, ATAPI, etc.) and therefore whether
we should use 6 or 10 byte mode sense/select commands.
- Change the way the da(4) handles the no_6_byte sysctl. There is
now a per-drive sysctl to set the minimum command size for that
particular disk. (Since you could have multiple disks with
multiple requirements in one system.)
- Loader tunable support for all the sysctls in the da(4) and cd(4)
drivers.
- Add a CDIOCCLOSE ioctl for cd(4) (bde pointed this out a long
time ago).
- Add a media validation routine (cdcheckmedia()) to the cd(4)
driver, to fix some problems bde pointed out a long time ago. We
now allow open() to succeed no matter what, but if we don't detect
valid media, the user can only issue CDIOCCLOSE or CDIOCEJECT
ioctls.
- The media validation routine also reads the table of contents off
the drive. We use the table of contents to implement the
CDIOCPLAYTRACKS ioctl using the PLAY AUDIO MSF command. The
PLAY AUDIO TRACK INDEX command that we previously used was
deprecated after SCSI-2. It works in every SCSI CDROM I've tried,
but doesn't seem to work on ATAPI CDROM drives. We still use the
play audio track index command if we don't have a valid TOC, but
I suppose it'll fail anyway in that case.
- Add _len() versions of scsi_mode_sense() and scsi_mode_select() so
that we can specify the minimum command length.
- Fix a couple of formatting problems in the sense printing code.
MFC after: 4 weeks
2003-02-21 06:19:38 +00:00
|
|
|
static int
|
|
|
|
dacmdsizesysctl(SYSCTL_HANDLER_ARGS)
|
|
|
|
{
|
|
|
|
int error, value;
|
|
|
|
|
|
|
|
value = *(int *)arg1;
|
|
|
|
|
|
|
|
error = sysctl_handle_int(oidp, &value, 0, req);
|
|
|
|
|
|
|
|
if ((error != 0)
|
|
|
|
|| (req->newptr == NULL))
|
|
|
|
return (error);
|
|
|
|
|
|
|
|
/*
|
Add support to CAM for devices with more than 2^32 blocks. (2TB if you're
using 512 byte blocks).
cam_ccb.h: Bump up volume_size and cylinders in ccb_calc_geometry to
64 bits and 32 bits respectively, so we can hold larger
device sizes. cylinders would overflow at about 500GB.
Bump CAM_VERSION for this change. Note that this will
require a recompile of all applications that talk to the
pass(4) driver.
scsi_all.c: Add descriptions for READ/WRITE(16), update READ/WRITE(12)
descriptions, add descriptions for SERVICE ACTION IN/OUT.
Add a new function, scsi_read_capacity_16(), that issues
the read capacity service action. (Necessary for arrays
larger than 2^32 sectors.) Update scsi_read_write() to use
a 64 bit LBA and issue READ(16) or WRITE(16) if necessary.
NOTE the API change. This should be largely transparnet
to most userland applications at compile time, but will
break binary compatibility. The CAM_VERSION bump, above,
also serves the purpose of forcing a recompile for any
applications that talk to CAM.
scsi_all.h: Add 16 byte READ/WRITE structures, structures for 16 byte
READ CAPACITY/SERVICE ACTION IN. Add scsi_u64to8b() and
scsi_8btou64.
scsi_da.c: The da(4) driver probe now has two stages for devices
larger than 2TB. If a standard READ CAPACITY(10) returns
0xffffffff, we issue the 16 byte version of read capacity
to determine the true array capacity. We also do the same
thing in daopen() -- use the 16 byte read capacity if the
device is large enough.
The sysctl/loader code has also been updated to accept
16 bytes as a minimum command size.
2003-04-30 00:35:22 +00:00
|
|
|
* Acceptable values here are 6, 10, 12 or 16.
|
Fix ATAPI/USB/Firewire CDROM drive handling in cd(4) and hopefully fix
a number of related problems along the way.
- Automatically detect CDROM drives that can't handle 6 byte mode
sense and mode select, and adjust our command size accordingly.
We have to handle this in the cd(4) driver (where the buffers are
allocated), since the parameter list length is different for the
6 and 10 byte mode sense commands.
- Remove MODE_SENSE and MODE_SELECT translation removed in ATAPICAM
and in the umass(4) driver, since there's no way for that to work
properly.
- Add a quirk entry for CDROM drives that just hang when they get a 6
byte mode sense or mode select. The reason for the quirk must be
documented in a PR, and all quirks must be approved by
ken@FreeBSD.org. This is to make sure that we fully understand why
each quirk is needed. Once the CAM_NEW_TRAN_CODE is finished, we
should be able to remove any such quirks, since we'll know what
protocol the drive speaks (SCSI, ATAPI, etc.) and therefore whether
we should use 6 or 10 byte mode sense/select commands.
- Change the way the da(4) handles the no_6_byte sysctl. There is
now a per-drive sysctl to set the minimum command size for that
particular disk. (Since you could have multiple disks with
multiple requirements in one system.)
- Loader tunable support for all the sysctls in the da(4) and cd(4)
drivers.
- Add a CDIOCCLOSE ioctl for cd(4) (bde pointed this out a long
time ago).
- Add a media validation routine (cdcheckmedia()) to the cd(4)
driver, to fix some problems bde pointed out a long time ago. We
now allow open() to succeed no matter what, but if we don't detect
valid media, the user can only issue CDIOCCLOSE or CDIOCEJECT
ioctls.
- The media validation routine also reads the table of contents off
the drive. We use the table of contents to implement the
CDIOCPLAYTRACKS ioctl using the PLAY AUDIO MSF command. The
PLAY AUDIO TRACK INDEX command that we previously used was
deprecated after SCSI-2. It works in every SCSI CDROM I've tried,
but doesn't seem to work on ATAPI CDROM drives. We still use the
play audio track index command if we don't have a valid TOC, but
I suppose it'll fail anyway in that case.
- Add _len() versions of scsi_mode_sense() and scsi_mode_select() so
that we can specify the minimum command length.
- Fix a couple of formatting problems in the sense printing code.
MFC after: 4 weeks
2003-02-21 06:19:38 +00:00
|
|
|
*/
|
|
|
|
if (value < 6)
|
|
|
|
value = 6;
|
|
|
|
else if ((value > 6)
|
|
|
|
&& (value <= 10))
|
|
|
|
value = 10;
|
Add support to CAM for devices with more than 2^32 blocks. (2TB if you're
using 512 byte blocks).
cam_ccb.h: Bump up volume_size and cylinders in ccb_calc_geometry to
64 bits and 32 bits respectively, so we can hold larger
device sizes. cylinders would overflow at about 500GB.
Bump CAM_VERSION for this change. Note that this will
require a recompile of all applications that talk to the
pass(4) driver.
scsi_all.c: Add descriptions for READ/WRITE(16), update READ/WRITE(12)
descriptions, add descriptions for SERVICE ACTION IN/OUT.
Add a new function, scsi_read_capacity_16(), that issues
the read capacity service action. (Necessary for arrays
larger than 2^32 sectors.) Update scsi_read_write() to use
a 64 bit LBA and issue READ(16) or WRITE(16) if necessary.
NOTE the API change. This should be largely transparnet
to most userland applications at compile time, but will
break binary compatibility. The CAM_VERSION bump, above,
also serves the purpose of forcing a recompile for any
applications that talk to CAM.
scsi_all.h: Add 16 byte READ/WRITE structures, structures for 16 byte
READ CAPACITY/SERVICE ACTION IN. Add scsi_u64to8b() and
scsi_8btou64.
scsi_da.c: The da(4) driver probe now has two stages for devices
larger than 2TB. If a standard READ CAPACITY(10) returns
0xffffffff, we issue the 16 byte version of read capacity
to determine the true array capacity. We also do the same
thing in daopen() -- use the 16 byte read capacity if the
device is large enough.
The sysctl/loader code has also been updated to accept
16 bytes as a minimum command size.
2003-04-30 00:35:22 +00:00
|
|
|
else if ((value > 10)
|
|
|
|
&& (value <= 12))
|
Fix ATAPI/USB/Firewire CDROM drive handling in cd(4) and hopefully fix
a number of related problems along the way.
- Automatically detect CDROM drives that can't handle 6 byte mode
sense and mode select, and adjust our command size accordingly.
We have to handle this in the cd(4) driver (where the buffers are
allocated), since the parameter list length is different for the
6 and 10 byte mode sense commands.
- Remove MODE_SENSE and MODE_SELECT translation removed in ATAPICAM
and in the umass(4) driver, since there's no way for that to work
properly.
- Add a quirk entry for CDROM drives that just hang when they get a 6
byte mode sense or mode select. The reason for the quirk must be
documented in a PR, and all quirks must be approved by
ken@FreeBSD.org. This is to make sure that we fully understand why
each quirk is needed. Once the CAM_NEW_TRAN_CODE is finished, we
should be able to remove any such quirks, since we'll know what
protocol the drive speaks (SCSI, ATAPI, etc.) and therefore whether
we should use 6 or 10 byte mode sense/select commands.
- Change the way the da(4) handles the no_6_byte sysctl. There is
now a per-drive sysctl to set the minimum command size for that
particular disk. (Since you could have multiple disks with
multiple requirements in one system.)
- Loader tunable support for all the sysctls in the da(4) and cd(4)
drivers.
- Add a CDIOCCLOSE ioctl for cd(4) (bde pointed this out a long
time ago).
- Add a media validation routine (cdcheckmedia()) to the cd(4)
driver, to fix some problems bde pointed out a long time ago. We
now allow open() to succeed no matter what, but if we don't detect
valid media, the user can only issue CDIOCCLOSE or CDIOCEJECT
ioctls.
- The media validation routine also reads the table of contents off
the drive. We use the table of contents to implement the
CDIOCPLAYTRACKS ioctl using the PLAY AUDIO MSF command. The
PLAY AUDIO TRACK INDEX command that we previously used was
deprecated after SCSI-2. It works in every SCSI CDROM I've tried,
but doesn't seem to work on ATAPI CDROM drives. We still use the
play audio track index command if we don't have a valid TOC, but
I suppose it'll fail anyway in that case.
- Add _len() versions of scsi_mode_sense() and scsi_mode_select() so
that we can specify the minimum command length.
- Fix a couple of formatting problems in the sense printing code.
MFC after: 4 weeks
2003-02-21 06:19:38 +00:00
|
|
|
value = 12;
|
Add support to CAM for devices with more than 2^32 blocks. (2TB if you're
using 512 byte blocks).
cam_ccb.h: Bump up volume_size and cylinders in ccb_calc_geometry to
64 bits and 32 bits respectively, so we can hold larger
device sizes. cylinders would overflow at about 500GB.
Bump CAM_VERSION for this change. Note that this will
require a recompile of all applications that talk to the
pass(4) driver.
scsi_all.c: Add descriptions for READ/WRITE(16), update READ/WRITE(12)
descriptions, add descriptions for SERVICE ACTION IN/OUT.
Add a new function, scsi_read_capacity_16(), that issues
the read capacity service action. (Necessary for arrays
larger than 2^32 sectors.) Update scsi_read_write() to use
a 64 bit LBA and issue READ(16) or WRITE(16) if necessary.
NOTE the API change. This should be largely transparnet
to most userland applications at compile time, but will
break binary compatibility. The CAM_VERSION bump, above,
also serves the purpose of forcing a recompile for any
applications that talk to CAM.
scsi_all.h: Add 16 byte READ/WRITE structures, structures for 16 byte
READ CAPACITY/SERVICE ACTION IN. Add scsi_u64to8b() and
scsi_8btou64.
scsi_da.c: The da(4) driver probe now has two stages for devices
larger than 2TB. If a standard READ CAPACITY(10) returns
0xffffffff, we issue the 16 byte version of read capacity
to determine the true array capacity. We also do the same
thing in daopen() -- use the 16 byte read capacity if the
device is large enough.
The sysctl/loader code has also been updated to accept
16 bytes as a minimum command size.
2003-04-30 00:35:22 +00:00
|
|
|
else if (value > 12)
|
|
|
|
value = 16;
|
Fix ATAPI/USB/Firewire CDROM drive handling in cd(4) and hopefully fix
a number of related problems along the way.
- Automatically detect CDROM drives that can't handle 6 byte mode
sense and mode select, and adjust our command size accordingly.
We have to handle this in the cd(4) driver (where the buffers are
allocated), since the parameter list length is different for the
6 and 10 byte mode sense commands.
- Remove MODE_SENSE and MODE_SELECT translation removed in ATAPICAM
and in the umass(4) driver, since there's no way for that to work
properly.
- Add a quirk entry for CDROM drives that just hang when they get a 6
byte mode sense or mode select. The reason for the quirk must be
documented in a PR, and all quirks must be approved by
ken@FreeBSD.org. This is to make sure that we fully understand why
each quirk is needed. Once the CAM_NEW_TRAN_CODE is finished, we
should be able to remove any such quirks, since we'll know what
protocol the drive speaks (SCSI, ATAPI, etc.) and therefore whether
we should use 6 or 10 byte mode sense/select commands.
- Change the way the da(4) handles the no_6_byte sysctl. There is
now a per-drive sysctl to set the minimum command size for that
particular disk. (Since you could have multiple disks with
multiple requirements in one system.)
- Loader tunable support for all the sysctls in the da(4) and cd(4)
drivers.
- Add a CDIOCCLOSE ioctl for cd(4) (bde pointed this out a long
time ago).
- Add a media validation routine (cdcheckmedia()) to the cd(4)
driver, to fix some problems bde pointed out a long time ago. We
now allow open() to succeed no matter what, but if we don't detect
valid media, the user can only issue CDIOCCLOSE or CDIOCEJECT
ioctls.
- The media validation routine also reads the table of contents off
the drive. We use the table of contents to implement the
CDIOCPLAYTRACKS ioctl using the PLAY AUDIO MSF command. The
PLAY AUDIO TRACK INDEX command that we previously used was
deprecated after SCSI-2. It works in every SCSI CDROM I've tried,
but doesn't seem to work on ATAPI CDROM drives. We still use the
play audio track index command if we don't have a valid TOC, but
I suppose it'll fail anyway in that case.
- Add _len() versions of scsi_mode_sense() and scsi_mode_select() so
that we can specify the minimum command length.
- Fix a couple of formatting problems in the sense printing code.
MFC after: 4 weeks
2003-02-21 06:19:38 +00:00
|
|
|
|
|
|
|
*(int *)arg1 = value;
|
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
2013-04-26 15:31:52 +00:00
|
|
|
static void
|
2013-01-10 11:57:46 +00:00
|
|
|
dadeletemethodset(struct da_softc *softc, da_delete_methods delete_method)
|
|
|
|
{
|
|
|
|
|
|
|
|
softc->delete_method = delete_method;
|
2013-04-26 16:22:54 +00:00
|
|
|
softc->disk->d_delmaxsize = dadeletemaxsize(softc, delete_method);
|
2013-07-12 23:20:11 +00:00
|
|
|
softc->delete_func = da_delete_functions[delete_method];
|
2013-01-10 11:57:46 +00:00
|
|
|
|
|
|
|
if (softc->delete_method > DA_DELETE_DISABLE)
|
|
|
|
softc->disk->d_flags |= DISKFLAG_CANDELETE;
|
|
|
|
else
|
|
|
|
softc->disk->d_flags &= ~DISKFLAG_CANDELETE;
|
|
|
|
}
|
|
|
|
|
2013-04-26 16:22:54 +00:00
|
|
|
static off_t
|
|
|
|
dadeletemaxsize(struct da_softc *softc, da_delete_methods delete_method)
|
|
|
|
{
|
|
|
|
off_t sectors;
|
|
|
|
|
|
|
|
switch(delete_method) {
|
|
|
|
case DA_DELETE_UNMAP:
|
2014-01-22 22:19:53 +00:00
|
|
|
sectors = (off_t)softc->unmap_max_lba;
|
2013-04-26 16:22:54 +00:00
|
|
|
break;
|
|
|
|
case DA_DELETE_ATA_TRIM:
|
|
|
|
sectors = (off_t)ATA_DSM_RANGE_MAX * softc->trim_max_ranges;
|
|
|
|
break;
|
|
|
|
case DA_DELETE_WS16:
|
2015-01-26 15:47:08 +00:00
|
|
|
sectors = omin(softc->ws_max_blks, WS16_MAX_BLKS);
|
2013-04-26 16:22:54 +00:00
|
|
|
break;
|
|
|
|
case DA_DELETE_ZERO:
|
|
|
|
case DA_DELETE_WS10:
|
2015-01-26 15:47:08 +00:00
|
|
|
sectors = omin(softc->ws_max_blks, WS10_MAX_BLKS);
|
2013-04-26 16:22:54 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (off_t)softc->params.secsize *
|
2015-01-26 15:47:08 +00:00
|
|
|
omin(sectors, softc->params.sectors);
|
2013-04-26 16:22:54 +00:00
|
|
|
}
|
|
|
|
|
2013-05-02 14:37:23 +00:00
|
|
|
static void
|
|
|
|
daprobedone(struct cam_periph *periph, union ccb *ccb)
|
|
|
|
{
|
|
|
|
struct da_softc *softc;
|
|
|
|
|
|
|
|
softc = (struct da_softc *)periph->softc;
|
|
|
|
|
|
|
|
dadeletemethodchoose(softc, DA_DELETE_NONE);
|
|
|
|
|
2014-04-30 17:38:26 +00:00
|
|
|
if (bootverbose && (softc->flags & DA_FLAG_ANNOUNCED) == 0) {
|
2013-05-02 14:37:23 +00:00
|
|
|
char buf[80];
|
|
|
|
int i, sep;
|
|
|
|
|
|
|
|
snprintf(buf, sizeof(buf), "Delete methods: <");
|
|
|
|
sep = 0;
|
2015-10-11 18:26:06 +00:00
|
|
|
for (i = 0; i <= DA_DELETE_MAX; i++) {
|
|
|
|
if ((softc->delete_available & (1 << i)) == 0 &&
|
|
|
|
i != softc->delete_method)
|
|
|
|
continue;
|
|
|
|
if (sep)
|
|
|
|
strlcat(buf, ",", sizeof(buf));
|
|
|
|
strlcat(buf, da_delete_method_names[i],
|
|
|
|
sizeof(buf));
|
|
|
|
if (i == softc->delete_method)
|
|
|
|
strlcat(buf, "(*)", sizeof(buf));
|
|
|
|
sep = 1;
|
2013-05-02 14:37:23 +00:00
|
|
|
}
|
|
|
|
strlcat(buf, ">", sizeof(buf));
|
|
|
|
printf("%s%d: %s\n", periph->periph_name,
|
|
|
|
periph->unit_number, buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Since our peripheral may be invalidated by an error
|
|
|
|
* above or an external event, we must release our CCB
|
|
|
|
* before releasing the probe lock on the peripheral.
|
|
|
|
* The peripheral will only go away once the last lock
|
|
|
|
* is removed, and we need it around for the CCB release
|
|
|
|
* operation.
|
|
|
|
*/
|
|
|
|
xpt_release_ccb(ccb);
|
|
|
|
softc->state = DA_STATE_NORMAL;
|
2014-04-30 17:38:26 +00:00
|
|
|
softc->flags |= DA_FLAG_PROBED;
|
2013-05-02 14:37:23 +00:00
|
|
|
daschedule(periph);
|
|
|
|
wakeup(&softc->disk->d_mediasize);
|
2014-04-30 17:38:26 +00:00
|
|
|
if ((softc->flags & DA_FLAG_ANNOUNCED) == 0) {
|
|
|
|
softc->flags |= DA_FLAG_ANNOUNCED;
|
2013-05-02 14:37:23 +00:00
|
|
|
cam_periph_unhold(periph);
|
|
|
|
} else
|
|
|
|
cam_periph_release_locked(periph);
|
|
|
|
}
|
|
|
|
|
2013-04-26 16:17:04 +00:00
|
|
|
static void
|
|
|
|
dadeletemethodchoose(struct da_softc *softc, da_delete_methods default_method)
|
|
|
|
{
|
2015-10-11 18:26:06 +00:00
|
|
|
int i, methods;
|
2013-04-26 16:17:04 +00:00
|
|
|
|
2015-10-11 18:26:06 +00:00
|
|
|
/* If available, prefer the method requested by user. */
|
|
|
|
i = softc->delete_method_pref;
|
|
|
|
methods = softc->delete_available | (1 << DA_DELETE_DISABLE);
|
|
|
|
if (methods & (1 << i)) {
|
|
|
|
dadeletemethodset(softc, i);
|
|
|
|
return;
|
|
|
|
}
|
2013-04-26 16:17:04 +00:00
|
|
|
|
2015-10-11 18:26:06 +00:00
|
|
|
/* Use the pre-defined order to choose the best performing delete. */
|
2013-04-26 16:17:04 +00:00
|
|
|
for (i = DA_DELETE_MIN; i <= DA_DELETE_MAX; i++) {
|
2015-10-11 18:26:06 +00:00
|
|
|
if (i == DA_DELETE_ZERO)
|
|
|
|
continue;
|
2013-04-26 16:17:04 +00:00
|
|
|
if (softc->delete_available & (1 << i)) {
|
|
|
|
dadeletemethodset(softc, i);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2015-10-11 18:26:06 +00:00
|
|
|
|
|
|
|
/* Fallback to default. */
|
|
|
|
dadeletemethodset(softc, default_method);
|
2013-04-26 16:17:04 +00:00
|
|
|
}
|
|
|
|
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
static int
|
|
|
|
dadeletemethodsysctl(SYSCTL_HANDLER_ARGS)
|
|
|
|
{
|
|
|
|
char buf[16];
|
|
|
|
const char *p;
|
2013-01-10 11:57:46 +00:00
|
|
|
struct da_softc *softc;
|
2014-01-07 20:12:10 +00:00
|
|
|
int i, error, methods, value;
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
|
2013-01-10 11:57:46 +00:00
|
|
|
softc = (struct da_softc *)arg1;
|
|
|
|
|
|
|
|
value = softc->delete_method;
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
if (value < 0 || value > DA_DELETE_MAX)
|
|
|
|
p = "UNKNOWN";
|
|
|
|
else
|
|
|
|
p = da_delete_method_names[value];
|
|
|
|
strncpy(buf, p, sizeof(buf));
|
|
|
|
error = sysctl_handle_string(oidp, buf, sizeof(buf), req);
|
|
|
|
if (error != 0 || req->newptr == NULL)
|
|
|
|
return (error);
|
2014-01-07 20:12:10 +00:00
|
|
|
methods = softc->delete_available | (1 << DA_DELETE_DISABLE);
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
for (i = 0; i <= DA_DELETE_MAX; i++) {
|
2015-10-11 18:26:06 +00:00
|
|
|
if (strcmp(buf, da_delete_method_names[i]) == 0)
|
|
|
|
break;
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
}
|
2015-10-11 18:26:06 +00:00
|
|
|
if (i > DA_DELETE_MAX)
|
|
|
|
return (EINVAL);
|
|
|
|
softc->delete_method_pref = i;
|
|
|
|
dadeletemethodchoose(softc, DA_DELETE_NONE);
|
|
|
|
return (0);
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
}
|
|
|
|
|
1998-09-15 06:36:34 +00:00
|
|
|
static cam_status
|
|
|
|
daregister(struct cam_periph *periph, void *arg)
|
|
|
|
{
|
|
|
|
struct da_softc *softc;
|
2003-07-28 06:15:59 +00:00
|
|
|
struct ccb_pathinq cpi;
|
1998-09-15 06:36:34 +00:00
|
|
|
struct ccb_getdev *cgd;
|
Move dynamic sysctl(8) variable creation for the cd(4) and da(4) drivers
out of cdregister() and daregister(), which are run from interrupt context.
The sysctl code does blocking mallocs (M_WAITOK), which causes problems
if malloc(9) actually needs to sleep.
The eventual fix for this issue will involve moving the CAM probe process
inside a kernel thread. For now, though, I have fixed the issue by moving
dynamic sysctl variable creation for these two drivers to a task queue
running in a kernel thread.
The existing task queues (taskqueue_swi and taskqueue_swi_giant) run in
software interrupt handlers, which wouldn't fix the problem at hand. So I
have created a new task queue, taskqueue_thread, that runs inside a kernel
thread. (It also runs outside of Giant -- clients must explicitly acquire
and release Giant in their taskqueue functions.)
scsi_cd.c: Remove sysctl variable creation code from cdregister(), and
move it to a new function, cdsysctlinit(). Queue
cdsysctlinit() to the taskqueue_thread taskqueue once we
have fully registered the cd(4) driver instance.
scsi_da.c: Remove sysctl variable creation code from daregister(), and
move it to move it to a new function, dasysctlinit().
Queue dasysctlinit() to the taskqueue_thread taskqueue once
we have fully registered the da(4) instance.
taskqueue.h: Declare the new taskqueue_thread taskqueue, update some
comments.
subr_taskqueue.c:
Create the new kernel thread taskqueue. This taskqueue
runs outside of Giant, so any functions queued to it would
need to explicitly acquire/release Giant if they need it.
cd.4: Update the cd(4) man page to talk about the minimum command
size sysctl/loader tunable. Also note that the changer
variables are available as loader tunables as well.
da.4: Update the da(4) man page to cover the retry_count,
default_timeout and minimum_cmd_size sysctl variables/loader
tunables. Remove references to /dev/r???, they aren't used
any longer.
cd.9: Update the cd(9) man page to describe the CD_Q_10_BYTE_ONLY
quirk.
taskqueue.9: Update the taskqueue(9) man page to describe the new thread
task queue, and the taskqueue_swi_giant queue.
MFC after: 3 days
2003-09-03 04:46:28 +00:00
|
|
|
char tmpstr[80];
|
1998-10-08 05:46:38 +00:00
|
|
|
caddr_t match;
|
1998-09-15 06:36:34 +00:00
|
|
|
|
|
|
|
cgd = (struct ccb_getdev *)arg;
|
|
|
|
if (cgd == NULL) {
|
|
|
|
printf("daregister: no getdev CCB, can't register device\n");
|
|
|
|
return(CAM_REQ_CMP_ERR);
|
|
|
|
}
|
|
|
|
|
2002-10-11 09:59:22 +00:00
|
|
|
softc = (struct da_softc *)malloc(sizeof(*softc), M_DEVBUF,
|
|
|
|
M_NOWAIT|M_ZERO);
|
1998-09-15 06:36:34 +00:00
|
|
|
|
|
|
|
if (softc == NULL) {
|
|
|
|
printf("daregister: Unable to probe new device. "
|
|
|
|
"Unable to allocate softc\n");
|
|
|
|
return(CAM_REQ_CMP_ERR);
|
|
|
|
}
|
|
|
|
|
|
|
|
LIST_INIT(&softc->pending_ccbs);
|
2013-04-26 16:17:04 +00:00
|
|
|
softc->state = DA_STATE_PROBE_RC;
|
2000-04-15 05:54:02 +00:00
|
|
|
bioq_init(&softc->bio_queue);
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
bioq_init(&softc->delete_queue);
|
|
|
|
bioq_init(&softc->delete_run_queue);
|
1998-09-15 06:36:34 +00:00
|
|
|
if (SID_IS_REMOVABLE(&cgd->inq_data))
|
|
|
|
softc->flags |= DA_FLAG_PACK_REMOVABLE;
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
softc->unmap_max_ranges = UNMAP_MAX_RANGES;
|
2013-04-26 16:17:04 +00:00
|
|
|
softc->unmap_max_lba = UNMAP_RANGE_MAX;
|
|
|
|
softc->ws_max_blks = WS16_MAX_BLKS;
|
|
|
|
softc->trim_max_ranges = ATA_TRIM_MAX_RANGES;
|
2013-03-29 22:58:15 +00:00
|
|
|
softc->sort_io_queue = -1;
|
1998-09-15 06:36:34 +00:00
|
|
|
|
|
|
|
periph->softc = softc;
|
1998-10-08 05:46:38 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* See if this device has any quirks.
|
|
|
|
*/
|
|
|
|
match = cam_quirkmatch((caddr_t)&cgd->inq_data,
|
|
|
|
(caddr_t)da_quirk_table,
|
|
|
|
sizeof(da_quirk_table)/sizeof(*da_quirk_table),
|
|
|
|
sizeof(*da_quirk_table), scsi_inquiry_match);
|
|
|
|
|
|
|
|
if (match != NULL)
|
|
|
|
softc->quirks = ((struct da_quirk_entry *)match)->quirks;
|
|
|
|
else
|
|
|
|
softc->quirks = DA_Q_NONE;
|
|
|
|
|
2003-07-28 06:15:59 +00:00
|
|
|
/* Check if the SIM does not want 6 byte commands */
|
Separate the parallel scsi knowledge out of the core of the XPT, and
modularize it so that new transports can be created.
Add a transport for SATA
Add a periph+protocol layer for ATA
Add a driver for AHCI-compliant hardware.
Add a maxio field to CAM so that drivers can advertise their max
I/O capability. Modify various drivers so that they are insulated
from the value of MAXPHYS.
The new ATA/SATA code supports AHCI-compliant hardware, and will override
the classic ATA driver if it is loaded as a module at boot time or compiled
into the kernel. The stack now support NCQ (tagged queueing) for increased
performance on modern SATA drives. It also supports port multipliers.
ATA drives are accessed via 'ada' device nodes. ATAPI drives are
accessed via 'cd' device nodes. They can all be enumerated and manipulated
via camcontrol, just like SCSI drives. SCSI commands are not translated to
their ATA equivalents; ATA native commands are used throughout the entire
stack, including camcontrol. See the camcontrol manpage for further
details. Testing this code may require that you update your fstab, and
possibly modify your BIOS to enable AHCI functionality, if available.
This code is very experimental at the moment. The userland ABI/API has
changed, so applications will need to be recompiled. It may change
further in the near future. The 'ada' device name may also change as
more infrastructure is completed in this project. The goal is to
eventually put all CAM busses and devices until newbus, allowing for
interesting topology and management options.
Few functional changes will be seen with existing SCSI/SAS/FC drivers,
though the userland ABI has still changed. In the future, transports
specific modules for SAS and FC may appear in order to better support
the topologies and capabilities of these technologies.
The modularization of CAM and the addition of the ATA/SATA modules is
meant to break CAM out of the mold of being specific to SCSI, letting it
grow to be a framework for arbitrary transports and protocols. It also
allows drivers to be written to support discrete hardware without
jeopardizing the stability of non-related hardware. While only an AHCI
driver is provided now, a Silicon Image driver is also in the works.
Drivers for ICH1-4, ICH5-6, PIIX, classic IDE, and any other hardware
is possible and encouraged. Help with new transports is also encouraged.
Submitted by: scottl, mav
Approved by: re
2009-07-10 08:18:08 +00:00
|
|
|
bzero(&cpi, sizeof(cpi));
|
2009-10-23 08:27:55 +00:00
|
|
|
xpt_setup_ccb(&cpi.ccb_h, periph->path, CAM_PRIORITY_NORMAL);
|
2003-07-28 06:15:59 +00:00
|
|
|
cpi.ccb_h.func_code = XPT_PATH_INQ;
|
|
|
|
xpt_action((union ccb *)&cpi);
|
|
|
|
if (cpi.ccb_h.status == CAM_REQ_CMP && (cpi.hba_misc & PIM_NO_6_BYTE))
|
|
|
|
softc->quirks |= DA_Q_NO_6_BYTE;
|
|
|
|
|
Move dynamic sysctl(8) variable creation for the cd(4) and da(4) drivers
out of cdregister() and daregister(), which are run from interrupt context.
The sysctl code does blocking mallocs (M_WAITOK), which causes problems
if malloc(9) actually needs to sleep.
The eventual fix for this issue will involve moving the CAM probe process
inside a kernel thread. For now, though, I have fixed the issue by moving
dynamic sysctl variable creation for these two drivers to a task queue
running in a kernel thread.
The existing task queues (taskqueue_swi and taskqueue_swi_giant) run in
software interrupt handlers, which wouldn't fix the problem at hand. So I
have created a new task queue, taskqueue_thread, that runs inside a kernel
thread. (It also runs outside of Giant -- clients must explicitly acquire
and release Giant in their taskqueue functions.)
scsi_cd.c: Remove sysctl variable creation code from cdregister(), and
move it to a new function, cdsysctlinit(). Queue
cdsysctlinit() to the taskqueue_thread taskqueue once we
have fully registered the cd(4) driver instance.
scsi_da.c: Remove sysctl variable creation code from daregister(), and
move it to move it to a new function, dasysctlinit().
Queue dasysctlinit() to the taskqueue_thread taskqueue once
we have fully registered the da(4) instance.
taskqueue.h: Declare the new taskqueue_thread taskqueue, update some
comments.
subr_taskqueue.c:
Create the new kernel thread taskqueue. This taskqueue
runs outside of Giant, so any functions queued to it would
need to explicitly acquire/release Giant if they need it.
cd.4: Update the cd(4) man page to talk about the minimum command
size sysctl/loader tunable. Also note that the changer
variables are available as loader tunables as well.
da.4: Update the da(4) man page to cover the retry_count,
default_timeout and minimum_cmd_size sysctl variables/loader
tunables. Remove references to /dev/r???, they aren't used
any longer.
cd.9: Update the cd(9) man page to describe the CD_Q_10_BYTE_ONLY
quirk.
taskqueue.9: Update the taskqueue(9) man page to describe the new thread
task queue, and the taskqueue_swi_giant queue.
MFC after: 3 days
2003-09-03 04:46:28 +00:00
|
|
|
TASK_INIT(&softc->sysctl_task, 0, dasysctlinit, periph);
|
Fix ATAPI/USB/Firewire CDROM drive handling in cd(4) and hopefully fix
a number of related problems along the way.
- Automatically detect CDROM drives that can't handle 6 byte mode
sense and mode select, and adjust our command size accordingly.
We have to handle this in the cd(4) driver (where the buffers are
allocated), since the parameter list length is different for the
6 and 10 byte mode sense commands.
- Remove MODE_SENSE and MODE_SELECT translation removed in ATAPICAM
and in the umass(4) driver, since there's no way for that to work
properly.
- Add a quirk entry for CDROM drives that just hang when they get a 6
byte mode sense or mode select. The reason for the quirk must be
documented in a PR, and all quirks must be approved by
ken@FreeBSD.org. This is to make sure that we fully understand why
each quirk is needed. Once the CAM_NEW_TRAN_CODE is finished, we
should be able to remove any such quirks, since we'll know what
protocol the drive speaks (SCSI, ATAPI, etc.) and therefore whether
we should use 6 or 10 byte mode sense/select commands.
- Change the way the da(4) handles the no_6_byte sysctl. There is
now a per-drive sysctl to set the minimum command size for that
particular disk. (Since you could have multiple disks with
multiple requirements in one system.)
- Loader tunable support for all the sysctls in the da(4) and cd(4)
drivers.
- Add a CDIOCCLOSE ioctl for cd(4) (bde pointed this out a long
time ago).
- Add a media validation routine (cdcheckmedia()) to the cd(4)
driver, to fix some problems bde pointed out a long time ago. We
now allow open() to succeed no matter what, but if we don't detect
valid media, the user can only issue CDIOCCLOSE or CDIOCEJECT
ioctls.
- The media validation routine also reads the table of contents off
the drive. We use the table of contents to implement the
CDIOCPLAYTRACKS ioctl using the PLAY AUDIO MSF command. The
PLAY AUDIO TRACK INDEX command that we previously used was
deprecated after SCSI-2. It works in every SCSI CDROM I've tried,
but doesn't seem to work on ATAPI CDROM drives. We still use the
play audio track index command if we don't have a valid TOC, but
I suppose it'll fail anyway in that case.
- Add _len() versions of scsi_mode_sense() and scsi_mode_select() so
that we can specify the minimum command length.
- Fix a couple of formatting problems in the sense printing code.
MFC after: 4 weeks
2003-02-21 06:19:38 +00:00
|
|
|
|
1998-09-15 06:36:34 +00:00
|
|
|
/*
|
2007-04-15 08:49:19 +00:00
|
|
|
* Take an exclusive refcount on the periph while dastart is called
|
|
|
|
* to finish the probe. The reference will be dropped in dadone at
|
|
|
|
* the end of probe.
|
1998-09-15 06:36:34 +00:00
|
|
|
*/
|
2007-04-15 08:49:19 +00:00
|
|
|
(void)cam_periph_hold(periph, PRIBIO);
|
1998-09-15 06:36:34 +00:00
|
|
|
|
2007-04-15 08:49:19 +00:00
|
|
|
/*
|
|
|
|
* Schedule a periodic event to occasionally send an
|
|
|
|
* ordered tag to a device.
|
|
|
|
*/
|
Merge CAM locking changes from the projects/camlock branch to radically
reduce lock congestion and improve SMP scalability of the SCSI/ATA stack,
preparing the ground for the coming next GEOM direct dispatch support.
Replace big per-SIM locks with bunch of smaller ones:
- per-LUN locks to protect device and peripheral drivers state;
- per-target locks to protect list of LUNs on target;
- per-bus locks to protect reference counting;
- per-send queue locks to protect queue of CCBs to be sent;
- per-done queue locks to protect queue of completed CCBs;
- remaining per-SIM locks now protect only HBA driver internals.
While holding LUN lock it is allowed (while not recommended for performance
reasons) to take SIM lock. The opposite acquisition order is forbidden.
All the other locks are leaf locks, that can be taken anywhere, but should
not be cascaded. Many functions, such as: xpt_action(), xpt_done(),
xpt_async(), xpt_create_path(), etc. are no longer require (but allow) SIM
lock to be held.
To keep compatibility and solve cases where SIM lock can't be dropped, all
xpt_async() calls in addition to xpt_done() calls are queued to completion
threads for async processing in clean environment without SIM lock held.
Instead of single CAM SWI thread, used for commands completion processing
before, use multiple (depending on number of CPUs) threads. Load balanced
between them using "hash" of the device B:T:L address.
HBA drivers that can drop SIM lock during completion processing and have
sufficient number of completion threads to efficiently scale to multiple
CPUs can use new function xpt_done_direct() to avoid extra context switch.
Make ahci(4) driver to use this mechanism depending on hardware setup.
Sponsored by: iXsystems, Inc.
MFC after: 2 months
2013-10-21 12:00:26 +00:00
|
|
|
callout_init_mtx(&softc->sendordered_c, cam_periph_mtx(periph), 0);
|
2007-04-15 08:49:19 +00:00
|
|
|
callout_reset(&softc->sendordered_c,
|
2012-02-02 19:02:15 +00:00
|
|
|
(da_default_timeout * hz) / DA_ORDEREDTAG_INTERVAL,
|
2007-04-15 08:49:19 +00:00
|
|
|
dasendorderedtag, softc);
|
|
|
|
|
2013-04-04 19:07:37 +00:00
|
|
|
cam_periph_unlock(periph);
|
2011-04-16 06:54:41 +00:00
|
|
|
/*
|
|
|
|
* RBC devices don't have to support READ(6), only READ(10).
|
|
|
|
*/
|
|
|
|
if (softc->quirks & DA_Q_NO_6_BYTE || SID_TYPE(&cgd->inq_data) == T_RBC)
|
|
|
|
softc->minimum_cmd_size = 10;
|
|
|
|
else
|
|
|
|
softc->minimum_cmd_size = 6;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Load the user's default, if any.
|
|
|
|
*/
|
|
|
|
snprintf(tmpstr, sizeof(tmpstr), "kern.cam.da.%d.minimum_cmd_size",
|
|
|
|
periph->unit_number);
|
|
|
|
TUNABLE_INT_FETCH(tmpstr, &softc->minimum_cmd_size);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 6, 10, 12 and 16 are the currently permissible values.
|
|
|
|
*/
|
|
|
|
if (softc->minimum_cmd_size < 6)
|
|
|
|
softc->minimum_cmd_size = 6;
|
|
|
|
else if ((softc->minimum_cmd_size > 6)
|
|
|
|
&& (softc->minimum_cmd_size <= 10))
|
|
|
|
softc->minimum_cmd_size = 10;
|
|
|
|
else if ((softc->minimum_cmd_size > 10)
|
|
|
|
&& (softc->minimum_cmd_size <= 12))
|
|
|
|
softc->minimum_cmd_size = 12;
|
|
|
|
else if (softc->minimum_cmd_size > 12)
|
|
|
|
softc->minimum_cmd_size = 16;
|
|
|
|
|
2011-12-23 19:12:02 +00:00
|
|
|
/* Predict whether device may support READ CAPACITY(16). */
|
2013-07-30 13:00:09 +00:00
|
|
|
if (SID_ANSI_REV(&cgd->inq_data) >= SCSI_REV_SPC3 &&
|
|
|
|
(softc->quirks & DA_Q_NO_RC16) == 0) {
|
2011-12-23 19:12:02 +00:00
|
|
|
softc->flags |= DA_FLAG_CAN_RC16;
|
2013-04-26 16:17:04 +00:00
|
|
|
softc->state = DA_STATE_PROBE_RC16;
|
2011-12-23 19:12:02 +00:00
|
|
|
}
|
|
|
|
|
2011-04-16 08:38:11 +00:00
|
|
|
/*
|
|
|
|
* Register this media as a disk.
|
|
|
|
*/
|
2010-06-08 22:46:44 +00:00
|
|
|
softc->disk = disk_alloc();
|
2011-04-14 21:25:32 +00:00
|
|
|
softc->disk->d_devstat = devstat_new_entry(periph->periph_name,
|
|
|
|
periph->unit_number, 0,
|
|
|
|
DEVSTAT_BS_UNAVAILABLE,
|
|
|
|
SID_TYPE(&cgd->inq_data) |
|
|
|
|
XPORT_DEVSTAT_TYPE(cpi.transport),
|
|
|
|
DEVSTAT_PRIORITY_DISK);
|
2010-06-08 22:46:44 +00:00
|
|
|
softc->disk->d_open = daopen;
|
|
|
|
softc->disk->d_close = daclose;
|
|
|
|
softc->disk->d_strategy = dastrategy;
|
|
|
|
softc->disk->d_dump = dadump;
|
Plumb device physical path reporting from CAM devices, through GEOM and
DEVFS, and make it accessible via the diskinfo utility.
Extend GEOM's generic attribute query mechanism into generic disk consumers.
sys/geom/geom_disk.c:
sys/geom/geom_disk.h:
sys/cam/scsi/scsi_da.c:
sys/cam/ata/ata_da.c:
- Allow disk providers to implement a new method which can override
the default BIO_GETATTR response, d_getattr(struct bio *). This
function returns -1 if not handled, otherwise it returns 0 or an
errno to be passed to g_io_deliver().
sys/cam/scsi/scsi_da.c:
sys/cam/ata/ata_da.c:
- Don't copy the serial number to dp->d_ident anymore, as the CAM XPT
is now responsible for returning this information via
d_getattr()->(a)dagetattr()->xpt_getatr().
sys/geom/geom_dev.c:
- Implement a new ioctl, DIOCGPHYSPATH, which returns the GEOM
attribute "GEOM::physpath", if possible. If the attribute request
returns a zero-length string, ENOENT is returned.
usr.sbin/diskinfo/diskinfo.c:
- If the DIOCGPHYSPATH ioctl is successful, report physical path
data when diskinfo is executed with the '-v' option.
Submitted by: will
Reviewed by: gibbs
Sponsored by: Spectra Logic Corporation
Add generic attribute change notification support to GEOM.
sys/sys/geom/geom.h:
Add a new attrchanged method field to both g_class
and g_geom.
sys/sys/geom/geom.h:
sys/geom/geom_event.c:
- Provide the g_attr_changed() function that providers
can use to advertise attribute changes.
- Perform delivery of attribute change notifications
from a thread context via the standard GEOM event
mechanism.
sys/geom/geom_subr.c:
Inherit the attrchanged method from class to geom (class instance).
sys/geom/geom_disk.c:
Provide disk_attr_changed() to provide g_attr_changed() access
to consumers of the disk API.
sys/cam/scsi/scsi_pass.c:
sys/cam/scsi/scsi_da.c:
sys/geom/geom_dev.c:
sys/geom/geom_disk.c:
Use attribute changed events to track updates to physical path
information.
sys/cam/scsi/scsi_da.c:
Add AC_ADVINFO_CHANGED to the registered asynchronous CAM
events for this driver. When this event occurs, and
the updated buffer type references our physical path
attribute, emit a GEOM attribute changed event via the
disk_attr_changed() API.
sys/cam/scsi/scsi_pass.c:
Add AC_ADVINFO_CHANGED to the registered asynchronous CAM
events for this driver. When this event occurs, update
the physical patch devfs alias for this pass instance.
Submitted by: gibbs
Sponsored by: Spectra Logic Corporation
2011-06-14 17:10:32 +00:00
|
|
|
softc->disk->d_getattr = dagetattr;
|
Fix a bug which causes a panic in daopen(). The panic is caused by
a da(4) instance going away while GEOM is still probing it.
In this case, the GEOM disk class instance has been created by
disk_create(), and the taste of the disk is queued in the GEOM
event queue.
While that event is queued, the da(4) instance goes away. When the
open call comes into the da(4) driver, it dereferences the freed
(but non-NULL) peripheral pointer provided by GEOM, which results
in a panic.
The solution is to add a callback to the GEOM disk code that is
called when all of its resources are cleaned up. This is
implemented inside GEOM by adding an optional callback that is
called when all consumers have detached from a provider, and the
provider is about to be deleted.
scsi_cd.c,
scsi_da.c: In the register routine for the cd(4) and da(4)
routines, acquire a reference to the CAM peripheral
instance just before we call disk_create().
Use the new GEOM disk d_gone() callback to register
a callback (dadiskgonecb()/cddiskgonecb()) that
decrements the peripheral reference count once GEOM
has finished cleaning up its resources.
In the cd(4) driver, clean up open and close
behavior slightly. GEOM makes sure we only get one
open() and one close call, so there is no need to
set an open flag and decrement the reference count
if we are not the first open.
In the cd(4) driver, use cam_periph_release_locked()
in a couple of error scenarios to avoid extra mutex
calls.
geom.h: Add a new, optional, providergone callback that
is called when a provider is about to be deleted.
geom_disk.h: Add a new d_gone() callback to the GEOM disk
interface.
Bump the DISK_VERSION to version 2. This probably
should have been done after a couple of previous
changes, especially the addition of the d_getattr()
callback.
geom_disk.c: Add a providergone callback for the disk class,
g_disk_providergone(), that calls the user's
d_gone() callback if it exists.
Bump the DISK_VERSION to 2.
geom_subr.c: In g_destroy_provider(), call the providergone
callback if it has been provided.
In g_new_geomf(), propagate the class's
providergone callback to the new geom instance.
blkfront.c: Callers of disk_create() are supposed to pass in
DISK_VERSION, not an explicit disk API version
number. Update the blkfront driver to do that.
disk.9: Update the disk(9) man page to include information
on the new d_gone() callback, as well as the
previously added d_getattr() callback, d_descr
field, and HBA PCI ID fields.
MFC after: 5 days
2012-06-24 04:29:03 +00:00
|
|
|
softc->disk->d_gone = dadiskgonecb;
|
2010-06-08 22:46:44 +00:00
|
|
|
softc->disk->d_name = "da";
|
|
|
|
softc->disk->d_drv1 = periph;
|
|
|
|
if (cpi.maxio == 0)
|
2014-04-30 19:44:31 +00:00
|
|
|
softc->maxio = DFLTPHYS; /* traditional default */
|
2010-06-08 22:46:44 +00:00
|
|
|
else if (cpi.maxio > MAXPHYS)
|
2014-04-30 19:44:31 +00:00
|
|
|
softc->maxio = MAXPHYS; /* for safety */
|
2010-06-08 22:46:44 +00:00
|
|
|
else
|
2014-04-30 19:44:31 +00:00
|
|
|
softc->maxio = cpi.maxio;
|
|
|
|
softc->disk->d_maxsize = softc->maxio;
|
2010-06-08 22:46:44 +00:00
|
|
|
softc->disk->d_unit = periph->unit_number;
|
Merge GEOM direct dispatch changes from the projects/camlock branch.
When safety requirements are met, it allows to avoid passing I/O requests
to GEOM g_up/g_down thread, executing them directly in the caller context.
That allows to avoid CPU bottlenecks in g_up/g_down threads, plus avoid
several context switches per I/O.
The defined now safety requirements are:
- caller should not hold any locks and should be reenterable;
- callee should not depend on GEOM dual-threaded concurency semantics;
- on the way down, if request is unmapped while callee doesn't support it,
the context should be sleepable;
- kernel thread stack usage should be below 50%.
To keep compatibility with GEOM classes not meeting above requirements
new provider and consumer flags added:
- G_CF_DIRECT_SEND -- consumer code meets caller requirements (request);
- G_CF_DIRECT_RECEIVE -- consumer code meets callee requirements (done);
- G_PF_DIRECT_SEND -- provider code meets caller requirements (done);
- G_PF_DIRECT_RECEIVE -- provider code meets callee requirements (request).
Capable GEOM class can set them, allowing direct dispatch in cases where
it is safe. If any of requirements are not met, request is queued to
g_up or g_down thread same as before.
Such GEOM classes were reviewed and updated to support direct dispatch:
CONCAT, DEV, DISK, GATE, MD, MIRROR, MULTIPATH, NOP, PART, RAID, STRIPE,
VFS, ZERO, ZFS::VDEV, ZFS::ZVOL, all classes based on g_slice KPI (LABEL,
MAP, FLASHMAP, etc).
To declare direct completion capability disk(9) KPI got new flag equivalent
to G_PF_DIRECT_SEND -- DISKFLAG_DIRECT_COMPLETION. da(4) and ada(4) disk
drivers got it set now thanks to earlier CAM locking work.
This change more then twice increases peak block storage performance on
systems with manu CPUs, together with earlier CAM locking changes reaching
more then 1 million IOPS (512 byte raw reads from 16 SATA SSDs on 4 HBAs to
256 user-level threads).
Sponsored by: iXsystems, Inc.
MFC after: 2 months
2013-10-22 08:22:19 +00:00
|
|
|
softc->disk->d_flags = DISKFLAG_DIRECT_COMPLETION;
|
2010-06-08 22:46:44 +00:00
|
|
|
if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0)
|
|
|
|
softc->disk->d_flags |= DISKFLAG_CANFLUSHCACHE;
|
2013-03-19 15:01:50 +00:00
|
|
|
if ((cpi.hba_misc & PIM_UNMAPPED) != 0)
|
|
|
|
softc->disk->d_flags |= DISKFLAG_UNMAPPED_BIO;
|
2011-02-26 23:30:32 +00:00
|
|
|
cam_strvis(softc->disk->d_descr, cgd->inq_data.vendor,
|
|
|
|
sizeof(cgd->inq_data.vendor), sizeof(softc->disk->d_descr));
|
|
|
|
strlcat(softc->disk->d_descr, " ", sizeof(softc->disk->d_descr));
|
|
|
|
cam_strvis(&softc->disk->d_descr[strlen(softc->disk->d_descr)],
|
|
|
|
cgd->inq_data.product, sizeof(cgd->inq_data.product),
|
|
|
|
sizeof(softc->disk->d_descr) - strlen(softc->disk->d_descr));
|
2010-07-25 15:43:52 +00:00
|
|
|
softc->disk->d_hba_vendor = cpi.hba_vendor;
|
|
|
|
softc->disk->d_hba_device = cpi.hba_device;
|
|
|
|
softc->disk->d_hba_subvendor = cpi.hba_subvendor;
|
|
|
|
softc->disk->d_hba_subdevice = cpi.hba_subdevice;
|
Fix a bug which causes a panic in daopen(). The panic is caused by
a da(4) instance going away while GEOM is still probing it.
In this case, the GEOM disk class instance has been created by
disk_create(), and the taste of the disk is queued in the GEOM
event queue.
While that event is queued, the da(4) instance goes away. When the
open call comes into the da(4) driver, it dereferences the freed
(but non-NULL) peripheral pointer provided by GEOM, which results
in a panic.
The solution is to add a callback to the GEOM disk code that is
called when all of its resources are cleaned up. This is
implemented inside GEOM by adding an optional callback that is
called when all consumers have detached from a provider, and the
provider is about to be deleted.
scsi_cd.c,
scsi_da.c: In the register routine for the cd(4) and da(4)
routines, acquire a reference to the CAM peripheral
instance just before we call disk_create().
Use the new GEOM disk d_gone() callback to register
a callback (dadiskgonecb()/cddiskgonecb()) that
decrements the peripheral reference count once GEOM
has finished cleaning up its resources.
In the cd(4) driver, clean up open and close
behavior slightly. GEOM makes sure we only get one
open() and one close call, so there is no need to
set an open flag and decrement the reference count
if we are not the first open.
In the cd(4) driver, use cam_periph_release_locked()
in a couple of error scenarios to avoid extra mutex
calls.
geom.h: Add a new, optional, providergone callback that
is called when a provider is about to be deleted.
geom_disk.h: Add a new d_gone() callback to the GEOM disk
interface.
Bump the DISK_VERSION to version 2. This probably
should have been done after a couple of previous
changes, especially the addition of the d_getattr()
callback.
geom_disk.c: Add a providergone callback for the disk class,
g_disk_providergone(), that calls the user's
d_gone() callback if it exists.
Bump the DISK_VERSION to 2.
geom_subr.c: In g_destroy_provider(), call the providergone
callback if it has been provided.
In g_new_geomf(), propagate the class's
providergone callback to the new geom instance.
blkfront.c: Callers of disk_create() are supposed to pass in
DISK_VERSION, not an explicit disk API version
number. Update the blkfront driver to do that.
disk.9: Update the disk(9) man page to include information
on the new d_gone() callback, as well as the
previously added d_getattr() callback, d_descr
field, and HBA PCI ID fields.
MFC after: 5 days
2012-06-24 04:29:03 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Acquire a reference to the periph before we register with GEOM.
|
|
|
|
* We'll release this reference once GEOM calls us back (via
|
|
|
|
* dadiskgonecb()) telling us that our provider has been freed.
|
|
|
|
*/
|
|
|
|
if (cam_periph_acquire(periph) != CAM_REQ_CMP) {
|
|
|
|
xpt_print(periph->path, "%s: lost periph during "
|
|
|
|
"registration!\n", __func__);
|
2013-04-04 19:07:37 +00:00
|
|
|
cam_periph_lock(periph);
|
Fix a bug which causes a panic in daopen(). The panic is caused by
a da(4) instance going away while GEOM is still probing it.
In this case, the GEOM disk class instance has been created by
disk_create(), and the taste of the disk is queued in the GEOM
event queue.
While that event is queued, the da(4) instance goes away. When the
open call comes into the da(4) driver, it dereferences the freed
(but non-NULL) peripheral pointer provided by GEOM, which results
in a panic.
The solution is to add a callback to the GEOM disk code that is
called when all of its resources are cleaned up. This is
implemented inside GEOM by adding an optional callback that is
called when all consumers have detached from a provider, and the
provider is about to be deleted.
scsi_cd.c,
scsi_da.c: In the register routine for the cd(4) and da(4)
routines, acquire a reference to the CAM peripheral
instance just before we call disk_create().
Use the new GEOM disk d_gone() callback to register
a callback (dadiskgonecb()/cddiskgonecb()) that
decrements the peripheral reference count once GEOM
has finished cleaning up its resources.
In the cd(4) driver, clean up open and close
behavior slightly. GEOM makes sure we only get one
open() and one close call, so there is no need to
set an open flag and decrement the reference count
if we are not the first open.
In the cd(4) driver, use cam_periph_release_locked()
in a couple of error scenarios to avoid extra mutex
calls.
geom.h: Add a new, optional, providergone callback that
is called when a provider is about to be deleted.
geom_disk.h: Add a new d_gone() callback to the GEOM disk
interface.
Bump the DISK_VERSION to version 2. This probably
should have been done after a couple of previous
changes, especially the addition of the d_getattr()
callback.
geom_disk.c: Add a providergone callback for the disk class,
g_disk_providergone(), that calls the user's
d_gone() callback if it exists.
Bump the DISK_VERSION to 2.
geom_subr.c: In g_destroy_provider(), call the providergone
callback if it has been provided.
In g_new_geomf(), propagate the class's
providergone callback to the new geom instance.
blkfront.c: Callers of disk_create() are supposed to pass in
DISK_VERSION, not an explicit disk API version
number. Update the blkfront driver to do that.
disk.9: Update the disk(9) man page to include information
on the new d_gone() callback, as well as the
previously added d_getattr() callback, d_descr
field, and HBA PCI ID fields.
MFC after: 5 days
2012-06-24 04:29:03 +00:00
|
|
|
return (CAM_REQ_CMP_ERR);
|
|
|
|
}
|
|
|
|
|
2010-06-08 22:46:44 +00:00
|
|
|
disk_create(softc->disk, DISK_VERSION);
|
2013-04-04 19:07:37 +00:00
|
|
|
cam_periph_lock(periph);
|
2010-06-08 22:46:44 +00:00
|
|
|
|
Plumb device physical path reporting from CAM devices, through GEOM and
DEVFS, and make it accessible via the diskinfo utility.
Extend GEOM's generic attribute query mechanism into generic disk consumers.
sys/geom/geom_disk.c:
sys/geom/geom_disk.h:
sys/cam/scsi/scsi_da.c:
sys/cam/ata/ata_da.c:
- Allow disk providers to implement a new method which can override
the default BIO_GETATTR response, d_getattr(struct bio *). This
function returns -1 if not handled, otherwise it returns 0 or an
errno to be passed to g_io_deliver().
sys/cam/scsi/scsi_da.c:
sys/cam/ata/ata_da.c:
- Don't copy the serial number to dp->d_ident anymore, as the CAM XPT
is now responsible for returning this information via
d_getattr()->(a)dagetattr()->xpt_getatr().
sys/geom/geom_dev.c:
- Implement a new ioctl, DIOCGPHYSPATH, which returns the GEOM
attribute "GEOM::physpath", if possible. If the attribute request
returns a zero-length string, ENOENT is returned.
usr.sbin/diskinfo/diskinfo.c:
- If the DIOCGPHYSPATH ioctl is successful, report physical path
data when diskinfo is executed with the '-v' option.
Submitted by: will
Reviewed by: gibbs
Sponsored by: Spectra Logic Corporation
Add generic attribute change notification support to GEOM.
sys/sys/geom/geom.h:
Add a new attrchanged method field to both g_class
and g_geom.
sys/sys/geom/geom.h:
sys/geom/geom_event.c:
- Provide the g_attr_changed() function that providers
can use to advertise attribute changes.
- Perform delivery of attribute change notifications
from a thread context via the standard GEOM event
mechanism.
sys/geom/geom_subr.c:
Inherit the attrchanged method from class to geom (class instance).
sys/geom/geom_disk.c:
Provide disk_attr_changed() to provide g_attr_changed() access
to consumers of the disk API.
sys/cam/scsi/scsi_pass.c:
sys/cam/scsi/scsi_da.c:
sys/geom/geom_dev.c:
sys/geom/geom_disk.c:
Use attribute changed events to track updates to physical path
information.
sys/cam/scsi/scsi_da.c:
Add AC_ADVINFO_CHANGED to the registered asynchronous CAM
events for this driver. When this event occurs, and
the updated buffer type references our physical path
attribute, emit a GEOM attribute changed event via the
disk_attr_changed() API.
sys/cam/scsi/scsi_pass.c:
Add AC_ADVINFO_CHANGED to the registered asynchronous CAM
events for this driver. When this event occurs, update
the physical patch devfs alias for this pass instance.
Submitted by: gibbs
Sponsored by: Spectra Logic Corporation
2011-06-14 17:10:32 +00:00
|
|
|
/*
|
|
|
|
* Add async callbacks for events of interest.
|
|
|
|
* I don't bother checking if this fails as,
|
|
|
|
* in most cases, the system will function just
|
|
|
|
* fine without them and the only alternative
|
|
|
|
* would be to not attach the device on failure.
|
|
|
|
*/
|
2012-07-29 11:51:48 +00:00
|
|
|
xpt_register_async(AC_SENT_BDR | AC_BUS_RESET | AC_LOST_DEVICE |
|
|
|
|
AC_ADVINFO_CHANGED | AC_SCSI_AEN | AC_UNIT_ATTENTION,
|
|
|
|
daasync, periph, periph->path);
|
Plumb device physical path reporting from CAM devices, through GEOM and
DEVFS, and make it accessible via the diskinfo utility.
Extend GEOM's generic attribute query mechanism into generic disk consumers.
sys/geom/geom_disk.c:
sys/geom/geom_disk.h:
sys/cam/scsi/scsi_da.c:
sys/cam/ata/ata_da.c:
- Allow disk providers to implement a new method which can override
the default BIO_GETATTR response, d_getattr(struct bio *). This
function returns -1 if not handled, otherwise it returns 0 or an
errno to be passed to g_io_deliver().
sys/cam/scsi/scsi_da.c:
sys/cam/ata/ata_da.c:
- Don't copy the serial number to dp->d_ident anymore, as the CAM XPT
is now responsible for returning this information via
d_getattr()->(a)dagetattr()->xpt_getatr().
sys/geom/geom_dev.c:
- Implement a new ioctl, DIOCGPHYSPATH, which returns the GEOM
attribute "GEOM::physpath", if possible. If the attribute request
returns a zero-length string, ENOENT is returned.
usr.sbin/diskinfo/diskinfo.c:
- If the DIOCGPHYSPATH ioctl is successful, report physical path
data when diskinfo is executed with the '-v' option.
Submitted by: will
Reviewed by: gibbs
Sponsored by: Spectra Logic Corporation
Add generic attribute change notification support to GEOM.
sys/sys/geom/geom.h:
Add a new attrchanged method field to both g_class
and g_geom.
sys/sys/geom/geom.h:
sys/geom/geom_event.c:
- Provide the g_attr_changed() function that providers
can use to advertise attribute changes.
- Perform delivery of attribute change notifications
from a thread context via the standard GEOM event
mechanism.
sys/geom/geom_subr.c:
Inherit the attrchanged method from class to geom (class instance).
sys/geom/geom_disk.c:
Provide disk_attr_changed() to provide g_attr_changed() access
to consumers of the disk API.
sys/cam/scsi/scsi_pass.c:
sys/cam/scsi/scsi_da.c:
sys/geom/geom_dev.c:
sys/geom/geom_disk.c:
Use attribute changed events to track updates to physical path
information.
sys/cam/scsi/scsi_da.c:
Add AC_ADVINFO_CHANGED to the registered asynchronous CAM
events for this driver. When this event occurs, and
the updated buffer type references our physical path
attribute, emit a GEOM attribute changed event via the
disk_attr_changed() API.
sys/cam/scsi/scsi_pass.c:
Add AC_ADVINFO_CHANGED to the registered asynchronous CAM
events for this driver. When this event occurs, update
the physical patch devfs alias for this pass instance.
Submitted by: gibbs
Sponsored by: Spectra Logic Corporation
2011-06-14 17:10:32 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Emit an attribute changed notification just in case
|
|
|
|
* physical path information arrived before our async
|
|
|
|
* event handler was registered, but after anyone attaching
|
|
|
|
* to our disk device polled it.
|
|
|
|
*/
|
|
|
|
disk_attr_changed(softc->disk, "GEOM::physpath", M_NOWAIT);
|
|
|
|
|
2012-07-29 11:51:48 +00:00
|
|
|
/*
|
|
|
|
* Schedule a periodic media polling events.
|
|
|
|
*/
|
Merge CAM locking changes from the projects/camlock branch to radically
reduce lock congestion and improve SMP scalability of the SCSI/ATA stack,
preparing the ground for the coming next GEOM direct dispatch support.
Replace big per-SIM locks with bunch of smaller ones:
- per-LUN locks to protect device and peripheral drivers state;
- per-target locks to protect list of LUNs on target;
- per-bus locks to protect reference counting;
- per-send queue locks to protect queue of CCBs to be sent;
- per-done queue locks to protect queue of completed CCBs;
- remaining per-SIM locks now protect only HBA driver internals.
While holding LUN lock it is allowed (while not recommended for performance
reasons) to take SIM lock. The opposite acquisition order is forbidden.
All the other locks are leaf locks, that can be taken anywhere, but should
not be cascaded. Many functions, such as: xpt_action(), xpt_done(),
xpt_async(), xpt_create_path(), etc. are no longer require (but allow) SIM
lock to be held.
To keep compatibility and solve cases where SIM lock can't be dropped, all
xpt_async() calls in addition to xpt_done() calls are queued to completion
threads for async processing in clean environment without SIM lock held.
Instead of single CAM SWI thread, used for commands completion processing
before, use multiple (depending on number of CPUs) threads. Load balanced
between them using "hash" of the device B:T:L address.
HBA drivers that can drop SIM lock during completion processing and have
sufficient number of completion threads to efficiently scale to multiple
CPUs can use new function xpt_done_direct() to avoid extra context switch.
Make ahci(4) driver to use this mechanism depending on hardware setup.
Sponsored by: iXsystems, Inc.
MFC after: 2 months
2013-10-21 12:00:26 +00:00
|
|
|
callout_init_mtx(&softc->mediapoll_c, cam_periph_mtx(periph), 0);
|
2012-07-29 11:51:48 +00:00
|
|
|
if ((softc->flags & DA_FLAG_PACK_REMOVABLE) &&
|
|
|
|
(cgd->inq_flags & SID_AEN) == 0 &&
|
|
|
|
da_poll_period != 0)
|
|
|
|
callout_reset(&softc->mediapoll_c, da_poll_period * hz,
|
|
|
|
damediapoll, periph);
|
|
|
|
|
2010-06-08 22:46:44 +00:00
|
|
|
xpt_schedule(periph, CAM_PRIORITY_DEV);
|
|
|
|
|
1998-09-15 06:36:34 +00:00
|
|
|
return(CAM_REQ_CMP);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
dastart(struct cam_periph *periph, union ccb *start_ccb)
|
|
|
|
{
|
|
|
|
struct da_softc *softc;
|
|
|
|
|
|
|
|
softc = (struct da_softc *)periph->softc;
|
|
|
|
|
2012-06-05 09:45:42 +00:00
|
|
|
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("dastart\n"));
|
|
|
|
|
2013-04-26 16:17:04 +00:00
|
|
|
skipstate:
|
1998-09-15 06:36:34 +00:00
|
|
|
switch (softc->state) {
|
|
|
|
case DA_STATE_NORMAL:
|
|
|
|
{
|
2013-07-12 00:50:25 +00:00
|
|
|
struct bio *bp;
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
uint8_t tag_code;
|
1998-09-15 06:36:34 +00:00
|
|
|
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
/* Run BIO_DELETE if not running yet. */
|
|
|
|
if (!softc->delete_running &&
|
|
|
|
(bp = bioq_first(&softc->delete_queue)) != NULL) {
|
2013-07-12 00:50:25 +00:00
|
|
|
if (softc->delete_func != NULL) {
|
|
|
|
softc->delete_func(periph, start_ccb, bp);
|
2013-04-26 16:17:04 +00:00
|
|
|
goto out;
|
2013-07-12 00:50:25 +00:00
|
|
|
} else {
|
|
|
|
bioq_flush(&softc->delete_queue, NULL, 0);
|
|
|
|
/* FALLTHROUGH */
|
|
|
|
}
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
}
|
1998-09-15 06:36:34 +00:00
|
|
|
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
/* Run regular command. */
|
|
|
|
bp = bioq_takefirst(&softc->bio_queue);
|
|
|
|
if (bp == NULL) {
|
2012-07-29 11:51:48 +00:00
|
|
|
if (softc->tur) {
|
|
|
|
softc->tur = 0;
|
|
|
|
scsi_test_unit_ready(&start_ccb->csio,
|
|
|
|
/*retries*/ da_retry_count,
|
|
|
|
dadone,
|
|
|
|
MSG_SIMPLE_Q_TAG,
|
|
|
|
SSD_FULL_SIZE,
|
|
|
|
da_default_timeout * 1000);
|
|
|
|
start_ccb->ccb_h.ccb_bp = NULL;
|
|
|
|
start_ccb->ccb_h.ccb_state = DA_CCB_TUR;
|
|
|
|
xpt_action(start_ccb);
|
|
|
|
} else
|
|
|
|
xpt_release_ccb(start_ccb);
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
break;
|
|
|
|
}
|
2012-07-29 11:51:48 +00:00
|
|
|
if (softc->tur) {
|
|
|
|
softc->tur = 0;
|
|
|
|
cam_periph_release_locked(periph);
|
|
|
|
}
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
|
|
|
|
if ((bp->bio_flags & BIO_ORDERED) != 0 ||
|
|
|
|
(softc->flags & DA_FLAG_NEED_OTAG) != 0) {
|
|
|
|
softc->flags &= ~DA_FLAG_NEED_OTAG;
|
2013-10-24 14:05:44 +00:00
|
|
|
softc->flags |= DA_FLAG_WAS_OTAG;
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
tag_code = MSG_ORDERED_Q_TAG;
|
|
|
|
} else {
|
|
|
|
tag_code = MSG_SIMPLE_Q_TAG;
|
|
|
|
}
|
1998-09-15 06:36:34 +00:00
|
|
|
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
switch (bp->bio_cmd) {
|
|
|
|
case BIO_WRITE:
|
2013-07-27 22:44:55 +00:00
|
|
|
case BIO_READ:
|
Add asynchronous command support to the pass(4) driver, and the new
camdd(8) utility.
CCBs may be queued to the driver via the new CAMIOQUEUE ioctl, and
completed CCBs may be retrieved via the CAMIOGET ioctl. User
processes can use poll(2) or kevent(2) to get notification when
I/O has completed.
While the existing CAMIOCOMMAND blocking ioctl interface only
supports user virtual data pointers in a CCB (generally only
one per CCB), the new CAMIOQUEUE ioctl supports user virtual and
physical address pointers, as well as user virtual and physical
scatter/gather lists. This allows user applications to have more
flexibility in their data handling operations.
Kernel memory for data transferred via the queued interface is
allocated from the zone allocator in MAXPHYS sized chunks, and user
data is copied in and out. This is likely faster than the
vmapbuf()/vunmapbuf() method used by the CAMIOCOMMAND ioctl in
configurations with many processors (there are more TLB shootdowns
caused by the mapping/unmapping operation) but may not be as fast
as running with unmapped I/O.
The new memory handling model for user requests also allows
applications to send CCBs with request sizes that are larger than
MAXPHYS. The pass(4) driver now limits queued requests to the I/O
size listed by the SIM driver in the maxio field in the Path
Inquiry (XPT_PATH_INQ) CCB.
There are some things things would be good to add:
1. Come up with a way to do unmapped I/O on multiple buffers.
Currently the unmapped I/O interface operates on a struct bio,
which includes only one address and length. It would be nice
to be able to send an unmapped scatter/gather list down to
busdma. This would allow eliminating the copy we currently do
for data.
2. Add an ioctl to list currently outstanding CCBs in the various
queues.
3. Add an ioctl to cancel a request, or use the XPT_ABORT CCB to do
that.
4. Test physical address support. Virtual pointers and scatter
gather lists have been tested, but I have not yet tested
physical addresses or scatter/gather lists.
5. Investigate multiple queue support. At the moment there is one
queue of commands per pass(4) device. If multiple processes
open the device, they will submit I/O into the same queue and
get events for the same completions. This is probably the right
model for most applications, but it is something that could be
changed later on.
Also, add a new utility, camdd(8) that uses the asynchronous pass(4)
driver interface.
This utility is intended to be a basic data transfer/copy utility,
a simple benchmark utility, and an example of how to use the
asynchronous pass(4) interface.
It can copy data to and from pass(4) devices using any target queue
depth, starting offset and blocksize for the input and ouptut devices.
It currently only supports SCSI devices, but could be easily extended
to support ATA devices.
It can also copy data to and from regular files, block devices, tape
devices, pipes, stdin, and stdout. It does not support queueing
multiple commands to any of those targets, since it uses the standard
read(2)/write(2)/writev(2)/readv(2) system calls.
The I/O is done by two threads, one for the reader and one for the
writer. The reader thread sends completed read requests to the
writer thread in strictly sequential order, even if they complete
out of order. That could be modified later on for random I/O patterns
or slightly out of order I/O.
camdd(8) uses kqueue(2)/kevent(2) to get I/O completion events from
the pass(4) driver and also to send request notifications internally.
For pass(4) devcies, camdd(8) uses a single buffer (CAM_DATA_VADDR)
per CAM CCB on the reading side, and a scatter/gather list
(CAM_DATA_SG) on the writing side. In addition to testing both
interfaces, this makes any potential reblocking of I/O easier. No
data is copied between the reader and the writer, but rather the
reader's buffers are split into multiple I/O requests or combined
into a single I/O request depending on the input and output blocksize.
For the file I/O path, camdd(8) also uses a single buffer (read(2),
write(2), pread(2) or pwrite(2)) on reads, and a scatter/gather list
(readv(2), writev(2), preadv(2), pwritev(2)) on writes.
Things that would be nice to do for camdd(8) eventually:
1. Add support for I/O pattern generation. Patterns like all
zeros, all ones, LBA-based patterns, random patterns, etc. Right
Now you can always use /dev/zero, /dev/random, etc.
2. Add support for a "sink" mode, so we do only reads with no
writes. Right now, you can use /dev/null.
3. Add support for automatic queue depth probing, so that we can
figure out the right queue depth on the input and output side
for maximum throughput. At the moment it defaults to 6.
4. Add support for SATA device passthrough I/O.
5. Add support for random LBAs and/or lengths on the input and
output sides.
6. Track average per-I/O latency and busy time. The busy time
and latency could also feed in to the automatic queue depth
determination.
sys/cam/scsi/scsi_pass.h:
Define two new ioctls, CAMIOQUEUE and CAMIOGET, that queue
and fetch asynchronous CAM CCBs respectively.
Although these ioctls do not have a declared argument, they
both take a union ccb pointer. If we declare a size here,
the ioctl code in sys/kern/sys_generic.c will malloc and free
a buffer for either the CCB or the CCB pointer (depending on
how it is declared). Since we have to keep a copy of the
CCB (which is fairly large) anyway, having the ioctl malloc
and free a CCB for each call is wasteful.
sys/cam/scsi/scsi_pass.c:
Add asynchronous CCB support.
Add two new ioctls, CAMIOQUEUE and CAMIOGET.
CAMIOQUEUE adds a CCB to the incoming queue. The CCB is
executed immediately (and moved to the active queue) if it
is an immediate CCB, but otherwise it will be executed
in passstart() when a CCB is available from the transport layer.
When CCBs are completed (because they are immediate or
passdone() if they are queued), they are put on the done
queue.
If we get the final close on the device before all pending
I/O is complete, all active I/O is moved to the abandoned
queue and we increment the peripheral reference count so
that the peripheral driver instance doesn't go away before
all pending I/O is done.
The new passcreatezone() function is called on the first
call to the CAMIOQUEUE ioctl on a given device to allocate
the UMA zones for I/O requests and S/G list buffers. This
may be good to move off to a taskqueue at some point.
The new passmemsetup() function allocates memory and
scatter/gather lists to hold the user's data, and copies
in any data that needs to be written. For virtual pointers
(CAM_DATA_VADDR), the kernel buffer is malloced from the
new pass(4) driver malloc bucket. For virtual
scatter/gather lists (CAM_DATA_SG), buffers are allocated
from a new per-pass(9) UMA zone in MAXPHYS-sized chunks.
Physical pointers are passed in unchanged. We have support
for up to 16 scatter/gather segments (for the user and
kernel S/G lists) in the default struct pass_io_req, so
requests with longer S/G lists require an extra kernel malloc.
The new passcopysglist() function copies a user scatter/gather
list to a kernel scatter/gather list. The number of elements
in each list may be different, but (obviously) the amount of data
stored has to be identical.
The new passmemdone() function copies data out for the
CAM_DATA_VADDR and CAM_DATA_SG cases.
The new passiocleanup() function restores data pointers in
user CCBs and frees memory.
Add new functions to support kqueue(2)/kevent(2):
passreadfilt() tells kevent whether or not the done
queue is empty.
passkqfilter() adds a knote to our list.
passreadfiltdetach() removes a knote from our list.
Add a new function, passpoll(), for poll(2)/select(2)
to use.
Add devstat(9) support for the queued CCB path.
sys/cam/ata/ata_da.c:
Add support for the BIO_VLIST bio type.
sys/cam/cam_ccb.h:
Add a new enumeration for the xflags field in the CCB header.
(This doesn't change the CCB header, just adds an enumeration to
use.)
sys/cam/cam_xpt.c:
Add a new function, xpt_setup_ccb_flags(), that allows specifying
CCB flags.
sys/cam/cam_xpt.h:
Add a prototype for xpt_setup_ccb_flags().
sys/cam/scsi/scsi_da.c:
Add support for BIO_VLIST.
sys/dev/md/md.c:
Add BIO_VLIST support to md(4).
sys/geom/geom_disk.c:
Add BIO_VLIST support to the GEOM disk class. Re-factor the I/O size
limiting code in g_disk_start() a bit.
sys/kern/subr_bus_dma.c:
Change _bus_dmamap_load_vlist() to take a starting offset and
length.
Add a new function, _bus_dmamap_load_pages(), that will load a list
of physical pages starting at an offset.
Update _bus_dmamap_load_bio() to allow loading BIO_VLIST bios.
Allow unmapped I/O to start at an offset.
sys/kern/subr_uio.c:
Add two new functions, physcopyin_vlist() and physcopyout_vlist().
sys/pc98/include/bus.h:
Guard kernel-only parts of the pc98 machine/bus.h header with
#ifdef _KERNEL.
This allows userland programs to include <machine/bus.h> to get the
definition of bus_addr_t and bus_size_t.
sys/sys/bio.h:
Add a new bio flag, BIO_VLIST.
sys/sys/uio.h:
Add prototypes for physcopyin_vlist() and physcopyout_vlist().
share/man/man4/pass.4:
Document the CAMIOQUEUE and CAMIOGET ioctls.
usr.sbin/Makefile:
Add camdd.
usr.sbin/camdd/Makefile:
Add a makefile for camdd(8).
usr.sbin/camdd/camdd.8:
Man page for camdd(8).
usr.sbin/camdd/camdd.c:
The new camdd(8) utility.
Sponsored by: Spectra Logic
MFC after: 1 week
2015-12-03 20:54:55 +00:00
|
|
|
{
|
|
|
|
void *data_ptr;
|
|
|
|
int rw_op;
|
|
|
|
|
|
|
|
if (bp->bio_cmd == BIO_WRITE) {
|
|
|
|
softc->flags |= DA_FLAG_DIRTY;
|
|
|
|
rw_op = SCSI_RW_WRITE;
|
|
|
|
} else {
|
|
|
|
rw_op = SCSI_RW_READ;
|
|
|
|
}
|
|
|
|
|
|
|
|
data_ptr = bp->bio_data;
|
|
|
|
if ((bp->bio_flags & (BIO_UNMAPPED|BIO_VLIST)) != 0) {
|
|
|
|
rw_op |= SCSI_RW_BIO;
|
|
|
|
data_ptr = bp;
|
|
|
|
}
|
|
|
|
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
scsi_read_write(&start_ccb->csio,
|
|
|
|
/*retries*/da_retry_count,
|
|
|
|
/*cbfcnp*/dadone,
|
|
|
|
/*tag_action*/tag_code,
|
Add asynchronous command support to the pass(4) driver, and the new
camdd(8) utility.
CCBs may be queued to the driver via the new CAMIOQUEUE ioctl, and
completed CCBs may be retrieved via the CAMIOGET ioctl. User
processes can use poll(2) or kevent(2) to get notification when
I/O has completed.
While the existing CAMIOCOMMAND blocking ioctl interface only
supports user virtual data pointers in a CCB (generally only
one per CCB), the new CAMIOQUEUE ioctl supports user virtual and
physical address pointers, as well as user virtual and physical
scatter/gather lists. This allows user applications to have more
flexibility in their data handling operations.
Kernel memory for data transferred via the queued interface is
allocated from the zone allocator in MAXPHYS sized chunks, and user
data is copied in and out. This is likely faster than the
vmapbuf()/vunmapbuf() method used by the CAMIOCOMMAND ioctl in
configurations with many processors (there are more TLB shootdowns
caused by the mapping/unmapping operation) but may not be as fast
as running with unmapped I/O.
The new memory handling model for user requests also allows
applications to send CCBs with request sizes that are larger than
MAXPHYS. The pass(4) driver now limits queued requests to the I/O
size listed by the SIM driver in the maxio field in the Path
Inquiry (XPT_PATH_INQ) CCB.
There are some things things would be good to add:
1. Come up with a way to do unmapped I/O on multiple buffers.
Currently the unmapped I/O interface operates on a struct bio,
which includes only one address and length. It would be nice
to be able to send an unmapped scatter/gather list down to
busdma. This would allow eliminating the copy we currently do
for data.
2. Add an ioctl to list currently outstanding CCBs in the various
queues.
3. Add an ioctl to cancel a request, or use the XPT_ABORT CCB to do
that.
4. Test physical address support. Virtual pointers and scatter
gather lists have been tested, but I have not yet tested
physical addresses or scatter/gather lists.
5. Investigate multiple queue support. At the moment there is one
queue of commands per pass(4) device. If multiple processes
open the device, they will submit I/O into the same queue and
get events for the same completions. This is probably the right
model for most applications, but it is something that could be
changed later on.
Also, add a new utility, camdd(8) that uses the asynchronous pass(4)
driver interface.
This utility is intended to be a basic data transfer/copy utility,
a simple benchmark utility, and an example of how to use the
asynchronous pass(4) interface.
It can copy data to and from pass(4) devices using any target queue
depth, starting offset and blocksize for the input and ouptut devices.
It currently only supports SCSI devices, but could be easily extended
to support ATA devices.
It can also copy data to and from regular files, block devices, tape
devices, pipes, stdin, and stdout. It does not support queueing
multiple commands to any of those targets, since it uses the standard
read(2)/write(2)/writev(2)/readv(2) system calls.
The I/O is done by two threads, one for the reader and one for the
writer. The reader thread sends completed read requests to the
writer thread in strictly sequential order, even if they complete
out of order. That could be modified later on for random I/O patterns
or slightly out of order I/O.
camdd(8) uses kqueue(2)/kevent(2) to get I/O completion events from
the pass(4) driver and also to send request notifications internally.
For pass(4) devcies, camdd(8) uses a single buffer (CAM_DATA_VADDR)
per CAM CCB on the reading side, and a scatter/gather list
(CAM_DATA_SG) on the writing side. In addition to testing both
interfaces, this makes any potential reblocking of I/O easier. No
data is copied between the reader and the writer, but rather the
reader's buffers are split into multiple I/O requests or combined
into a single I/O request depending on the input and output blocksize.
For the file I/O path, camdd(8) also uses a single buffer (read(2),
write(2), pread(2) or pwrite(2)) on reads, and a scatter/gather list
(readv(2), writev(2), preadv(2), pwritev(2)) on writes.
Things that would be nice to do for camdd(8) eventually:
1. Add support for I/O pattern generation. Patterns like all
zeros, all ones, LBA-based patterns, random patterns, etc. Right
Now you can always use /dev/zero, /dev/random, etc.
2. Add support for a "sink" mode, so we do only reads with no
writes. Right now, you can use /dev/null.
3. Add support for automatic queue depth probing, so that we can
figure out the right queue depth on the input and output side
for maximum throughput. At the moment it defaults to 6.
4. Add support for SATA device passthrough I/O.
5. Add support for random LBAs and/or lengths on the input and
output sides.
6. Track average per-I/O latency and busy time. The busy time
and latency could also feed in to the automatic queue depth
determination.
sys/cam/scsi/scsi_pass.h:
Define two new ioctls, CAMIOQUEUE and CAMIOGET, that queue
and fetch asynchronous CAM CCBs respectively.
Although these ioctls do not have a declared argument, they
both take a union ccb pointer. If we declare a size here,
the ioctl code in sys/kern/sys_generic.c will malloc and free
a buffer for either the CCB or the CCB pointer (depending on
how it is declared). Since we have to keep a copy of the
CCB (which is fairly large) anyway, having the ioctl malloc
and free a CCB for each call is wasteful.
sys/cam/scsi/scsi_pass.c:
Add asynchronous CCB support.
Add two new ioctls, CAMIOQUEUE and CAMIOGET.
CAMIOQUEUE adds a CCB to the incoming queue. The CCB is
executed immediately (and moved to the active queue) if it
is an immediate CCB, but otherwise it will be executed
in passstart() when a CCB is available from the transport layer.
When CCBs are completed (because they are immediate or
passdone() if they are queued), they are put on the done
queue.
If we get the final close on the device before all pending
I/O is complete, all active I/O is moved to the abandoned
queue and we increment the peripheral reference count so
that the peripheral driver instance doesn't go away before
all pending I/O is done.
The new passcreatezone() function is called on the first
call to the CAMIOQUEUE ioctl on a given device to allocate
the UMA zones for I/O requests and S/G list buffers. This
may be good to move off to a taskqueue at some point.
The new passmemsetup() function allocates memory and
scatter/gather lists to hold the user's data, and copies
in any data that needs to be written. For virtual pointers
(CAM_DATA_VADDR), the kernel buffer is malloced from the
new pass(4) driver malloc bucket. For virtual
scatter/gather lists (CAM_DATA_SG), buffers are allocated
from a new per-pass(9) UMA zone in MAXPHYS-sized chunks.
Physical pointers are passed in unchanged. We have support
for up to 16 scatter/gather segments (for the user and
kernel S/G lists) in the default struct pass_io_req, so
requests with longer S/G lists require an extra kernel malloc.
The new passcopysglist() function copies a user scatter/gather
list to a kernel scatter/gather list. The number of elements
in each list may be different, but (obviously) the amount of data
stored has to be identical.
The new passmemdone() function copies data out for the
CAM_DATA_VADDR and CAM_DATA_SG cases.
The new passiocleanup() function restores data pointers in
user CCBs and frees memory.
Add new functions to support kqueue(2)/kevent(2):
passreadfilt() tells kevent whether or not the done
queue is empty.
passkqfilter() adds a knote to our list.
passreadfiltdetach() removes a knote from our list.
Add a new function, passpoll(), for poll(2)/select(2)
to use.
Add devstat(9) support for the queued CCB path.
sys/cam/ata/ata_da.c:
Add support for the BIO_VLIST bio type.
sys/cam/cam_ccb.h:
Add a new enumeration for the xflags field in the CCB header.
(This doesn't change the CCB header, just adds an enumeration to
use.)
sys/cam/cam_xpt.c:
Add a new function, xpt_setup_ccb_flags(), that allows specifying
CCB flags.
sys/cam/cam_xpt.h:
Add a prototype for xpt_setup_ccb_flags().
sys/cam/scsi/scsi_da.c:
Add support for BIO_VLIST.
sys/dev/md/md.c:
Add BIO_VLIST support to md(4).
sys/geom/geom_disk.c:
Add BIO_VLIST support to the GEOM disk class. Re-factor the I/O size
limiting code in g_disk_start() a bit.
sys/kern/subr_bus_dma.c:
Change _bus_dmamap_load_vlist() to take a starting offset and
length.
Add a new function, _bus_dmamap_load_pages(), that will load a list
of physical pages starting at an offset.
Update _bus_dmamap_load_bio() to allow loading BIO_VLIST bios.
Allow unmapped I/O to start at an offset.
sys/kern/subr_uio.c:
Add two new functions, physcopyin_vlist() and physcopyout_vlist().
sys/pc98/include/bus.h:
Guard kernel-only parts of the pc98 machine/bus.h header with
#ifdef _KERNEL.
This allows userland programs to include <machine/bus.h> to get the
definition of bus_addr_t and bus_size_t.
sys/sys/bio.h:
Add a new bio flag, BIO_VLIST.
sys/sys/uio.h:
Add prototypes for physcopyin_vlist() and physcopyout_vlist().
share/man/man4/pass.4:
Document the CAMIOQUEUE and CAMIOGET ioctls.
usr.sbin/Makefile:
Add camdd.
usr.sbin/camdd/Makefile:
Add a makefile for camdd(8).
usr.sbin/camdd/camdd.8:
Man page for camdd(8).
usr.sbin/camdd/camdd.c:
The new camdd(8) utility.
Sponsored by: Spectra Logic
MFC after: 1 week
2015-12-03 20:54:55 +00:00
|
|
|
rw_op,
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
/*byte2*/0,
|
|
|
|
softc->minimum_cmd_size,
|
|
|
|
/*lba*/bp->bio_pblkno,
|
|
|
|
/*block_count*/bp->bio_bcount /
|
|
|
|
softc->params.secsize,
|
Add asynchronous command support to the pass(4) driver, and the new
camdd(8) utility.
CCBs may be queued to the driver via the new CAMIOQUEUE ioctl, and
completed CCBs may be retrieved via the CAMIOGET ioctl. User
processes can use poll(2) or kevent(2) to get notification when
I/O has completed.
While the existing CAMIOCOMMAND blocking ioctl interface only
supports user virtual data pointers in a CCB (generally only
one per CCB), the new CAMIOQUEUE ioctl supports user virtual and
physical address pointers, as well as user virtual and physical
scatter/gather lists. This allows user applications to have more
flexibility in their data handling operations.
Kernel memory for data transferred via the queued interface is
allocated from the zone allocator in MAXPHYS sized chunks, and user
data is copied in and out. This is likely faster than the
vmapbuf()/vunmapbuf() method used by the CAMIOCOMMAND ioctl in
configurations with many processors (there are more TLB shootdowns
caused by the mapping/unmapping operation) but may not be as fast
as running with unmapped I/O.
The new memory handling model for user requests also allows
applications to send CCBs with request sizes that are larger than
MAXPHYS. The pass(4) driver now limits queued requests to the I/O
size listed by the SIM driver in the maxio field in the Path
Inquiry (XPT_PATH_INQ) CCB.
There are some things things would be good to add:
1. Come up with a way to do unmapped I/O on multiple buffers.
Currently the unmapped I/O interface operates on a struct bio,
which includes only one address and length. It would be nice
to be able to send an unmapped scatter/gather list down to
busdma. This would allow eliminating the copy we currently do
for data.
2. Add an ioctl to list currently outstanding CCBs in the various
queues.
3. Add an ioctl to cancel a request, or use the XPT_ABORT CCB to do
that.
4. Test physical address support. Virtual pointers and scatter
gather lists have been tested, but I have not yet tested
physical addresses or scatter/gather lists.
5. Investigate multiple queue support. At the moment there is one
queue of commands per pass(4) device. If multiple processes
open the device, they will submit I/O into the same queue and
get events for the same completions. This is probably the right
model for most applications, but it is something that could be
changed later on.
Also, add a new utility, camdd(8) that uses the asynchronous pass(4)
driver interface.
This utility is intended to be a basic data transfer/copy utility,
a simple benchmark utility, and an example of how to use the
asynchronous pass(4) interface.
It can copy data to and from pass(4) devices using any target queue
depth, starting offset and blocksize for the input and ouptut devices.
It currently only supports SCSI devices, but could be easily extended
to support ATA devices.
It can also copy data to and from regular files, block devices, tape
devices, pipes, stdin, and stdout. It does not support queueing
multiple commands to any of those targets, since it uses the standard
read(2)/write(2)/writev(2)/readv(2) system calls.
The I/O is done by two threads, one for the reader and one for the
writer. The reader thread sends completed read requests to the
writer thread in strictly sequential order, even if they complete
out of order. That could be modified later on for random I/O patterns
or slightly out of order I/O.
camdd(8) uses kqueue(2)/kevent(2) to get I/O completion events from
the pass(4) driver and also to send request notifications internally.
For pass(4) devcies, camdd(8) uses a single buffer (CAM_DATA_VADDR)
per CAM CCB on the reading side, and a scatter/gather list
(CAM_DATA_SG) on the writing side. In addition to testing both
interfaces, this makes any potential reblocking of I/O easier. No
data is copied between the reader and the writer, but rather the
reader's buffers are split into multiple I/O requests or combined
into a single I/O request depending on the input and output blocksize.
For the file I/O path, camdd(8) also uses a single buffer (read(2),
write(2), pread(2) or pwrite(2)) on reads, and a scatter/gather list
(readv(2), writev(2), preadv(2), pwritev(2)) on writes.
Things that would be nice to do for camdd(8) eventually:
1. Add support for I/O pattern generation. Patterns like all
zeros, all ones, LBA-based patterns, random patterns, etc. Right
Now you can always use /dev/zero, /dev/random, etc.
2. Add support for a "sink" mode, so we do only reads with no
writes. Right now, you can use /dev/null.
3. Add support for automatic queue depth probing, so that we can
figure out the right queue depth on the input and output side
for maximum throughput. At the moment it defaults to 6.
4. Add support for SATA device passthrough I/O.
5. Add support for random LBAs and/or lengths on the input and
output sides.
6. Track average per-I/O latency and busy time. The busy time
and latency could also feed in to the automatic queue depth
determination.
sys/cam/scsi/scsi_pass.h:
Define two new ioctls, CAMIOQUEUE and CAMIOGET, that queue
and fetch asynchronous CAM CCBs respectively.
Although these ioctls do not have a declared argument, they
both take a union ccb pointer. If we declare a size here,
the ioctl code in sys/kern/sys_generic.c will malloc and free
a buffer for either the CCB or the CCB pointer (depending on
how it is declared). Since we have to keep a copy of the
CCB (which is fairly large) anyway, having the ioctl malloc
and free a CCB for each call is wasteful.
sys/cam/scsi/scsi_pass.c:
Add asynchronous CCB support.
Add two new ioctls, CAMIOQUEUE and CAMIOGET.
CAMIOQUEUE adds a CCB to the incoming queue. The CCB is
executed immediately (and moved to the active queue) if it
is an immediate CCB, but otherwise it will be executed
in passstart() when a CCB is available from the transport layer.
When CCBs are completed (because they are immediate or
passdone() if they are queued), they are put on the done
queue.
If we get the final close on the device before all pending
I/O is complete, all active I/O is moved to the abandoned
queue and we increment the peripheral reference count so
that the peripheral driver instance doesn't go away before
all pending I/O is done.
The new passcreatezone() function is called on the first
call to the CAMIOQUEUE ioctl on a given device to allocate
the UMA zones for I/O requests and S/G list buffers. This
may be good to move off to a taskqueue at some point.
The new passmemsetup() function allocates memory and
scatter/gather lists to hold the user's data, and copies
in any data that needs to be written. For virtual pointers
(CAM_DATA_VADDR), the kernel buffer is malloced from the
new pass(4) driver malloc bucket. For virtual
scatter/gather lists (CAM_DATA_SG), buffers are allocated
from a new per-pass(9) UMA zone in MAXPHYS-sized chunks.
Physical pointers are passed in unchanged. We have support
for up to 16 scatter/gather segments (for the user and
kernel S/G lists) in the default struct pass_io_req, so
requests with longer S/G lists require an extra kernel malloc.
The new passcopysglist() function copies a user scatter/gather
list to a kernel scatter/gather list. The number of elements
in each list may be different, but (obviously) the amount of data
stored has to be identical.
The new passmemdone() function copies data out for the
CAM_DATA_VADDR and CAM_DATA_SG cases.
The new passiocleanup() function restores data pointers in
user CCBs and frees memory.
Add new functions to support kqueue(2)/kevent(2):
passreadfilt() tells kevent whether or not the done
queue is empty.
passkqfilter() adds a knote to our list.
passreadfiltdetach() removes a knote from our list.
Add a new function, passpoll(), for poll(2)/select(2)
to use.
Add devstat(9) support for the queued CCB path.
sys/cam/ata/ata_da.c:
Add support for the BIO_VLIST bio type.
sys/cam/cam_ccb.h:
Add a new enumeration for the xflags field in the CCB header.
(This doesn't change the CCB header, just adds an enumeration to
use.)
sys/cam/cam_xpt.c:
Add a new function, xpt_setup_ccb_flags(), that allows specifying
CCB flags.
sys/cam/cam_xpt.h:
Add a prototype for xpt_setup_ccb_flags().
sys/cam/scsi/scsi_da.c:
Add support for BIO_VLIST.
sys/dev/md/md.c:
Add BIO_VLIST support to md(4).
sys/geom/geom_disk.c:
Add BIO_VLIST support to the GEOM disk class. Re-factor the I/O size
limiting code in g_disk_start() a bit.
sys/kern/subr_bus_dma.c:
Change _bus_dmamap_load_vlist() to take a starting offset and
length.
Add a new function, _bus_dmamap_load_pages(), that will load a list
of physical pages starting at an offset.
Update _bus_dmamap_load_bio() to allow loading BIO_VLIST bios.
Allow unmapped I/O to start at an offset.
sys/kern/subr_uio.c:
Add two new functions, physcopyin_vlist() and physcopyout_vlist().
sys/pc98/include/bus.h:
Guard kernel-only parts of the pc98 machine/bus.h header with
#ifdef _KERNEL.
This allows userland programs to include <machine/bus.h> to get the
definition of bus_addr_t and bus_size_t.
sys/sys/bio.h:
Add a new bio flag, BIO_VLIST.
sys/sys/uio.h:
Add prototypes for physcopyin_vlist() and physcopyout_vlist().
share/man/man4/pass.4:
Document the CAMIOQUEUE and CAMIOGET ioctls.
usr.sbin/Makefile:
Add camdd.
usr.sbin/camdd/Makefile:
Add a makefile for camdd(8).
usr.sbin/camdd/camdd.8:
Man page for camdd(8).
usr.sbin/camdd/camdd.c:
The new camdd(8) utility.
Sponsored by: Spectra Logic
MFC after: 1 week
2015-12-03 20:54:55 +00:00
|
|
|
data_ptr,
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
/*dxfer_len*/ bp->bio_bcount,
|
|
|
|
/*sense_len*/SSD_FULL_SIZE,
|
|
|
|
da_default_timeout * 1000);
|
|
|
|
break;
|
Add asynchronous command support to the pass(4) driver, and the new
camdd(8) utility.
CCBs may be queued to the driver via the new CAMIOQUEUE ioctl, and
completed CCBs may be retrieved via the CAMIOGET ioctl. User
processes can use poll(2) or kevent(2) to get notification when
I/O has completed.
While the existing CAMIOCOMMAND blocking ioctl interface only
supports user virtual data pointers in a CCB (generally only
one per CCB), the new CAMIOQUEUE ioctl supports user virtual and
physical address pointers, as well as user virtual and physical
scatter/gather lists. This allows user applications to have more
flexibility in their data handling operations.
Kernel memory for data transferred via the queued interface is
allocated from the zone allocator in MAXPHYS sized chunks, and user
data is copied in and out. This is likely faster than the
vmapbuf()/vunmapbuf() method used by the CAMIOCOMMAND ioctl in
configurations with many processors (there are more TLB shootdowns
caused by the mapping/unmapping operation) but may not be as fast
as running with unmapped I/O.
The new memory handling model for user requests also allows
applications to send CCBs with request sizes that are larger than
MAXPHYS. The pass(4) driver now limits queued requests to the I/O
size listed by the SIM driver in the maxio field in the Path
Inquiry (XPT_PATH_INQ) CCB.
There are some things things would be good to add:
1. Come up with a way to do unmapped I/O on multiple buffers.
Currently the unmapped I/O interface operates on a struct bio,
which includes only one address and length. It would be nice
to be able to send an unmapped scatter/gather list down to
busdma. This would allow eliminating the copy we currently do
for data.
2. Add an ioctl to list currently outstanding CCBs in the various
queues.
3. Add an ioctl to cancel a request, or use the XPT_ABORT CCB to do
that.
4. Test physical address support. Virtual pointers and scatter
gather lists have been tested, but I have not yet tested
physical addresses or scatter/gather lists.
5. Investigate multiple queue support. At the moment there is one
queue of commands per pass(4) device. If multiple processes
open the device, they will submit I/O into the same queue and
get events for the same completions. This is probably the right
model for most applications, but it is something that could be
changed later on.
Also, add a new utility, camdd(8) that uses the asynchronous pass(4)
driver interface.
This utility is intended to be a basic data transfer/copy utility,
a simple benchmark utility, and an example of how to use the
asynchronous pass(4) interface.
It can copy data to and from pass(4) devices using any target queue
depth, starting offset and blocksize for the input and ouptut devices.
It currently only supports SCSI devices, but could be easily extended
to support ATA devices.
It can also copy data to and from regular files, block devices, tape
devices, pipes, stdin, and stdout. It does not support queueing
multiple commands to any of those targets, since it uses the standard
read(2)/write(2)/writev(2)/readv(2) system calls.
The I/O is done by two threads, one for the reader and one for the
writer. The reader thread sends completed read requests to the
writer thread in strictly sequential order, even if they complete
out of order. That could be modified later on for random I/O patterns
or slightly out of order I/O.
camdd(8) uses kqueue(2)/kevent(2) to get I/O completion events from
the pass(4) driver and also to send request notifications internally.
For pass(4) devcies, camdd(8) uses a single buffer (CAM_DATA_VADDR)
per CAM CCB on the reading side, and a scatter/gather list
(CAM_DATA_SG) on the writing side. In addition to testing both
interfaces, this makes any potential reblocking of I/O easier. No
data is copied between the reader and the writer, but rather the
reader's buffers are split into multiple I/O requests or combined
into a single I/O request depending on the input and output blocksize.
For the file I/O path, camdd(8) also uses a single buffer (read(2),
write(2), pread(2) or pwrite(2)) on reads, and a scatter/gather list
(readv(2), writev(2), preadv(2), pwritev(2)) on writes.
Things that would be nice to do for camdd(8) eventually:
1. Add support for I/O pattern generation. Patterns like all
zeros, all ones, LBA-based patterns, random patterns, etc. Right
Now you can always use /dev/zero, /dev/random, etc.
2. Add support for a "sink" mode, so we do only reads with no
writes. Right now, you can use /dev/null.
3. Add support for automatic queue depth probing, so that we can
figure out the right queue depth on the input and output side
for maximum throughput. At the moment it defaults to 6.
4. Add support for SATA device passthrough I/O.
5. Add support for random LBAs and/or lengths on the input and
output sides.
6. Track average per-I/O latency and busy time. The busy time
and latency could also feed in to the automatic queue depth
determination.
sys/cam/scsi/scsi_pass.h:
Define two new ioctls, CAMIOQUEUE and CAMIOGET, that queue
and fetch asynchronous CAM CCBs respectively.
Although these ioctls do not have a declared argument, they
both take a union ccb pointer. If we declare a size here,
the ioctl code in sys/kern/sys_generic.c will malloc and free
a buffer for either the CCB or the CCB pointer (depending on
how it is declared). Since we have to keep a copy of the
CCB (which is fairly large) anyway, having the ioctl malloc
and free a CCB for each call is wasteful.
sys/cam/scsi/scsi_pass.c:
Add asynchronous CCB support.
Add two new ioctls, CAMIOQUEUE and CAMIOGET.
CAMIOQUEUE adds a CCB to the incoming queue. The CCB is
executed immediately (and moved to the active queue) if it
is an immediate CCB, but otherwise it will be executed
in passstart() when a CCB is available from the transport layer.
When CCBs are completed (because they are immediate or
passdone() if they are queued), they are put on the done
queue.
If we get the final close on the device before all pending
I/O is complete, all active I/O is moved to the abandoned
queue and we increment the peripheral reference count so
that the peripheral driver instance doesn't go away before
all pending I/O is done.
The new passcreatezone() function is called on the first
call to the CAMIOQUEUE ioctl on a given device to allocate
the UMA zones for I/O requests and S/G list buffers. This
may be good to move off to a taskqueue at some point.
The new passmemsetup() function allocates memory and
scatter/gather lists to hold the user's data, and copies
in any data that needs to be written. For virtual pointers
(CAM_DATA_VADDR), the kernel buffer is malloced from the
new pass(4) driver malloc bucket. For virtual
scatter/gather lists (CAM_DATA_SG), buffers are allocated
from a new per-pass(9) UMA zone in MAXPHYS-sized chunks.
Physical pointers are passed in unchanged. We have support
for up to 16 scatter/gather segments (for the user and
kernel S/G lists) in the default struct pass_io_req, so
requests with longer S/G lists require an extra kernel malloc.
The new passcopysglist() function copies a user scatter/gather
list to a kernel scatter/gather list. The number of elements
in each list may be different, but (obviously) the amount of data
stored has to be identical.
The new passmemdone() function copies data out for the
CAM_DATA_VADDR and CAM_DATA_SG cases.
The new passiocleanup() function restores data pointers in
user CCBs and frees memory.
Add new functions to support kqueue(2)/kevent(2):
passreadfilt() tells kevent whether or not the done
queue is empty.
passkqfilter() adds a knote to our list.
passreadfiltdetach() removes a knote from our list.
Add a new function, passpoll(), for poll(2)/select(2)
to use.
Add devstat(9) support for the queued CCB path.
sys/cam/ata/ata_da.c:
Add support for the BIO_VLIST bio type.
sys/cam/cam_ccb.h:
Add a new enumeration for the xflags field in the CCB header.
(This doesn't change the CCB header, just adds an enumeration to
use.)
sys/cam/cam_xpt.c:
Add a new function, xpt_setup_ccb_flags(), that allows specifying
CCB flags.
sys/cam/cam_xpt.h:
Add a prototype for xpt_setup_ccb_flags().
sys/cam/scsi/scsi_da.c:
Add support for BIO_VLIST.
sys/dev/md/md.c:
Add BIO_VLIST support to md(4).
sys/geom/geom_disk.c:
Add BIO_VLIST support to the GEOM disk class. Re-factor the I/O size
limiting code in g_disk_start() a bit.
sys/kern/subr_bus_dma.c:
Change _bus_dmamap_load_vlist() to take a starting offset and
length.
Add a new function, _bus_dmamap_load_pages(), that will load a list
of physical pages starting at an offset.
Update _bus_dmamap_load_bio() to allow loading BIO_VLIST bios.
Allow unmapped I/O to start at an offset.
sys/kern/subr_uio.c:
Add two new functions, physcopyin_vlist() and physcopyout_vlist().
sys/pc98/include/bus.h:
Guard kernel-only parts of the pc98 machine/bus.h header with
#ifdef _KERNEL.
This allows userland programs to include <machine/bus.h> to get the
definition of bus_addr_t and bus_size_t.
sys/sys/bio.h:
Add a new bio flag, BIO_VLIST.
sys/sys/uio.h:
Add prototypes for physcopyin_vlist() and physcopyout_vlist().
share/man/man4/pass.4:
Document the CAMIOQUEUE and CAMIOGET ioctls.
usr.sbin/Makefile:
Add camdd.
usr.sbin/camdd/Makefile:
Add a makefile for camdd(8).
usr.sbin/camdd/camdd.8:
Man page for camdd(8).
usr.sbin/camdd/camdd.c:
The new camdd(8) utility.
Sponsored by: Spectra Logic
MFC after: 1 week
2015-12-03 20:54:55 +00:00
|
|
|
}
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
case BIO_FLUSH:
|
1998-09-15 06:36:34 +00:00
|
|
|
/*
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
* BIO_FLUSH doesn't currently communicate
|
|
|
|
* range data, so we synchronize the cache
|
|
|
|
* over the whole disk. We also force
|
|
|
|
* ordered tag semantics the flush applies
|
|
|
|
* to all previously queued I/O.
|
1998-09-15 06:36:34 +00:00
|
|
|
*/
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
scsi_synchronize_cache(&start_ccb->csio,
|
|
|
|
/*retries*/1,
|
|
|
|
/*cbfcnp*/dadone,
|
|
|
|
MSG_ORDERED_Q_TAG,
|
|
|
|
/*begin_lba*/0,
|
|
|
|
/*lb_count*/0,
|
|
|
|
SSD_FULL_SIZE,
|
|
|
|
da_default_timeout*1000);
|
|
|
|
break;
|
1998-09-15 06:36:34 +00:00
|
|
|
}
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
start_ccb->ccb_h.ccb_state = DA_CCB_BUFFER_IO;
|
Merge CAM locking changes from the projects/camlock branch to radically
reduce lock congestion and improve SMP scalability of the SCSI/ATA stack,
preparing the ground for the coming next GEOM direct dispatch support.
Replace big per-SIM locks with bunch of smaller ones:
- per-LUN locks to protect device and peripheral drivers state;
- per-target locks to protect list of LUNs on target;
- per-bus locks to protect reference counting;
- per-send queue locks to protect queue of CCBs to be sent;
- per-done queue locks to protect queue of completed CCBs;
- remaining per-SIM locks now protect only HBA driver internals.
While holding LUN lock it is allowed (while not recommended for performance
reasons) to take SIM lock. The opposite acquisition order is forbidden.
All the other locks are leaf locks, that can be taken anywhere, but should
not be cascaded. Many functions, such as: xpt_action(), xpt_done(),
xpt_async(), xpt_create_path(), etc. are no longer require (but allow) SIM
lock to be held.
To keep compatibility and solve cases where SIM lock can't be dropped, all
xpt_async() calls in addition to xpt_done() calls are queued to completion
threads for async processing in clean environment without SIM lock held.
Instead of single CAM SWI thread, used for commands completion processing
before, use multiple (depending on number of CPUs) threads. Load balanced
between them using "hash" of the device B:T:L address.
HBA drivers that can drop SIM lock during completion processing and have
sufficient number of completion threads to efficiently scale to multiple
CPUs can use new function xpt_done_direct() to avoid extra context switch.
Make ahci(4) driver to use this mechanism depending on hardware setup.
Sponsored by: iXsystems, Inc.
MFC after: 2 months
2013-10-21 12:00:26 +00:00
|
|
|
start_ccb->ccb_h.flags |= CAM_UNLOCKED;
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
|
|
|
|
out:
|
|
|
|
LIST_INSERT_HEAD(&softc->pending_ccbs,
|
|
|
|
&start_ccb->ccb_h, periph_links.le);
|
|
|
|
|
|
|
|
/* We expect a unit attention from this device */
|
|
|
|
if ((softc->flags & DA_FLAG_RETRY_UA) != 0) {
|
|
|
|
start_ccb->ccb_h.ccb_state |= DA_CCB_RETRY_UA;
|
|
|
|
softc->flags &= ~DA_FLAG_RETRY_UA;
|
1998-09-15 06:36:34 +00:00
|
|
|
}
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
|
|
|
|
start_ccb->ccb_h.ccb_bp = bp;
|
Merge CAM locking changes from the projects/camlock branch to radically
reduce lock congestion and improve SMP scalability of the SCSI/ATA stack,
preparing the ground for the coming next GEOM direct dispatch support.
Replace big per-SIM locks with bunch of smaller ones:
- per-LUN locks to protect device and peripheral drivers state;
- per-target locks to protect list of LUNs on target;
- per-bus locks to protect reference counting;
- per-send queue locks to protect queue of CCBs to be sent;
- per-done queue locks to protect queue of completed CCBs;
- remaining per-SIM locks now protect only HBA driver internals.
While holding LUN lock it is allowed (while not recommended for performance
reasons) to take SIM lock. The opposite acquisition order is forbidden.
All the other locks are leaf locks, that can be taken anywhere, but should
not be cascaded. Many functions, such as: xpt_action(), xpt_done(),
xpt_async(), xpt_create_path(), etc. are no longer require (but allow) SIM
lock to be held.
To keep compatibility and solve cases where SIM lock can't be dropped, all
xpt_async() calls in addition to xpt_done() calls are queued to completion
threads for async processing in clean environment without SIM lock held.
Instead of single CAM SWI thread, used for commands completion processing
before, use multiple (depending on number of CPUs) threads. Load balanced
between them using "hash" of the device B:T:L address.
HBA drivers that can drop SIM lock during completion processing and have
sufficient number of completion threads to efficiently scale to multiple
CPUs can use new function xpt_done_direct() to avoid extra context switch.
Make ahci(4) driver to use this mechanism depending on hardware setup.
Sponsored by: iXsystems, Inc.
MFC after: 2 months
2013-10-21 12:00:26 +00:00
|
|
|
softc->refcount++;
|
|
|
|
cam_periph_unlock(periph);
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
xpt_action(start_ccb);
|
Merge CAM locking changes from the projects/camlock branch to radically
reduce lock congestion and improve SMP scalability of the SCSI/ATA stack,
preparing the ground for the coming next GEOM direct dispatch support.
Replace big per-SIM locks with bunch of smaller ones:
- per-LUN locks to protect device and peripheral drivers state;
- per-target locks to protect list of LUNs on target;
- per-bus locks to protect reference counting;
- per-send queue locks to protect queue of CCBs to be sent;
- per-done queue locks to protect queue of completed CCBs;
- remaining per-SIM locks now protect only HBA driver internals.
While holding LUN lock it is allowed (while not recommended for performance
reasons) to take SIM lock. The opposite acquisition order is forbidden.
All the other locks are leaf locks, that can be taken anywhere, but should
not be cascaded. Many functions, such as: xpt_action(), xpt_done(),
xpt_async(), xpt_create_path(), etc. are no longer require (but allow) SIM
lock to be held.
To keep compatibility and solve cases where SIM lock can't be dropped, all
xpt_async() calls in addition to xpt_done() calls are queued to completion
threads for async processing in clean environment without SIM lock held.
Instead of single CAM SWI thread, used for commands completion processing
before, use multiple (depending on number of CPUs) threads. Load balanced
between them using "hash" of the device B:T:L address.
HBA drivers that can drop SIM lock during completion processing and have
sufficient number of completion threads to efficiently scale to multiple
CPUs can use new function xpt_done_direct() to avoid extra context switch.
Make ahci(4) driver to use this mechanism depending on hardware setup.
Sponsored by: iXsystems, Inc.
MFC after: 2 months
2013-10-21 12:00:26 +00:00
|
|
|
cam_periph_lock(periph);
|
|
|
|
softc->refcount--;
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
|
|
|
|
/* May have more work to do, so ensure we stay scheduled */
|
|
|
|
daschedule(periph);
|
1998-09-15 06:36:34 +00:00
|
|
|
break;
|
|
|
|
}
|
2013-04-26 16:17:04 +00:00
|
|
|
case DA_STATE_PROBE_RC:
|
1998-09-15 06:36:34 +00:00
|
|
|
{
|
|
|
|
struct scsi_read_capacity_data *rcap;
|
|
|
|
|
2007-05-18 21:58:07 +00:00
|
|
|
rcap = (struct scsi_read_capacity_data *)
|
|
|
|
malloc(sizeof(*rcap), M_SCSIDA, M_NOWAIT|M_ZERO);
|
1998-09-15 06:36:34 +00:00
|
|
|
if (rcap == NULL) {
|
|
|
|
printf("dastart: Couldn't malloc read_capacity data\n");
|
|
|
|
/* da_free_periph??? */
|
|
|
|
break;
|
|
|
|
}
|
2013-01-10 11:28:12 +00:00
|
|
|
scsi_read_capacity(&start_ccb->csio,
|
2013-01-10 12:25:00 +00:00
|
|
|
/*retries*/da_retry_count,
|
1998-09-15 06:36:34 +00:00
|
|
|
dadone,
|
|
|
|
MSG_SIMPLE_Q_TAG,
|
|
|
|
rcap,
|
|
|
|
SSD_FULL_SIZE,
|
|
|
|
/*timeout*/5000);
|
|
|
|
start_ccb->ccb_h.ccb_bp = NULL;
|
2013-04-26 16:17:04 +00:00
|
|
|
start_ccb->ccb_h.ccb_state = DA_CCB_PROBE_RC;
|
1998-09-15 06:36:34 +00:00
|
|
|
xpt_action(start_ccb);
|
|
|
|
break;
|
|
|
|
}
|
2013-04-26 16:17:04 +00:00
|
|
|
case DA_STATE_PROBE_RC16:
|
Add support to CAM for devices with more than 2^32 blocks. (2TB if you're
using 512 byte blocks).
cam_ccb.h: Bump up volume_size and cylinders in ccb_calc_geometry to
64 bits and 32 bits respectively, so we can hold larger
device sizes. cylinders would overflow at about 500GB.
Bump CAM_VERSION for this change. Note that this will
require a recompile of all applications that talk to the
pass(4) driver.
scsi_all.c: Add descriptions for READ/WRITE(16), update READ/WRITE(12)
descriptions, add descriptions for SERVICE ACTION IN/OUT.
Add a new function, scsi_read_capacity_16(), that issues
the read capacity service action. (Necessary for arrays
larger than 2^32 sectors.) Update scsi_read_write() to use
a 64 bit LBA and issue READ(16) or WRITE(16) if necessary.
NOTE the API change. This should be largely transparnet
to most userland applications at compile time, but will
break binary compatibility. The CAM_VERSION bump, above,
also serves the purpose of forcing a recompile for any
applications that talk to CAM.
scsi_all.h: Add 16 byte READ/WRITE structures, structures for 16 byte
READ CAPACITY/SERVICE ACTION IN. Add scsi_u64to8b() and
scsi_8btou64.
scsi_da.c: The da(4) driver probe now has two stages for devices
larger than 2TB. If a standard READ CAPACITY(10) returns
0xffffffff, we issue the 16 byte version of read capacity
to determine the true array capacity. We also do the same
thing in daopen() -- use the 16 byte read capacity if the
device is large enough.
The sysctl/loader code has also been updated to accept
16 bytes as a minimum command size.
2003-04-30 00:35:22 +00:00
|
|
|
{
|
|
|
|
struct scsi_read_capacity_data_long *rcaplong;
|
|
|
|
|
|
|
|
rcaplong = (struct scsi_read_capacity_data_long *)
|
2007-05-18 21:58:07 +00:00
|
|
|
malloc(sizeof(*rcaplong), M_SCSIDA, M_NOWAIT|M_ZERO);
|
Add support to CAM for devices with more than 2^32 blocks. (2TB if you're
using 512 byte blocks).
cam_ccb.h: Bump up volume_size and cylinders in ccb_calc_geometry to
64 bits and 32 bits respectively, so we can hold larger
device sizes. cylinders would overflow at about 500GB.
Bump CAM_VERSION for this change. Note that this will
require a recompile of all applications that talk to the
pass(4) driver.
scsi_all.c: Add descriptions for READ/WRITE(16), update READ/WRITE(12)
descriptions, add descriptions for SERVICE ACTION IN/OUT.
Add a new function, scsi_read_capacity_16(), that issues
the read capacity service action. (Necessary for arrays
larger than 2^32 sectors.) Update scsi_read_write() to use
a 64 bit LBA and issue READ(16) or WRITE(16) if necessary.
NOTE the API change. This should be largely transparnet
to most userland applications at compile time, but will
break binary compatibility. The CAM_VERSION bump, above,
also serves the purpose of forcing a recompile for any
applications that talk to CAM.
scsi_all.h: Add 16 byte READ/WRITE structures, structures for 16 byte
READ CAPACITY/SERVICE ACTION IN. Add scsi_u64to8b() and
scsi_8btou64.
scsi_da.c: The da(4) driver probe now has two stages for devices
larger than 2TB. If a standard READ CAPACITY(10) returns
0xffffffff, we issue the 16 byte version of read capacity
to determine the true array capacity. We also do the same
thing in daopen() -- use the 16 byte read capacity if the
device is large enough.
The sysctl/loader code has also been updated to accept
16 bytes as a minimum command size.
2003-04-30 00:35:22 +00:00
|
|
|
if (rcaplong == NULL) {
|
|
|
|
printf("dastart: Couldn't malloc read_capacity data\n");
|
|
|
|
/* da_free_periph??? */
|
|
|
|
break;
|
|
|
|
}
|
2013-01-10 11:28:12 +00:00
|
|
|
scsi_read_capacity_16(&start_ccb->csio,
|
2013-01-10 12:25:00 +00:00
|
|
|
/*retries*/ da_retry_count,
|
Add support to CAM for devices with more than 2^32 blocks. (2TB if you're
using 512 byte blocks).
cam_ccb.h: Bump up volume_size and cylinders in ccb_calc_geometry to
64 bits and 32 bits respectively, so we can hold larger
device sizes. cylinders would overflow at about 500GB.
Bump CAM_VERSION for this change. Note that this will
require a recompile of all applications that talk to the
pass(4) driver.
scsi_all.c: Add descriptions for READ/WRITE(16), update READ/WRITE(12)
descriptions, add descriptions for SERVICE ACTION IN/OUT.
Add a new function, scsi_read_capacity_16(), that issues
the read capacity service action. (Necessary for arrays
larger than 2^32 sectors.) Update scsi_read_write() to use
a 64 bit LBA and issue READ(16) or WRITE(16) if necessary.
NOTE the API change. This should be largely transparnet
to most userland applications at compile time, but will
break binary compatibility. The CAM_VERSION bump, above,
also serves the purpose of forcing a recompile for any
applications that talk to CAM.
scsi_all.h: Add 16 byte READ/WRITE structures, structures for 16 byte
READ CAPACITY/SERVICE ACTION IN. Add scsi_u64to8b() and
scsi_8btou64.
scsi_da.c: The da(4) driver probe now has two stages for devices
larger than 2TB. If a standard READ CAPACITY(10) returns
0xffffffff, we issue the 16 byte version of read capacity
to determine the true array capacity. We also do the same
thing in daopen() -- use the 16 byte read capacity if the
device is large enough.
The sysctl/loader code has also been updated to accept
16 bytes as a minimum command size.
2003-04-30 00:35:22 +00:00
|
|
|
/*cbfcnp*/ dadone,
|
|
|
|
/*tag_action*/ MSG_SIMPLE_Q_TAG,
|
|
|
|
/*lba*/ 0,
|
|
|
|
/*reladr*/ 0,
|
|
|
|
/*pmi*/ 0,
|
2012-01-26 18:09:28 +00:00
|
|
|
/*rcap_buf*/ (uint8_t *)rcaplong,
|
|
|
|
/*rcap_buf_len*/ sizeof(*rcaplong),
|
Add support to CAM for devices with more than 2^32 blocks. (2TB if you're
using 512 byte blocks).
cam_ccb.h: Bump up volume_size and cylinders in ccb_calc_geometry to
64 bits and 32 bits respectively, so we can hold larger
device sizes. cylinders would overflow at about 500GB.
Bump CAM_VERSION for this change. Note that this will
require a recompile of all applications that talk to the
pass(4) driver.
scsi_all.c: Add descriptions for READ/WRITE(16), update READ/WRITE(12)
descriptions, add descriptions for SERVICE ACTION IN/OUT.
Add a new function, scsi_read_capacity_16(), that issues
the read capacity service action. (Necessary for arrays
larger than 2^32 sectors.) Update scsi_read_write() to use
a 64 bit LBA and issue READ(16) or WRITE(16) if necessary.
NOTE the API change. This should be largely transparnet
to most userland applications at compile time, but will
break binary compatibility. The CAM_VERSION bump, above,
also serves the purpose of forcing a recompile for any
applications that talk to CAM.
scsi_all.h: Add 16 byte READ/WRITE structures, structures for 16 byte
READ CAPACITY/SERVICE ACTION IN. Add scsi_u64to8b() and
scsi_8btou64.
scsi_da.c: The da(4) driver probe now has two stages for devices
larger than 2TB. If a standard READ CAPACITY(10) returns
0xffffffff, we issue the 16 byte version of read capacity
to determine the true array capacity. We also do the same
thing in daopen() -- use the 16 byte read capacity if the
device is large enough.
The sysctl/loader code has also been updated to accept
16 bytes as a minimum command size.
2003-04-30 00:35:22 +00:00
|
|
|
/*sense_len*/ SSD_FULL_SIZE,
|
2013-01-10 12:25:00 +00:00
|
|
|
/*timeout*/ da_default_timeout * 1000);
|
Add support to CAM for devices with more than 2^32 blocks. (2TB if you're
using 512 byte blocks).
cam_ccb.h: Bump up volume_size and cylinders in ccb_calc_geometry to
64 bits and 32 bits respectively, so we can hold larger
device sizes. cylinders would overflow at about 500GB.
Bump CAM_VERSION for this change. Note that this will
require a recompile of all applications that talk to the
pass(4) driver.
scsi_all.c: Add descriptions for READ/WRITE(16), update READ/WRITE(12)
descriptions, add descriptions for SERVICE ACTION IN/OUT.
Add a new function, scsi_read_capacity_16(), that issues
the read capacity service action. (Necessary for arrays
larger than 2^32 sectors.) Update scsi_read_write() to use
a 64 bit LBA and issue READ(16) or WRITE(16) if necessary.
NOTE the API change. This should be largely transparnet
to most userland applications at compile time, but will
break binary compatibility. The CAM_VERSION bump, above,
also serves the purpose of forcing a recompile for any
applications that talk to CAM.
scsi_all.h: Add 16 byte READ/WRITE structures, structures for 16 byte
READ CAPACITY/SERVICE ACTION IN. Add scsi_u64to8b() and
scsi_8btou64.
scsi_da.c: The da(4) driver probe now has two stages for devices
larger than 2TB. If a standard READ CAPACITY(10) returns
0xffffffff, we issue the 16 byte version of read capacity
to determine the true array capacity. We also do the same
thing in daopen() -- use the 16 byte read capacity if the
device is large enough.
The sysctl/loader code has also been updated to accept
16 bytes as a minimum command size.
2003-04-30 00:35:22 +00:00
|
|
|
start_ccb->ccb_h.ccb_bp = NULL;
|
2013-04-26 16:17:04 +00:00
|
|
|
start_ccb->ccb_h.ccb_state = DA_CCB_PROBE_RC16;
|
|
|
|
xpt_action(start_ccb);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case DA_STATE_PROBE_LBP:
|
|
|
|
{
|
|
|
|
struct scsi_vpd_logical_block_prov *lbp;
|
|
|
|
|
|
|
|
if (!scsi_vpd_supported_page(periph, SVPD_LBP)) {
|
|
|
|
/*
|
|
|
|
* If we get here we don't support any SBC-3 delete
|
|
|
|
* methods with UNMAP as the Logical Block Provisioning
|
|
|
|
* VPD page support is required for devices which
|
|
|
|
* support it according to T10/1799-D Revision 31
|
|
|
|
* however older revisions of the spec don't mandate
|
|
|
|
* this so we currently don't remove these methods
|
|
|
|
* from the available set.
|
|
|
|
*/
|
|
|
|
softc->state = DA_STATE_PROBE_BLK_LIMITS;
|
|
|
|
goto skipstate;
|
|
|
|
}
|
|
|
|
|
|
|
|
lbp = (struct scsi_vpd_logical_block_prov *)
|
|
|
|
malloc(sizeof(*lbp), M_SCSIDA, M_NOWAIT|M_ZERO);
|
|
|
|
|
|
|
|
if (lbp == NULL) {
|
|
|
|
printf("dastart: Couldn't malloc lbp data\n");
|
|
|
|
/* da_free_periph??? */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
scsi_inquiry(&start_ccb->csio,
|
|
|
|
/*retries*/da_retry_count,
|
|
|
|
/*cbfcnp*/dadone,
|
|
|
|
/*tag_action*/MSG_SIMPLE_Q_TAG,
|
|
|
|
/*inq_buf*/(u_int8_t *)lbp,
|
|
|
|
/*inq_len*/sizeof(*lbp),
|
|
|
|
/*evpd*/TRUE,
|
|
|
|
/*page_code*/SVPD_LBP,
|
|
|
|
/*sense_len*/SSD_MIN_SIZE,
|
|
|
|
/*timeout*/da_default_timeout * 1000);
|
|
|
|
start_ccb->ccb_h.ccb_bp = NULL;
|
|
|
|
start_ccb->ccb_h.ccb_state = DA_CCB_PROBE_LBP;
|
|
|
|
xpt_action(start_ccb);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case DA_STATE_PROBE_BLK_LIMITS:
|
|
|
|
{
|
|
|
|
struct scsi_vpd_block_limits *block_limits;
|
|
|
|
|
|
|
|
if (!scsi_vpd_supported_page(periph, SVPD_BLOCK_LIMITS)) {
|
|
|
|
/* Not supported skip to next probe */
|
2013-05-02 14:14:57 +00:00
|
|
|
softc->state = DA_STATE_PROBE_BDC;
|
2013-04-26 16:17:04 +00:00
|
|
|
goto skipstate;
|
|
|
|
}
|
|
|
|
|
|
|
|
block_limits = (struct scsi_vpd_block_limits *)
|
|
|
|
malloc(sizeof(*block_limits), M_SCSIDA, M_NOWAIT|M_ZERO);
|
|
|
|
|
|
|
|
if (block_limits == NULL) {
|
|
|
|
printf("dastart: Couldn't malloc block_limits data\n");
|
|
|
|
/* da_free_periph??? */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
scsi_inquiry(&start_ccb->csio,
|
|
|
|
/*retries*/da_retry_count,
|
|
|
|
/*cbfcnp*/dadone,
|
|
|
|
/*tag_action*/MSG_SIMPLE_Q_TAG,
|
|
|
|
/*inq_buf*/(u_int8_t *)block_limits,
|
|
|
|
/*inq_len*/sizeof(*block_limits),
|
|
|
|
/*evpd*/TRUE,
|
|
|
|
/*page_code*/SVPD_BLOCK_LIMITS,
|
|
|
|
/*sense_len*/SSD_MIN_SIZE,
|
|
|
|
/*timeout*/da_default_timeout * 1000);
|
|
|
|
start_ccb->ccb_h.ccb_bp = NULL;
|
|
|
|
start_ccb->ccb_h.ccb_state = DA_CCB_PROBE_BLK_LIMITS;
|
|
|
|
xpt_action(start_ccb);
|
|
|
|
break;
|
|
|
|
}
|
2013-04-26 16:31:03 +00:00
|
|
|
case DA_STATE_PROBE_BDC:
|
|
|
|
{
|
|
|
|
struct scsi_vpd_block_characteristics *bdc;
|
|
|
|
|
|
|
|
if (!scsi_vpd_supported_page(periph, SVPD_BDC)) {
|
|
|
|
softc->state = DA_STATE_PROBE_ATA;
|
|
|
|
goto skipstate;
|
|
|
|
}
|
|
|
|
|
|
|
|
bdc = (struct scsi_vpd_block_characteristics *)
|
|
|
|
malloc(sizeof(*bdc), M_SCSIDA, M_NOWAIT|M_ZERO);
|
|
|
|
|
|
|
|
if (bdc == NULL) {
|
|
|
|
printf("dastart: Couldn't malloc bdc data\n");
|
|
|
|
/* da_free_periph??? */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
scsi_inquiry(&start_ccb->csio,
|
|
|
|
/*retries*/da_retry_count,
|
|
|
|
/*cbfcnp*/dadone,
|
|
|
|
/*tag_action*/MSG_SIMPLE_Q_TAG,
|
|
|
|
/*inq_buf*/(u_int8_t *)bdc,
|
|
|
|
/*inq_len*/sizeof(*bdc),
|
|
|
|
/*evpd*/TRUE,
|
|
|
|
/*page_code*/SVPD_BDC,
|
|
|
|
/*sense_len*/SSD_MIN_SIZE,
|
|
|
|
/*timeout*/da_default_timeout * 1000);
|
|
|
|
start_ccb->ccb_h.ccb_bp = NULL;
|
|
|
|
start_ccb->ccb_h.ccb_state = DA_CCB_PROBE_BDC;
|
|
|
|
xpt_action(start_ccb);
|
|
|
|
break;
|
|
|
|
}
|
2013-04-26 16:17:04 +00:00
|
|
|
case DA_STATE_PROBE_ATA:
|
|
|
|
{
|
|
|
|
struct ata_params *ata_params;
|
|
|
|
|
2013-05-02 14:37:23 +00:00
|
|
|
if (!scsi_vpd_supported_page(periph, SVPD_ATA_INFORMATION)) {
|
|
|
|
daprobedone(periph, start_ccb);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2013-04-26 16:17:04 +00:00
|
|
|
ata_params = (struct ata_params*)
|
|
|
|
malloc(sizeof(*ata_params), M_SCSIDA, M_NOWAIT|M_ZERO);
|
|
|
|
|
|
|
|
if (ata_params == NULL) {
|
|
|
|
printf("dastart: Couldn't malloc ata_params data\n");
|
|
|
|
/* da_free_periph??? */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
scsi_ata_identify(&start_ccb->csio,
|
|
|
|
/*retries*/da_retry_count,
|
|
|
|
/*cbfcnp*/dadone,
|
|
|
|
/*tag_action*/MSG_SIMPLE_Q_TAG,
|
|
|
|
/*data_ptr*/(u_int8_t *)ata_params,
|
|
|
|
/*dxfer_len*/sizeof(*ata_params),
|
|
|
|
/*sense_len*/SSD_FULL_SIZE,
|
|
|
|
/*timeout*/da_default_timeout * 1000);
|
|
|
|
start_ccb->ccb_h.ccb_bp = NULL;
|
|
|
|
start_ccb->ccb_h.ccb_state = DA_CCB_PROBE_ATA;
|
|
|
|
xpt_action(start_ccb);
|
Add support to CAM for devices with more than 2^32 blocks. (2TB if you're
using 512 byte blocks).
cam_ccb.h: Bump up volume_size and cylinders in ccb_calc_geometry to
64 bits and 32 bits respectively, so we can hold larger
device sizes. cylinders would overflow at about 500GB.
Bump CAM_VERSION for this change. Note that this will
require a recompile of all applications that talk to the
pass(4) driver.
scsi_all.c: Add descriptions for READ/WRITE(16), update READ/WRITE(12)
descriptions, add descriptions for SERVICE ACTION IN/OUT.
Add a new function, scsi_read_capacity_16(), that issues
the read capacity service action. (Necessary for arrays
larger than 2^32 sectors.) Update scsi_read_write() to use
a 64 bit LBA and issue READ(16) or WRITE(16) if necessary.
NOTE the API change. This should be largely transparnet
to most userland applications at compile time, but will
break binary compatibility. The CAM_VERSION bump, above,
also serves the purpose of forcing a recompile for any
applications that talk to CAM.
scsi_all.h: Add 16 byte READ/WRITE structures, structures for 16 byte
READ CAPACITY/SERVICE ACTION IN. Add scsi_u64to8b() and
scsi_8btou64.
scsi_da.c: The da(4) driver probe now has two stages for devices
larger than 2TB. If a standard READ CAPACITY(10) returns
0xffffffff, we issue the 16 byte version of read capacity
to determine the true array capacity. We also do the same
thing in daopen() -- use the 16 byte read capacity if the
device is large enough.
The sysctl/loader code has also been updated to accept
16 bytes as a minimum command size.
2003-04-30 00:35:22 +00:00
|
|
|
break;
|
|
|
|
}
|
1998-09-15 06:36:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-12 00:50:25 +00:00
|
|
|
/*
|
|
|
|
* In each of the methods below, while its the caller's
|
|
|
|
* responsibility to ensure the request will fit into a
|
|
|
|
* single device request, we might have changed the delete
|
|
|
|
* method due to the device incorrectly advertising either
|
|
|
|
* its supported methods or limits.
|
|
|
|
*
|
|
|
|
* To prevent this causing further issues we validate the
|
|
|
|
* against the methods limits, and warn which would
|
|
|
|
* otherwise be unnecessary.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
da_delete_unmap(struct cam_periph *periph, union ccb *ccb, struct bio *bp)
|
|
|
|
{
|
|
|
|
struct da_softc *softc = (struct da_softc *)periph->softc;;
|
|
|
|
struct bio *bp1;
|
|
|
|
uint8_t *buf = softc->unmap_buf;
|
|
|
|
uint64_t lba, lastlba = (uint64_t)-1;
|
2014-01-22 22:19:53 +00:00
|
|
|
uint64_t totalcount = 0;
|
2013-07-12 00:50:25 +00:00
|
|
|
uint64_t count;
|
|
|
|
uint32_t lastcount = 0, c;
|
|
|
|
uint32_t off, ranges = 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Currently this doesn't take the UNMAP
|
|
|
|
* Granularity and Granularity Alignment
|
|
|
|
* fields into account.
|
|
|
|
*
|
|
|
|
* This could result in both unoptimal unmap
|
|
|
|
* requests as as well as UNMAP calls unmapping
|
|
|
|
* fewer LBA's than requested.
|
|
|
|
*/
|
|
|
|
|
|
|
|
softc->delete_running = 1;
|
|
|
|
bzero(softc->unmap_buf, sizeof(softc->unmap_buf));
|
|
|
|
bp1 = bp;
|
|
|
|
do {
|
|
|
|
bioq_remove(&softc->delete_queue, bp1);
|
|
|
|
if (bp1 != bp)
|
|
|
|
bioq_insert_tail(&softc->delete_run_queue, bp1);
|
|
|
|
lba = bp1->bio_pblkno;
|
|
|
|
count = bp1->bio_bcount / softc->params.secsize;
|
|
|
|
|
|
|
|
/* Try to extend the previous range. */
|
|
|
|
if (lba == lastlba) {
|
2014-01-22 22:19:53 +00:00
|
|
|
c = omin(count, UNMAP_RANGE_MAX - lastcount);
|
2013-07-12 00:50:25 +00:00
|
|
|
lastcount += c;
|
|
|
|
off = ((ranges - 1) * UNMAP_RANGE_SIZE) +
|
|
|
|
UNMAP_HEAD_SIZE;
|
|
|
|
scsi_ulto4b(lastcount, &buf[off + 8]);
|
|
|
|
count -= c;
|
|
|
|
lba +=c;
|
2014-01-22 22:19:53 +00:00
|
|
|
totalcount += c;
|
2013-07-12 00:50:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
while (count > 0) {
|
2014-01-22 22:19:53 +00:00
|
|
|
c = omin(count, UNMAP_RANGE_MAX);
|
|
|
|
if (totalcount + c > softc->unmap_max_lba ||
|
|
|
|
ranges >= softc->unmap_max_ranges) {
|
2013-07-12 00:50:25 +00:00
|
|
|
xpt_print(periph->path,
|
2014-01-22 22:19:53 +00:00
|
|
|
"%s issuing short delete %ld > %ld"
|
|
|
|
"|| %d >= %d",
|
2013-07-12 00:50:25 +00:00
|
|
|
da_delete_method_desc[softc->delete_method],
|
2014-01-22 22:19:53 +00:00
|
|
|
totalcount + c, softc->unmap_max_lba,
|
2013-07-12 00:50:25 +00:00
|
|
|
ranges, softc->unmap_max_ranges);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
off = (ranges * UNMAP_RANGE_SIZE) + UNMAP_HEAD_SIZE;
|
|
|
|
scsi_u64to8b(lba, &buf[off + 0]);
|
|
|
|
scsi_ulto4b(c, &buf[off + 8]);
|
|
|
|
lba += c;
|
2014-01-22 22:19:53 +00:00
|
|
|
totalcount += c;
|
2013-07-12 00:50:25 +00:00
|
|
|
ranges++;
|
|
|
|
count -= c;
|
|
|
|
lastcount = c;
|
|
|
|
}
|
|
|
|
lastlba = lba;
|
|
|
|
bp1 = bioq_first(&softc->delete_queue);
|
|
|
|
if (bp1 == NULL || ranges >= softc->unmap_max_ranges ||
|
2014-01-22 22:19:53 +00:00
|
|
|
totalcount + bp1->bio_bcount /
|
|
|
|
softc->params.secsize > softc->unmap_max_lba)
|
2013-07-12 00:50:25 +00:00
|
|
|
break;
|
|
|
|
} while (1);
|
|
|
|
scsi_ulto2b(ranges * 16 + 6, &buf[0]);
|
|
|
|
scsi_ulto2b(ranges * 16, &buf[2]);
|
|
|
|
|
|
|
|
scsi_unmap(&ccb->csio,
|
|
|
|
/*retries*/da_retry_count,
|
|
|
|
/*cbfcnp*/dadone,
|
|
|
|
/*tag_action*/MSG_SIMPLE_Q_TAG,
|
|
|
|
/*byte2*/0,
|
|
|
|
/*data_ptr*/ buf,
|
|
|
|
/*dxfer_len*/ ranges * 16 + 8,
|
|
|
|
/*sense_len*/SSD_FULL_SIZE,
|
|
|
|
da_default_timeout * 1000);
|
|
|
|
ccb->ccb_h.ccb_state = DA_CCB_DELETE;
|
Merge CAM locking changes from the projects/camlock branch to radically
reduce lock congestion and improve SMP scalability of the SCSI/ATA stack,
preparing the ground for the coming next GEOM direct dispatch support.
Replace big per-SIM locks with bunch of smaller ones:
- per-LUN locks to protect device and peripheral drivers state;
- per-target locks to protect list of LUNs on target;
- per-bus locks to protect reference counting;
- per-send queue locks to protect queue of CCBs to be sent;
- per-done queue locks to protect queue of completed CCBs;
- remaining per-SIM locks now protect only HBA driver internals.
While holding LUN lock it is allowed (while not recommended for performance
reasons) to take SIM lock. The opposite acquisition order is forbidden.
All the other locks are leaf locks, that can be taken anywhere, but should
not be cascaded. Many functions, such as: xpt_action(), xpt_done(),
xpt_async(), xpt_create_path(), etc. are no longer require (but allow) SIM
lock to be held.
To keep compatibility and solve cases where SIM lock can't be dropped, all
xpt_async() calls in addition to xpt_done() calls are queued to completion
threads for async processing in clean environment without SIM lock held.
Instead of single CAM SWI thread, used for commands completion processing
before, use multiple (depending on number of CPUs) threads. Load balanced
between them using "hash" of the device B:T:L address.
HBA drivers that can drop SIM lock during completion processing and have
sufficient number of completion threads to efficiently scale to multiple
CPUs can use new function xpt_done_direct() to avoid extra context switch.
Make ahci(4) driver to use this mechanism depending on hardware setup.
Sponsored by: iXsystems, Inc.
MFC after: 2 months
2013-10-21 12:00:26 +00:00
|
|
|
ccb->ccb_h.flags |= CAM_UNLOCKED;
|
2013-07-12 00:50:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
da_delete_trim(struct cam_periph *periph, union ccb *ccb, struct bio *bp)
|
|
|
|
{
|
|
|
|
struct da_softc *softc = (struct da_softc *)periph->softc;
|
|
|
|
struct bio *bp1;
|
|
|
|
uint8_t *buf = softc->unmap_buf;
|
|
|
|
uint64_t lastlba = (uint64_t)-1;
|
|
|
|
uint64_t count;
|
|
|
|
uint64_t lba;
|
|
|
|
uint32_t lastcount = 0, c, requestcount;
|
|
|
|
int ranges = 0, off, block_count;
|
|
|
|
|
|
|
|
softc->delete_running = 1;
|
|
|
|
bzero(softc->unmap_buf, sizeof(softc->unmap_buf));
|
|
|
|
bp1 = bp;
|
|
|
|
do {
|
|
|
|
bioq_remove(&softc->delete_queue, bp1);
|
|
|
|
if (bp1 != bp)
|
|
|
|
bioq_insert_tail(&softc->delete_run_queue, bp1);
|
|
|
|
lba = bp1->bio_pblkno;
|
|
|
|
count = bp1->bio_bcount / softc->params.secsize;
|
|
|
|
requestcount = count;
|
|
|
|
|
|
|
|
/* Try to extend the previous range. */
|
|
|
|
if (lba == lastlba) {
|
2015-01-26 15:47:08 +00:00
|
|
|
c = omin(count, ATA_DSM_RANGE_MAX - lastcount);
|
2013-07-12 00:50:25 +00:00
|
|
|
lastcount += c;
|
|
|
|
off = (ranges - 1) * 8;
|
|
|
|
buf[off + 6] = lastcount & 0xff;
|
|
|
|
buf[off + 7] = (lastcount >> 8) & 0xff;
|
|
|
|
count -= c;
|
|
|
|
lba += c;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (count > 0) {
|
2015-01-26 15:47:08 +00:00
|
|
|
c = omin(count, ATA_DSM_RANGE_MAX);
|
2013-07-12 00:50:25 +00:00
|
|
|
off = ranges * 8;
|
|
|
|
|
|
|
|
buf[off + 0] = lba & 0xff;
|
|
|
|
buf[off + 1] = (lba >> 8) & 0xff;
|
|
|
|
buf[off + 2] = (lba >> 16) & 0xff;
|
|
|
|
buf[off + 3] = (lba >> 24) & 0xff;
|
|
|
|
buf[off + 4] = (lba >> 32) & 0xff;
|
|
|
|
buf[off + 5] = (lba >> 40) & 0xff;
|
|
|
|
buf[off + 6] = c & 0xff;
|
|
|
|
buf[off + 7] = (c >> 8) & 0xff;
|
|
|
|
lba += c;
|
|
|
|
ranges++;
|
|
|
|
count -= c;
|
|
|
|
lastcount = c;
|
|
|
|
if (count != 0 && ranges == softc->trim_max_ranges) {
|
|
|
|
xpt_print(periph->path,
|
2014-01-04 17:52:43 +00:00
|
|
|
"%s issuing short delete %ld > %ld\n",
|
2013-07-12 00:50:25 +00:00
|
|
|
da_delete_method_desc[softc->delete_method],
|
|
|
|
requestcount,
|
|
|
|
(softc->trim_max_ranges - ranges) *
|
|
|
|
ATA_DSM_RANGE_MAX);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
lastlba = lba;
|
|
|
|
bp1 = bioq_first(&softc->delete_queue);
|
|
|
|
if (bp1 == NULL || bp1->bio_bcount / softc->params.secsize >
|
|
|
|
(softc->trim_max_ranges - ranges) * ATA_DSM_RANGE_MAX)
|
|
|
|
break;
|
|
|
|
} while (1);
|
|
|
|
|
|
|
|
block_count = (ranges + ATA_DSM_BLK_RANGES - 1) / ATA_DSM_BLK_RANGES;
|
|
|
|
scsi_ata_trim(&ccb->csio,
|
|
|
|
/*retries*/da_retry_count,
|
|
|
|
/*cbfcnp*/dadone,
|
|
|
|
/*tag_action*/MSG_SIMPLE_Q_TAG,
|
|
|
|
block_count,
|
|
|
|
/*data_ptr*/buf,
|
|
|
|
/*dxfer_len*/block_count * ATA_DSM_BLK_SIZE,
|
|
|
|
/*sense_len*/SSD_FULL_SIZE,
|
|
|
|
da_default_timeout * 1000);
|
|
|
|
ccb->ccb_h.ccb_state = DA_CCB_DELETE;
|
Merge CAM locking changes from the projects/camlock branch to radically
reduce lock congestion and improve SMP scalability of the SCSI/ATA stack,
preparing the ground for the coming next GEOM direct dispatch support.
Replace big per-SIM locks with bunch of smaller ones:
- per-LUN locks to protect device and peripheral drivers state;
- per-target locks to protect list of LUNs on target;
- per-bus locks to protect reference counting;
- per-send queue locks to protect queue of CCBs to be sent;
- per-done queue locks to protect queue of completed CCBs;
- remaining per-SIM locks now protect only HBA driver internals.
While holding LUN lock it is allowed (while not recommended for performance
reasons) to take SIM lock. The opposite acquisition order is forbidden.
All the other locks are leaf locks, that can be taken anywhere, but should
not be cascaded. Many functions, such as: xpt_action(), xpt_done(),
xpt_async(), xpt_create_path(), etc. are no longer require (but allow) SIM
lock to be held.
To keep compatibility and solve cases where SIM lock can't be dropped, all
xpt_async() calls in addition to xpt_done() calls are queued to completion
threads for async processing in clean environment without SIM lock held.
Instead of single CAM SWI thread, used for commands completion processing
before, use multiple (depending on number of CPUs) threads. Load balanced
between them using "hash" of the device B:T:L address.
HBA drivers that can drop SIM lock during completion processing and have
sufficient number of completion threads to efficiently scale to multiple
CPUs can use new function xpt_done_direct() to avoid extra context switch.
Make ahci(4) driver to use this mechanism depending on hardware setup.
Sponsored by: iXsystems, Inc.
MFC after: 2 months
2013-10-21 12:00:26 +00:00
|
|
|
ccb->ccb_h.flags |= CAM_UNLOCKED;
|
2013-07-12 00:50:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We calculate ws_max_blks here based off d_delmaxsize instead
|
|
|
|
* of using softc->ws_max_blks as it is absolute max for the
|
2014-01-04 17:52:43 +00:00
|
|
|
* device not the protocol max which may well be lower.
|
2013-07-12 00:50:25 +00:00
|
|
|
*/
|
|
|
|
static void
|
|
|
|
da_delete_ws(struct cam_periph *periph, union ccb *ccb, struct bio *bp)
|
|
|
|
{
|
|
|
|
struct da_softc *softc;
|
|
|
|
struct bio *bp1;
|
|
|
|
uint64_t ws_max_blks;
|
|
|
|
uint64_t lba;
|
|
|
|
uint64_t count; /* forward compat with WS32 */
|
|
|
|
|
|
|
|
softc = (struct da_softc *)periph->softc;
|
|
|
|
ws_max_blks = softc->disk->d_delmaxsize / softc->params.secsize;
|
|
|
|
softc->delete_running = 1;
|
|
|
|
lba = bp->bio_pblkno;
|
|
|
|
count = 0;
|
|
|
|
bp1 = bp;
|
|
|
|
do {
|
|
|
|
bioq_remove(&softc->delete_queue, bp1);
|
|
|
|
if (bp1 != bp)
|
|
|
|
bioq_insert_tail(&softc->delete_run_queue, bp1);
|
|
|
|
count += bp1->bio_bcount / softc->params.secsize;
|
|
|
|
if (count > ws_max_blks) {
|
|
|
|
xpt_print(periph->path,
|
2014-01-04 17:52:43 +00:00
|
|
|
"%s issuing short delete %ld > %ld\n",
|
2013-07-12 00:50:25 +00:00
|
|
|
da_delete_method_desc[softc->delete_method],
|
|
|
|
count, ws_max_blks);
|
2015-01-26 15:47:08 +00:00
|
|
|
count = omin(count, ws_max_blks);
|
2013-07-12 00:50:25 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
bp1 = bioq_first(&softc->delete_queue);
|
|
|
|
if (bp1 == NULL || lba + count != bp1->bio_pblkno ||
|
|
|
|
count + bp1->bio_bcount /
|
|
|
|
softc->params.secsize > ws_max_blks)
|
|
|
|
break;
|
|
|
|
} while (1);
|
|
|
|
|
|
|
|
scsi_write_same(&ccb->csio,
|
|
|
|
/*retries*/da_retry_count,
|
|
|
|
/*cbfcnp*/dadone,
|
|
|
|
/*tag_action*/MSG_SIMPLE_Q_TAG,
|
|
|
|
/*byte2*/softc->delete_method ==
|
|
|
|
DA_DELETE_ZERO ? 0 : SWS_UNMAP,
|
|
|
|
softc->delete_method == DA_DELETE_WS16 ? 16 : 10,
|
|
|
|
/*lba*/lba,
|
|
|
|
/*block_count*/count,
|
|
|
|
/*data_ptr*/ __DECONST(void *, zero_region),
|
|
|
|
/*dxfer_len*/ softc->params.secsize,
|
|
|
|
/*sense_len*/SSD_FULL_SIZE,
|
|
|
|
da_default_timeout * 1000);
|
|
|
|
ccb->ccb_h.ccb_state = DA_CCB_DELETE;
|
Merge CAM locking changes from the projects/camlock branch to radically
reduce lock congestion and improve SMP scalability of the SCSI/ATA stack,
preparing the ground for the coming next GEOM direct dispatch support.
Replace big per-SIM locks with bunch of smaller ones:
- per-LUN locks to protect device and peripheral drivers state;
- per-target locks to protect list of LUNs on target;
- per-bus locks to protect reference counting;
- per-send queue locks to protect queue of CCBs to be sent;
- per-done queue locks to protect queue of completed CCBs;
- remaining per-SIM locks now protect only HBA driver internals.
While holding LUN lock it is allowed (while not recommended for performance
reasons) to take SIM lock. The opposite acquisition order is forbidden.
All the other locks are leaf locks, that can be taken anywhere, but should
not be cascaded. Many functions, such as: xpt_action(), xpt_done(),
xpt_async(), xpt_create_path(), etc. are no longer require (but allow) SIM
lock to be held.
To keep compatibility and solve cases where SIM lock can't be dropped, all
xpt_async() calls in addition to xpt_done() calls are queued to completion
threads for async processing in clean environment without SIM lock held.
Instead of single CAM SWI thread, used for commands completion processing
before, use multiple (depending on number of CPUs) threads. Load balanced
between them using "hash" of the device B:T:L address.
HBA drivers that can drop SIM lock during completion processing and have
sufficient number of completion threads to efficiently scale to multiple
CPUs can use new function xpt_done_direct() to avoid extra context switch.
Make ahci(4) driver to use this mechanism depending on hardware setup.
Sponsored by: iXsystems, Inc.
MFC after: 2 months
2013-10-21 12:00:26 +00:00
|
|
|
ccb->ccb_h.flags |= CAM_UNLOCKED;
|
2013-07-12 00:50:25 +00:00
|
|
|
}
|
|
|
|
|
2002-03-23 18:18:02 +00:00
|
|
|
static int
|
|
|
|
cmd6workaround(union ccb *ccb)
|
|
|
|
{
|
|
|
|
struct scsi_rw_6 cmd6;
|
|
|
|
struct scsi_rw_10 *cmd10;
|
|
|
|
struct da_softc *softc;
|
2002-08-16 22:05:19 +00:00
|
|
|
u_int8_t *cdb;
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
struct bio *bp;
|
2002-08-16 22:05:19 +00:00
|
|
|
int frozen;
|
2002-03-23 18:18:02 +00:00
|
|
|
|
2002-08-16 22:05:19 +00:00
|
|
|
cdb = ccb->csio.cdb_io.cdb_bytes;
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
softc = (struct da_softc *)xpt_path_periph(ccb->ccb_h.path)->softc;
|
|
|
|
|
|
|
|
if (ccb->ccb_h.ccb_state == DA_CCB_DELETE) {
|
2013-04-26 16:17:04 +00:00
|
|
|
da_delete_methods old_method = softc->delete_method;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Typically there are two reasons for failure here
|
|
|
|
* 1. Delete method was detected as supported but isn't
|
|
|
|
* 2. Delete failed due to invalid params e.g. too big
|
|
|
|
*
|
|
|
|
* While we will attempt to choose an alternative delete method
|
|
|
|
* this may result in short deletes if the existing delete
|
|
|
|
* requests from geom are big for the new method choosen.
|
|
|
|
*
|
|
|
|
* This method assumes that the error which triggered this
|
|
|
|
* will not retry the io otherwise a panic will occur
|
|
|
|
*/
|
|
|
|
dadeleteflag(softc, old_method, 0);
|
|
|
|
dadeletemethodchoose(softc, DA_DELETE_DISABLE);
|
|
|
|
if (softc->delete_method == DA_DELETE_DISABLE)
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
xpt_print(ccb->ccb_h.path,
|
2013-04-26 16:17:04 +00:00
|
|
|
"%s failed, disabling BIO_DELETE\n",
|
|
|
|
da_delete_method_desc[old_method]);
|
|
|
|
else
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
xpt_print(ccb->ccb_h.path,
|
2013-04-26 16:17:04 +00:00
|
|
|
"%s failed, switching to %s BIO_DELETE\n",
|
|
|
|
da_delete_method_desc[old_method],
|
|
|
|
da_delete_method_desc[softc->delete_method]);
|
2013-03-29 22:58:15 +00:00
|
|
|
|
2014-06-05 17:13:42 +00:00
|
|
|
while ((bp = bioq_takefirst(&softc->delete_run_queue)) != NULL)
|
|
|
|
bioq_disksort(&softc->delete_queue, bp);
|
|
|
|
bioq_disksort(&softc->delete_queue,
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
(struct bio *)ccb->ccb_h.ccb_bp);
|
|
|
|
ccb->ccb_h.ccb_bp = NULL;
|
|
|
|
return (0);
|
|
|
|
}
|
2002-03-23 18:18:02 +00:00
|
|
|
|
2013-07-27 22:19:34 +00:00
|
|
|
/* Detect unsupported PREVENT ALLOW MEDIUM REMOVAL. */
|
|
|
|
if ((ccb->ccb_h.flags & CAM_CDB_POINTER) == 0 &&
|
|
|
|
(*cdb == PREVENT_ALLOW) &&
|
|
|
|
(softc->quirks & DA_Q_NO_PREVENT) == 0) {
|
|
|
|
if (bootverbose)
|
|
|
|
xpt_print(ccb->ccb_h.path,
|
|
|
|
"PREVENT ALLOW MEDIUM REMOVAL not supported.\n");
|
|
|
|
softc->quirks |= DA_Q_NO_PREVENT;
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Detect unsupported SYNCHRONIZE CACHE(10). */
|
|
|
|
if ((ccb->ccb_h.flags & CAM_CDB_POINTER) == 0 &&
|
|
|
|
(*cdb == SYNCHRONIZE_CACHE) &&
|
|
|
|
(softc->quirks & DA_Q_NO_SYNC_CACHE) == 0) {
|
|
|
|
if (bootverbose)
|
|
|
|
xpt_print(ccb->ccb_h.path,
|
|
|
|
"SYNCHRONIZE CACHE(10) not supported.\n");
|
|
|
|
softc->quirks |= DA_Q_NO_SYNC_CACHE;
|
2013-08-07 08:20:11 +00:00
|
|
|
softc->disk->d_flags &= ~DISKFLAG_CANFLUSHCACHE;
|
2013-07-27 22:19:34 +00:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
2002-08-16 22:05:19 +00:00
|
|
|
/* Translation only possible if CDB is an array and cmd is R/W6 */
|
|
|
|
if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0 ||
|
|
|
|
(*cdb != READ_6 && *cdb != WRITE_6))
|
2002-03-23 18:18:02 +00:00
|
|
|
return 0;
|
|
|
|
|
2006-12-05 07:45:28 +00:00
|
|
|
xpt_print(ccb->ccb_h.path, "READ(6)/WRITE(6) not supported, "
|
|
|
|
"increasing minimum_cmd_size to 10.\n");
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
softc->minimum_cmd_size = 10;
|
2002-03-23 18:18:02 +00:00
|
|
|
|
2002-08-16 22:05:19 +00:00
|
|
|
bcopy(cdb, &cmd6, sizeof(struct scsi_rw_6));
|
|
|
|
cmd10 = (struct scsi_rw_10 *)cdb;
|
2002-03-23 18:18:02 +00:00
|
|
|
cmd10->opcode = (cmd6.opcode == READ_6) ? READ_10 : WRITE_10;
|
|
|
|
cmd10->byte2 = 0;
|
|
|
|
scsi_ulto4b(scsi_3btoul(cmd6.addr), cmd10->addr);
|
|
|
|
cmd10->reserved = 0;
|
|
|
|
scsi_ulto2b(cmd6.length, cmd10->length);
|
|
|
|
cmd10->control = cmd6.control;
|
2002-08-16 22:05:19 +00:00
|
|
|
ccb->csio.cdb_len = sizeof(*cmd10);
|
2002-03-23 18:18:02 +00:00
|
|
|
|
2002-08-16 22:05:19 +00:00
|
|
|
/* Requeue request, unfreezing queue if necessary */
|
|
|
|
frozen = (ccb->ccb_h.status & CAM_DEV_QFRZN) != 0;
|
2002-03-23 18:18:02 +00:00
|
|
|
ccb->ccb_h.status = CAM_REQUEUE_REQ;
|
|
|
|
xpt_action(ccb);
|
2002-08-16 22:05:19 +00:00
|
|
|
if (frozen) {
|
2002-03-23 18:18:02 +00:00
|
|
|
cam_release_devq(ccb->ccb_h.path,
|
|
|
|
/*relsim_flags*/0,
|
|
|
|
/*reduction*/0,
|
|
|
|
/*timeout*/0,
|
|
|
|
/*getcount_only*/0);
|
2002-08-16 22:05:19 +00:00
|
|
|
}
|
2002-03-23 18:18:02 +00:00
|
|
|
return (ERESTART);
|
|
|
|
}
|
1998-09-15 06:36:34 +00:00
|
|
|
|
|
|
|
static void
|
|
|
|
dadone(struct cam_periph *periph, union ccb *done_ccb)
|
|
|
|
{
|
|
|
|
struct da_softc *softc;
|
|
|
|
struct ccb_scsiio *csio;
|
2009-10-31 10:43:38 +00:00
|
|
|
u_int32_t priority;
|
2013-01-11 16:10:11 +00:00
|
|
|
da_ccb_state state;
|
1998-09-15 06:36:34 +00:00
|
|
|
|
|
|
|
softc = (struct da_softc *)periph->softc;
|
2009-10-31 10:43:38 +00:00
|
|
|
priority = done_ccb->ccb_h.pinfo.priority;
|
2012-06-05 09:45:42 +00:00
|
|
|
|
|
|
|
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("dadone\n"));
|
|
|
|
|
1998-09-15 06:36:34 +00:00
|
|
|
csio = &done_ccb->csio;
|
2013-01-11 16:10:11 +00:00
|
|
|
state = csio->ccb_h.ccb_state & DA_CCB_TYPE_MASK;
|
|
|
|
switch (state) {
|
1998-09-15 06:36:34 +00:00
|
|
|
case DA_CCB_BUFFER_IO:
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
case DA_CCB_DELETE:
|
1998-09-15 06:36:34 +00:00
|
|
|
{
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
struct bio *bp, *bp1;
|
1998-09-15 06:36:34 +00:00
|
|
|
|
Merge CAM locking changes from the projects/camlock branch to radically
reduce lock congestion and improve SMP scalability of the SCSI/ATA stack,
preparing the ground for the coming next GEOM direct dispatch support.
Replace big per-SIM locks with bunch of smaller ones:
- per-LUN locks to protect device and peripheral drivers state;
- per-target locks to protect list of LUNs on target;
- per-bus locks to protect reference counting;
- per-send queue locks to protect queue of CCBs to be sent;
- per-done queue locks to protect queue of completed CCBs;
- remaining per-SIM locks now protect only HBA driver internals.
While holding LUN lock it is allowed (while not recommended for performance
reasons) to take SIM lock. The opposite acquisition order is forbidden.
All the other locks are leaf locks, that can be taken anywhere, but should
not be cascaded. Many functions, such as: xpt_action(), xpt_done(),
xpt_async(), xpt_create_path(), etc. are no longer require (but allow) SIM
lock to be held.
To keep compatibility and solve cases where SIM lock can't be dropped, all
xpt_async() calls in addition to xpt_done() calls are queued to completion
threads for async processing in clean environment without SIM lock held.
Instead of single CAM SWI thread, used for commands completion processing
before, use multiple (depending on number of CPUs) threads. Load balanced
between them using "hash" of the device B:T:L address.
HBA drivers that can drop SIM lock during completion processing and have
sufficient number of completion threads to efficiently scale to multiple
CPUs can use new function xpt_done_direct() to avoid extra context switch.
Make ahci(4) driver to use this mechanism depending on hardware setup.
Sponsored by: iXsystems, Inc.
MFC after: 2 months
2013-10-21 12:00:26 +00:00
|
|
|
cam_periph_lock(periph);
|
2000-04-15 05:54:02 +00:00
|
|
|
bp = (struct bio *)done_ccb->ccb_h.ccb_bp;
|
1998-09-15 06:36:34 +00:00
|
|
|
if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
|
|
|
|
int error;
|
|
|
|
int sf;
|
2011-06-14 16:05:00 +00:00
|
|
|
|
1998-09-15 06:36:34 +00:00
|
|
|
if ((csio->ccb_h.ccb_state & DA_CCB_RETRY_UA) != 0)
|
|
|
|
sf = SF_RETRY_UA;
|
|
|
|
else
|
|
|
|
sf = 0;
|
|
|
|
|
Rewrite of the CAM error recovery code.
Some of the major changes include:
- The SCSI error handling portion of cam_periph_error() has
been broken out into a number of subfunctions to better
modularize the code that handles the hierarchy of SCSI errors.
As a result, the code is now much easier to read.
- String handling and error printing has been significantly
revamped. We now use sbufs to do string formatting instead
of using printfs (for the kernel) and snprintf/strncat (for
userland) as before.
There is a new catchall error printing routine,
cam_error_print() and its string-based counterpart,
cam_error_string() that allow the kernel and userland
applications to pass in a CCB and have errors printed out
properly, whether or not they're SCSI errors. Among other
things, this helped eliminate a fair amount of duplicate code
in camcontrol.
We now print out more information than before, including
the CAM status and SCSI status and the error recovery action
taken to remedy the problem.
- sbufs are now available in userland, via libsbuf. This
change was necessary since most of the error printing code
is shared between libcam and the kernel.
- A new transfer settings interface is included in this checkin.
This code is #ifdef'ed out, and is primarily intended to aid
discussion with HBA driver authors on the final form the
interface should take. There is example code in the ahc(4)
driver that implements the HBA driver side of the new
interface. The new transfer settings code won't be enabled
until we're ready to switch all HBA drivers over to the new
interface.
src/Makefile.inc1,
lib/Makefile: Add libsbuf. It must be built before libcam,
since libcam uses sbuf routines.
libcam/Makefile: libcam now depends on libsbuf.
libsbuf/Makefile: Add a makefile for libsbuf. This pulls in the
sbuf sources from sys/kern.
bsd.libnames.mk: Add LIBSBUF.
camcontrol/Makefile: Add -lsbuf. Since camcontrol is statically
linked, we can't depend on the dynamic linker
to pull in libsbuf.
camcontrol.c: Use cam_error_print() instead of checking for
CAM_SCSI_STATUS_ERROR on every failed CCB.
sbuf.9: Change the prototypes for sbuf_cat() and
sbuf_cpy() so that the source string is now a
const char *. This is more in line wth the
standard system string functions, and helps
eliminate warnings when dealing with a const
source buffer.
Fix a typo.
cam.c: Add description strings for the various CAM
error status values, as well as routines to
look up those strings.
Add new cam_error_string() and
cam_error_print() routines for userland and
the kernel.
cam.h: Add a new CAM flag, CAM_RETRY_SELTO.
Add enumerated types for the various options
available with cam_error_print() and
cam_error_string().
cam_ccb.h: Add new transfer negotiation structures/types.
Change inq_len in the ccb_getdev structure to
be "reserved". This field has never been
filled in, and will be removed when we next
bump the CAM version.
cam_debug.h: Fix typo.
cam_periph.c: Modularize cam_periph_error(). The SCSI error
handling part of cam_periph_error() is now
in camperiphscsistatuserror() and
camperiphscsisenseerror().
In cam_periph_lock(), increase the reference
count on the periph while we wait for our lock
attempt to succeed so that the periph won't go
away while we're sleeping.
cam_xpt.c: Add new transfer negotiation code. (ifdefed
out)
Add a new function, xpt_path_string(). This
is a string/sbuf analog to xpt_print_path().
scsi_all.c: Revamp string handing and error printing code.
We now use sbufs for much of the string
formatting code. More of that code is shared
between userland the kernel.
scsi_all.h: Get rid of SS_TURSTART, it wasn't terribly
useful in the first place.
Add a new error action, SS_REQSENSE. (Send a
request sense and then retry the command.)
This is useful when the controller hasn't
performed autosense for some reason.
Change the default actions around a bit.
scsi_cd.c,
scsi_da.c,
scsi_pt.c,
scsi_ses.c: SF_RETRY_SELTO -> CAM_RETRY_SELTO. Selection
timeouts shouldn't be covered by a sense flag.
scsi_pass.[ch]: SF_RETRY_SELTO -> CAM_RETRY_SELTO.
Get rid of the last vestiges of a read/write
interface.
libkern/bsearch.c,
sys/libkern.h,
conf/files: Add bsearch.c, which is needed for some of the
new table lookup routines.
aic7xxx_freebsd.c: Define AHC_NEW_TRAN_SETTINGS if
CAM_NEW_TRAN_CODE is defined.
sbuf.h,
subr_sbuf.c: Add the appropriate #ifdefs so sbufs can
compile and run in userland.
Change sbuf_printf() to use vsnprintf()
instead of kvprintf(), which is only available
in the kernel.
Change the source string for sbuf_cpy() and
sbuf_cat() to be a const char *.
Add __BEGIN_DECLS and __END_DECLS around
function prototypes since they're now exported
to userland.
kdump/mkioctls: Include stdio.h before cam.h since cam.h now
includes a function with a FILE * argument.
Submitted by: gibbs (mostly)
Reviewed by: jdp, marcel (libsbuf makefile changes)
Reviewed by: des (sbuf changes)
Reviewed by: ken
2001-03-27 05:45:52 +00:00
|
|
|
error = daerror(done_ccb, CAM_RETRY_SELTO, sf);
|
|
|
|
if (error == ERESTART) {
|
1998-09-15 06:36:34 +00:00
|
|
|
/*
|
2013-04-26 16:17:04 +00:00
|
|
|
* A retry was scheduled, so
|
1998-09-15 06:36:34 +00:00
|
|
|
* just return.
|
|
|
|
*/
|
Merge CAM locking changes from the projects/camlock branch to radically
reduce lock congestion and improve SMP scalability of the SCSI/ATA stack,
preparing the ground for the coming next GEOM direct dispatch support.
Replace big per-SIM locks with bunch of smaller ones:
- per-LUN locks to protect device and peripheral drivers state;
- per-target locks to protect list of LUNs on target;
- per-bus locks to protect reference counting;
- per-send queue locks to protect queue of CCBs to be sent;
- per-done queue locks to protect queue of completed CCBs;
- remaining per-SIM locks now protect only HBA driver internals.
While holding LUN lock it is allowed (while not recommended for performance
reasons) to take SIM lock. The opposite acquisition order is forbidden.
All the other locks are leaf locks, that can be taken anywhere, but should
not be cascaded. Many functions, such as: xpt_action(), xpt_done(),
xpt_async(), xpt_create_path(), etc. are no longer require (but allow) SIM
lock to be held.
To keep compatibility and solve cases where SIM lock can't be dropped, all
xpt_async() calls in addition to xpt_done() calls are queued to completion
threads for async processing in clean environment without SIM lock held.
Instead of single CAM SWI thread, used for commands completion processing
before, use multiple (depending on number of CPUs) threads. Load balanced
between them using "hash" of the device B:T:L address.
HBA drivers that can drop SIM lock during completion processing and have
sufficient number of completion threads to efficiently scale to multiple
CPUs can use new function xpt_done_direct() to avoid extra context switch.
Make ahci(4) driver to use this mechanism depending on hardware setup.
Sponsored by: iXsystems, Inc.
MFC after: 2 months
2013-10-21 12:00:26 +00:00
|
|
|
cam_periph_unlock(periph);
|
1998-09-15 06:36:34 +00:00
|
|
|
return;
|
|
|
|
}
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
bp = (struct bio *)done_ccb->ccb_h.ccb_bp;
|
1998-09-15 06:36:34 +00:00
|
|
|
if (error != 0) {
|
2011-06-14 16:05:00 +00:00
|
|
|
int queued_error;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* return all queued I/O with EIO, so that
|
|
|
|
* the client can retry these I/Os in the
|
|
|
|
* proper order should it attempt to recover.
|
|
|
|
*/
|
|
|
|
queued_error = EIO;
|
1998-09-15 06:36:34 +00:00
|
|
|
|
2011-06-14 16:05:00 +00:00
|
|
|
if (error == ENXIO
|
|
|
|
&& (softc->flags & DA_FLAG_PACK_INVALID)== 0) {
|
1998-09-15 06:36:34 +00:00
|
|
|
/*
|
|
|
|
* Catastrophic error. Mark our pack as
|
|
|
|
* invalid.
|
|
|
|
*/
|
2006-12-05 07:45:28 +00:00
|
|
|
/*
|
|
|
|
* XXX See if this is really a media
|
|
|
|
* XXX change first?
|
1998-09-15 06:36:34 +00:00
|
|
|
*/
|
2006-12-05 07:45:28 +00:00
|
|
|
xpt_print(periph->path,
|
|
|
|
"Invalidating pack\n");
|
1998-09-15 06:36:34 +00:00
|
|
|
softc->flags |= DA_FLAG_PACK_INVALID;
|
2011-06-14 16:05:00 +00:00
|
|
|
queued_error = ENXIO;
|
1998-09-15 06:36:34 +00:00
|
|
|
}
|
2011-06-14 16:05:00 +00:00
|
|
|
bioq_flush(&softc->bio_queue, NULL,
|
|
|
|
queued_error);
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
if (bp != NULL) {
|
|
|
|
bp->bio_error = error;
|
|
|
|
bp->bio_resid = bp->bio_bcount;
|
|
|
|
bp->bio_flags |= BIO_ERROR;
|
|
|
|
}
|
|
|
|
} else if (bp != NULL) {
|
2013-07-28 19:56:08 +00:00
|
|
|
if (state == DA_CCB_DELETE)
|
|
|
|
bp->bio_resid = 0;
|
|
|
|
else
|
|
|
|
bp->bio_resid = csio->resid;
|
2000-04-15 05:54:02 +00:00
|
|
|
bp->bio_error = 0;
|
2003-08-06 14:24:16 +00:00
|
|
|
if (bp->bio_resid != 0)
|
2000-04-15 05:54:02 +00:00
|
|
|
bp->bio_flags |= BIO_ERROR;
|
1998-09-15 06:36:34 +00:00
|
|
|
}
|
|
|
|
if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
|
|
|
|
cam_release_devq(done_ccb->ccb_h.path,
|
|
|
|
/*relsim_flags*/0,
|
|
|
|
/*reduction*/0,
|
|
|
|
/*timeout*/0,
|
|
|
|
/*getcount_only*/0);
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
} else if (bp != NULL) {
|
Rewrite of the CAM error recovery code.
Some of the major changes include:
- The SCSI error handling portion of cam_periph_error() has
been broken out into a number of subfunctions to better
modularize the code that handles the hierarchy of SCSI errors.
As a result, the code is now much easier to read.
- String handling and error printing has been significantly
revamped. We now use sbufs to do string formatting instead
of using printfs (for the kernel) and snprintf/strncat (for
userland) as before.
There is a new catchall error printing routine,
cam_error_print() and its string-based counterpart,
cam_error_string() that allow the kernel and userland
applications to pass in a CCB and have errors printed out
properly, whether or not they're SCSI errors. Among other
things, this helped eliminate a fair amount of duplicate code
in camcontrol.
We now print out more information than before, including
the CAM status and SCSI status and the error recovery action
taken to remedy the problem.
- sbufs are now available in userland, via libsbuf. This
change was necessary since most of the error printing code
is shared between libcam and the kernel.
- A new transfer settings interface is included in this checkin.
This code is #ifdef'ed out, and is primarily intended to aid
discussion with HBA driver authors on the final form the
interface should take. There is example code in the ahc(4)
driver that implements the HBA driver side of the new
interface. The new transfer settings code won't be enabled
until we're ready to switch all HBA drivers over to the new
interface.
src/Makefile.inc1,
lib/Makefile: Add libsbuf. It must be built before libcam,
since libcam uses sbuf routines.
libcam/Makefile: libcam now depends on libsbuf.
libsbuf/Makefile: Add a makefile for libsbuf. This pulls in the
sbuf sources from sys/kern.
bsd.libnames.mk: Add LIBSBUF.
camcontrol/Makefile: Add -lsbuf. Since camcontrol is statically
linked, we can't depend on the dynamic linker
to pull in libsbuf.
camcontrol.c: Use cam_error_print() instead of checking for
CAM_SCSI_STATUS_ERROR on every failed CCB.
sbuf.9: Change the prototypes for sbuf_cat() and
sbuf_cpy() so that the source string is now a
const char *. This is more in line wth the
standard system string functions, and helps
eliminate warnings when dealing with a const
source buffer.
Fix a typo.
cam.c: Add description strings for the various CAM
error status values, as well as routines to
look up those strings.
Add new cam_error_string() and
cam_error_print() routines for userland and
the kernel.
cam.h: Add a new CAM flag, CAM_RETRY_SELTO.
Add enumerated types for the various options
available with cam_error_print() and
cam_error_string().
cam_ccb.h: Add new transfer negotiation structures/types.
Change inq_len in the ccb_getdev structure to
be "reserved". This field has never been
filled in, and will be removed when we next
bump the CAM version.
cam_debug.h: Fix typo.
cam_periph.c: Modularize cam_periph_error(). The SCSI error
handling part of cam_periph_error() is now
in camperiphscsistatuserror() and
camperiphscsisenseerror().
In cam_periph_lock(), increase the reference
count on the periph while we wait for our lock
attempt to succeed so that the periph won't go
away while we're sleeping.
cam_xpt.c: Add new transfer negotiation code. (ifdefed
out)
Add a new function, xpt_path_string(). This
is a string/sbuf analog to xpt_print_path().
scsi_all.c: Revamp string handing and error printing code.
We now use sbufs for much of the string
formatting code. More of that code is shared
between userland the kernel.
scsi_all.h: Get rid of SS_TURSTART, it wasn't terribly
useful in the first place.
Add a new error action, SS_REQSENSE. (Send a
request sense and then retry the command.)
This is useful when the controller hasn't
performed autosense for some reason.
Change the default actions around a bit.
scsi_cd.c,
scsi_da.c,
scsi_pt.c,
scsi_ses.c: SF_RETRY_SELTO -> CAM_RETRY_SELTO. Selection
timeouts shouldn't be covered by a sense flag.
scsi_pass.[ch]: SF_RETRY_SELTO -> CAM_RETRY_SELTO.
Get rid of the last vestiges of a read/write
interface.
libkern/bsearch.c,
sys/libkern.h,
conf/files: Add bsearch.c, which is needed for some of the
new table lookup routines.
aic7xxx_freebsd.c: Define AHC_NEW_TRAN_SETTINGS if
CAM_NEW_TRAN_CODE is defined.
sbuf.h,
subr_sbuf.c: Add the appropriate #ifdefs so sbufs can
compile and run in userland.
Change sbuf_printf() to use vsnprintf()
instead of kvprintf(), which is only available
in the kernel.
Change the source string for sbuf_cpy() and
sbuf_cat() to be a const char *.
Add __BEGIN_DECLS and __END_DECLS around
function prototypes since they're now exported
to userland.
kdump/mkioctls: Include stdio.h before cam.h since cam.h now
includes a function with a FILE * argument.
Submitted by: gibbs (mostly)
Reviewed by: jdp, marcel (libsbuf makefile changes)
Reviewed by: des (sbuf changes)
Reviewed by: ken
2001-03-27 05:45:52 +00:00
|
|
|
if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
|
|
|
|
panic("REQ_CMP with QFRZN");
|
2013-07-28 19:56:08 +00:00
|
|
|
if (state == DA_CCB_DELETE)
|
|
|
|
bp->bio_resid = 0;
|
|
|
|
else
|
|
|
|
bp->bio_resid = csio->resid;
|
2003-08-06 14:24:16 +00:00
|
|
|
if (csio->resid > 0)
|
2000-04-15 05:54:02 +00:00
|
|
|
bp->bio_flags |= BIO_ERROR;
|
Fix a race condition in CAM peripheral free handling, locking
in the CAM XPT bus traversal code, and a number of other periph level
issues.
cam_periph.h,
cam_periph.c: Modify cam_periph_acquire() to test the CAM_PERIPH_INVALID
flag prior to allowing a reference count to be gained
on a peripheral. Callers of this function will receive
CAM_REQ_CMP_ERR status in the situation of attempting to
reference an invalidated periph. This guarantees that
a peripheral scheduled for a deferred free will not
be accessed during its wait for destruction.
Panic during attempts to drop a reference count on
a peripheral that already has a zero reference count.
In cam_periph_list(), use a local sbuf with SBUF_FIXEDLEN
set so that mallocs do not occur while the xpt topology
lock is held, regardless of the allocation policy of the
passed in sbuf.
Add a new routine, cam_periph_release_locked_buses(),
that can be called when the caller already holds
the CAM topology lock.
Add some extra debugging for duplicate peripheral
allocations in cam_periph_alloc().
Treat CAM_DEV_NOT_THERE much the same as a selection
timeout (AC_LOST_DEVICE is emitted), but forgo retries.
cam_xpt.c: Revamp the way the EDT traversal code does locking
and reference counting. This was broken, since it
assumed that the EDT would not change during
traversal, but that assumption is no longer valid.
So, to prevent devices from going away while we
traverse the EDT, make sure we properly lock
everything and hold references on devices that
we are using.
The two peripheral driver traversal routines should
be examined. xptpdperiphtraverse() holds the
topology lock for the entire time it runs.
xptperiphtraverse() is now locked properly, but
only holds the topology lock while it is traversing
the list, and not while the traversal function is
running.
The bus locking code in xptbustraverse() should
also be revisited at a later time, since it is
complex and should probably be simplified.
scsi_da.c: Pay attention to the return value from cam_periph_acquire().
Return 0 always from daclose() even if the disk is now gone.
Add some rudimentary error injection support.
scsi_sg.c: Fix reference counting in the sg(4) driver.
The sg driver was calling cam_periph_release() on close,
but never called cam_periph_acquire() (which increments
the reference count) on open.
The periph code correctly complained that the sg(4)
driver was trying to decrement the refcount when it
was already 0.
Sponsored by: Spectra Logic
MFC after: 2 weeks
2012-01-12 00:41:48 +00:00
|
|
|
if (softc->error_inject != 0) {
|
|
|
|
bp->bio_error = softc->error_inject;
|
|
|
|
bp->bio_resid = bp->bio_bcount;
|
|
|
|
bp->bio_flags |= BIO_ERROR;
|
|
|
|
softc->error_inject = 0;
|
|
|
|
}
|
1998-09-15 06:36:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
LIST_REMOVE(&done_ccb->ccb_h, periph_links.le);
|
2013-10-24 14:05:44 +00:00
|
|
|
if (LIST_EMPTY(&softc->pending_ccbs))
|
|
|
|
softc->flags |= DA_FLAG_WAS_OTAG;
|
1998-09-15 06:36:34 +00:00
|
|
|
|
Merge CAM locking changes from the projects/camlock branch to radically
reduce lock congestion and improve SMP scalability of the SCSI/ATA stack,
preparing the ground for the coming next GEOM direct dispatch support.
Replace big per-SIM locks with bunch of smaller ones:
- per-LUN locks to protect device and peripheral drivers state;
- per-target locks to protect list of LUNs on target;
- per-bus locks to protect reference counting;
- per-send queue locks to protect queue of CCBs to be sent;
- per-done queue locks to protect queue of completed CCBs;
- remaining per-SIM locks now protect only HBA driver internals.
While holding LUN lock it is allowed (while not recommended for performance
reasons) to take SIM lock. The opposite acquisition order is forbidden.
All the other locks are leaf locks, that can be taken anywhere, but should
not be cascaded. Many functions, such as: xpt_action(), xpt_done(),
xpt_async(), xpt_create_path(), etc. are no longer require (but allow) SIM
lock to be held.
To keep compatibility and solve cases where SIM lock can't be dropped, all
xpt_async() calls in addition to xpt_done() calls are queued to completion
threads for async processing in clean environment without SIM lock held.
Instead of single CAM SWI thread, used for commands completion processing
before, use multiple (depending on number of CPUs) threads. Load balanced
between them using "hash" of the device B:T:L address.
HBA drivers that can drop SIM lock during completion processing and have
sufficient number of completion threads to efficiently scale to multiple
CPUs can use new function xpt_done_direct() to avoid extra context switch.
Make ahci(4) driver to use this mechanism depending on hardware setup.
Sponsored by: iXsystems, Inc.
MFC after: 2 months
2013-10-21 12:00:26 +00:00
|
|
|
xpt_release_ccb(done_ccb);
|
2013-01-11 16:10:11 +00:00
|
|
|
if (state == DA_CCB_DELETE) {
|
Merge CAM locking changes from the projects/camlock branch to radically
reduce lock congestion and improve SMP scalability of the SCSI/ATA stack,
preparing the ground for the coming next GEOM direct dispatch support.
Replace big per-SIM locks with bunch of smaller ones:
- per-LUN locks to protect device and peripheral drivers state;
- per-target locks to protect list of LUNs on target;
- per-bus locks to protect reference counting;
- per-send queue locks to protect queue of CCBs to be sent;
- per-done queue locks to protect queue of completed CCBs;
- remaining per-SIM locks now protect only HBA driver internals.
While holding LUN lock it is allowed (while not recommended for performance
reasons) to take SIM lock. The opposite acquisition order is forbidden.
All the other locks are leaf locks, that can be taken anywhere, but should
not be cascaded. Many functions, such as: xpt_action(), xpt_done(),
xpt_async(), xpt_create_path(), etc. are no longer require (but allow) SIM
lock to be held.
To keep compatibility and solve cases where SIM lock can't be dropped, all
xpt_async() calls in addition to xpt_done() calls are queued to completion
threads for async processing in clean environment without SIM lock held.
Instead of single CAM SWI thread, used for commands completion processing
before, use multiple (depending on number of CPUs) threads. Load balanced
between them using "hash" of the device B:T:L address.
HBA drivers that can drop SIM lock during completion processing and have
sufficient number of completion threads to efficiently scale to multiple
CPUs can use new function xpt_done_direct() to avoid extra context switch.
Make ahci(4) driver to use this mechanism depending on hardware setup.
Sponsored by: iXsystems, Inc.
MFC after: 2 months
2013-10-21 12:00:26 +00:00
|
|
|
TAILQ_HEAD(, bio) queue;
|
|
|
|
|
|
|
|
TAILQ_INIT(&queue);
|
|
|
|
TAILQ_CONCAT(&queue, &softc->delete_run_queue.queue, bio_queue);
|
|
|
|
softc->delete_run_queue.insert_point = NULL;
|
2015-01-13 00:20:35 +00:00
|
|
|
/*
|
|
|
|
* Normally, the xpt_release_ccb() above would make sure
|
|
|
|
* that when we have more work to do, that work would
|
|
|
|
* get kicked off. However, we specifically keep
|
|
|
|
* delete_running set to 0 before the call above to
|
|
|
|
* allow other I/O to progress when many BIO_DELETE
|
|
|
|
* requests are pushed down. We set delete_running to 0
|
|
|
|
* and call daschedule again so that we don't stall if
|
|
|
|
* there are no other I/Os pending apart from BIO_DELETEs.
|
|
|
|
*/
|
Merge CAM locking changes from the projects/camlock branch to radically
reduce lock congestion and improve SMP scalability of the SCSI/ATA stack,
preparing the ground for the coming next GEOM direct dispatch support.
Replace big per-SIM locks with bunch of smaller ones:
- per-LUN locks to protect device and peripheral drivers state;
- per-target locks to protect list of LUNs on target;
- per-bus locks to protect reference counting;
- per-send queue locks to protect queue of CCBs to be sent;
- per-done queue locks to protect queue of completed CCBs;
- remaining per-SIM locks now protect only HBA driver internals.
While holding LUN lock it is allowed (while not recommended for performance
reasons) to take SIM lock. The opposite acquisition order is forbidden.
All the other locks are leaf locks, that can be taken anywhere, but should
not be cascaded. Many functions, such as: xpt_action(), xpt_done(),
xpt_async(), xpt_create_path(), etc. are no longer require (but allow) SIM
lock to be held.
To keep compatibility and solve cases where SIM lock can't be dropped, all
xpt_async() calls in addition to xpt_done() calls are queued to completion
threads for async processing in clean environment without SIM lock held.
Instead of single CAM SWI thread, used for commands completion processing
before, use multiple (depending on number of CPUs) threads. Load balanced
between them using "hash" of the device B:T:L address.
HBA drivers that can drop SIM lock during completion processing and have
sufficient number of completion threads to efficiently scale to multiple
CPUs can use new function xpt_done_direct() to avoid extra context switch.
Make ahci(4) driver to use this mechanism depending on hardware setup.
Sponsored by: iXsystems, Inc.
MFC after: 2 months
2013-10-21 12:00:26 +00:00
|
|
|
softc->delete_running = 0;
|
|
|
|
daschedule(periph);
|
|
|
|
cam_periph_unlock(periph);
|
|
|
|
while ((bp1 = TAILQ_FIRST(&queue)) != NULL) {
|
|
|
|
TAILQ_REMOVE(&queue, bp1, bio_queue);
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
bp1->bio_error = bp->bio_error;
|
2013-07-28 19:56:08 +00:00
|
|
|
if (bp->bio_flags & BIO_ERROR) {
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
bp1->bio_flags |= BIO_ERROR;
|
2013-07-28 19:56:08 +00:00
|
|
|
bp1->bio_resid = bp1->bio_bcount;
|
|
|
|
} else
|
|
|
|
bp1->bio_resid = 0;
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
biodone(bp1);
|
|
|
|
}
|
Merge CAM locking changes from the projects/camlock branch to radically
reduce lock congestion and improve SMP scalability of the SCSI/ATA stack,
preparing the ground for the coming next GEOM direct dispatch support.
Replace big per-SIM locks with bunch of smaller ones:
- per-LUN locks to protect device and peripheral drivers state;
- per-target locks to protect list of LUNs on target;
- per-bus locks to protect reference counting;
- per-send queue locks to protect queue of CCBs to be sent;
- per-done queue locks to protect queue of completed CCBs;
- remaining per-SIM locks now protect only HBA driver internals.
While holding LUN lock it is allowed (while not recommended for performance
reasons) to take SIM lock. The opposite acquisition order is forbidden.
All the other locks are leaf locks, that can be taken anywhere, but should
not be cascaded. Many functions, such as: xpt_action(), xpt_done(),
xpt_async(), xpt_create_path(), etc. are no longer require (but allow) SIM
lock to be held.
To keep compatibility and solve cases where SIM lock can't be dropped, all
xpt_async() calls in addition to xpt_done() calls are queued to completion
threads for async processing in clean environment without SIM lock held.
Instead of single CAM SWI thread, used for commands completion processing
before, use multiple (depending on number of CPUs) threads. Load balanced
between them using "hash" of the device B:T:L address.
HBA drivers that can drop SIM lock during completion processing and have
sufficient number of completion threads to efficiently scale to multiple
CPUs can use new function xpt_done_direct() to avoid extra context switch.
Make ahci(4) driver to use this mechanism depending on hardware setup.
Sponsored by: iXsystems, Inc.
MFC after: 2 months
2013-10-21 12:00:26 +00:00
|
|
|
} else
|
|
|
|
cam_periph_unlock(periph);
|
|
|
|
if (bp != NULL)
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
biodone(bp);
|
Merge CAM locking changes from the projects/camlock branch to radically
reduce lock congestion and improve SMP scalability of the SCSI/ATA stack,
preparing the ground for the coming next GEOM direct dispatch support.
Replace big per-SIM locks with bunch of smaller ones:
- per-LUN locks to protect device and peripheral drivers state;
- per-target locks to protect list of LUNs on target;
- per-bus locks to protect reference counting;
- per-send queue locks to protect queue of CCBs to be sent;
- per-done queue locks to protect queue of completed CCBs;
- remaining per-SIM locks now protect only HBA driver internals.
While holding LUN lock it is allowed (while not recommended for performance
reasons) to take SIM lock. The opposite acquisition order is forbidden.
All the other locks are leaf locks, that can be taken anywhere, but should
not be cascaded. Many functions, such as: xpt_action(), xpt_done(),
xpt_async(), xpt_create_path(), etc. are no longer require (but allow) SIM
lock to be held.
To keep compatibility and solve cases where SIM lock can't be dropped, all
xpt_async() calls in addition to xpt_done() calls are queued to completion
threads for async processing in clean environment without SIM lock held.
Instead of single CAM SWI thread, used for commands completion processing
before, use multiple (depending on number of CPUs) threads. Load balanced
between them using "hash" of the device B:T:L address.
HBA drivers that can drop SIM lock during completion processing and have
sufficient number of completion threads to efficiently scale to multiple
CPUs can use new function xpt_done_direct() to avoid extra context switch.
Make ahci(4) driver to use this mechanism depending on hardware setup.
Sponsored by: iXsystems, Inc.
MFC after: 2 months
2013-10-21 12:00:26 +00:00
|
|
|
return;
|
1998-09-15 06:36:34 +00:00
|
|
|
}
|
2013-04-26 16:17:04 +00:00
|
|
|
case DA_CCB_PROBE_RC:
|
|
|
|
case DA_CCB_PROBE_RC16:
|
1998-09-15 06:36:34 +00:00
|
|
|
{
|
|
|
|
struct scsi_read_capacity_data *rdcap;
|
Add support to CAM for devices with more than 2^32 blocks. (2TB if you're
using 512 byte blocks).
cam_ccb.h: Bump up volume_size and cylinders in ccb_calc_geometry to
64 bits and 32 bits respectively, so we can hold larger
device sizes. cylinders would overflow at about 500GB.
Bump CAM_VERSION for this change. Note that this will
require a recompile of all applications that talk to the
pass(4) driver.
scsi_all.c: Add descriptions for READ/WRITE(16), update READ/WRITE(12)
descriptions, add descriptions for SERVICE ACTION IN/OUT.
Add a new function, scsi_read_capacity_16(), that issues
the read capacity service action. (Necessary for arrays
larger than 2^32 sectors.) Update scsi_read_write() to use
a 64 bit LBA and issue READ(16) or WRITE(16) if necessary.
NOTE the API change. This should be largely transparnet
to most userland applications at compile time, but will
break binary compatibility. The CAM_VERSION bump, above,
also serves the purpose of forcing a recompile for any
applications that talk to CAM.
scsi_all.h: Add 16 byte READ/WRITE structures, structures for 16 byte
READ CAPACITY/SERVICE ACTION IN. Add scsi_u64to8b() and
scsi_8btou64.
scsi_da.c: The da(4) driver probe now has two stages for devices
larger than 2TB. If a standard READ CAPACITY(10) returns
0xffffffff, we issue the 16 byte version of read capacity
to determine the true array capacity. We also do the same
thing in daopen() -- use the 16 byte read capacity if the
device is large enough.
The sysctl/loader code has also been updated to accept
16 bytes as a minimum command size.
2003-04-30 00:35:22 +00:00
|
|
|
struct scsi_read_capacity_data_long *rcaplong;
|
1998-09-15 06:36:34 +00:00
|
|
|
char announce_buf[80];
|
2013-04-26 16:17:04 +00:00
|
|
|
int lbp;
|
1998-09-15 06:36:34 +00:00
|
|
|
|
2013-04-26 16:17:04 +00:00
|
|
|
lbp = 0;
|
Add support to CAM for devices with more than 2^32 blocks. (2TB if you're
using 512 byte blocks).
cam_ccb.h: Bump up volume_size and cylinders in ccb_calc_geometry to
64 bits and 32 bits respectively, so we can hold larger
device sizes. cylinders would overflow at about 500GB.
Bump CAM_VERSION for this change. Note that this will
require a recompile of all applications that talk to the
pass(4) driver.
scsi_all.c: Add descriptions for READ/WRITE(16), update READ/WRITE(12)
descriptions, add descriptions for SERVICE ACTION IN/OUT.
Add a new function, scsi_read_capacity_16(), that issues
the read capacity service action. (Necessary for arrays
larger than 2^32 sectors.) Update scsi_read_write() to use
a 64 bit LBA and issue READ(16) or WRITE(16) if necessary.
NOTE the API change. This should be largely transparnet
to most userland applications at compile time, but will
break binary compatibility. The CAM_VERSION bump, above,
also serves the purpose of forcing a recompile for any
applications that talk to CAM.
scsi_all.h: Add 16 byte READ/WRITE structures, structures for 16 byte
READ CAPACITY/SERVICE ACTION IN. Add scsi_u64to8b() and
scsi_8btou64.
scsi_da.c: The da(4) driver probe now has two stages for devices
larger than 2TB. If a standard READ CAPACITY(10) returns
0xffffffff, we issue the 16 byte version of read capacity
to determine the true array capacity. We also do the same
thing in daopen() -- use the 16 byte read capacity if the
device is large enough.
The sysctl/loader code has also been updated to accept
16 bytes as a minimum command size.
2003-04-30 00:35:22 +00:00
|
|
|
rdcap = NULL;
|
|
|
|
rcaplong = NULL;
|
2013-04-26 16:17:04 +00:00
|
|
|
if (state == DA_CCB_PROBE_RC)
|
Add support to CAM for devices with more than 2^32 blocks. (2TB if you're
using 512 byte blocks).
cam_ccb.h: Bump up volume_size and cylinders in ccb_calc_geometry to
64 bits and 32 bits respectively, so we can hold larger
device sizes. cylinders would overflow at about 500GB.
Bump CAM_VERSION for this change. Note that this will
require a recompile of all applications that talk to the
pass(4) driver.
scsi_all.c: Add descriptions for READ/WRITE(16), update READ/WRITE(12)
descriptions, add descriptions for SERVICE ACTION IN/OUT.
Add a new function, scsi_read_capacity_16(), that issues
the read capacity service action. (Necessary for arrays
larger than 2^32 sectors.) Update scsi_read_write() to use
a 64 bit LBA and issue READ(16) or WRITE(16) if necessary.
NOTE the API change. This should be largely transparnet
to most userland applications at compile time, but will
break binary compatibility. The CAM_VERSION bump, above,
also serves the purpose of forcing a recompile for any
applications that talk to CAM.
scsi_all.h: Add 16 byte READ/WRITE structures, structures for 16 byte
READ CAPACITY/SERVICE ACTION IN. Add scsi_u64to8b() and
scsi_8btou64.
scsi_da.c: The da(4) driver probe now has two stages for devices
larger than 2TB. If a standard READ CAPACITY(10) returns
0xffffffff, we issue the 16 byte version of read capacity
to determine the true array capacity. We also do the same
thing in daopen() -- use the 16 byte read capacity if the
device is large enough.
The sysctl/loader code has also been updated to accept
16 bytes as a minimum command size.
2003-04-30 00:35:22 +00:00
|
|
|
rdcap =(struct scsi_read_capacity_data *)csio->data_ptr;
|
|
|
|
else
|
|
|
|
rcaplong = (struct scsi_read_capacity_data_long *)
|
|
|
|
csio->data_ptr;
|
|
|
|
|
1998-09-15 06:36:34 +00:00
|
|
|
if ((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
|
|
|
|
struct disk_params *dp;
|
Add support to CAM for devices with more than 2^32 blocks. (2TB if you're
using 512 byte blocks).
cam_ccb.h: Bump up volume_size and cylinders in ccb_calc_geometry to
64 bits and 32 bits respectively, so we can hold larger
device sizes. cylinders would overflow at about 500GB.
Bump CAM_VERSION for this change. Note that this will
require a recompile of all applications that talk to the
pass(4) driver.
scsi_all.c: Add descriptions for READ/WRITE(16), update READ/WRITE(12)
descriptions, add descriptions for SERVICE ACTION IN/OUT.
Add a new function, scsi_read_capacity_16(), that issues
the read capacity service action. (Necessary for arrays
larger than 2^32 sectors.) Update scsi_read_write() to use
a 64 bit LBA and issue READ(16) or WRITE(16) if necessary.
NOTE the API change. This should be largely transparnet
to most userland applications at compile time, but will
break binary compatibility. The CAM_VERSION bump, above,
also serves the purpose of forcing a recompile for any
applications that talk to CAM.
scsi_all.h: Add 16 byte READ/WRITE structures, structures for 16 byte
READ CAPACITY/SERVICE ACTION IN. Add scsi_u64to8b() and
scsi_8btou64.
scsi_da.c: The da(4) driver probe now has two stages for devices
larger than 2TB. If a standard READ CAPACITY(10) returns
0xffffffff, we issue the 16 byte version of read capacity
to determine the true array capacity. We also do the same
thing in daopen() -- use the 16 byte read capacity if the
device is large enough.
The sysctl/loader code has also been updated to accept
16 bytes as a minimum command size.
2003-04-30 00:35:22 +00:00
|
|
|
uint32_t block_size;
|
|
|
|
uint64_t maxsector;
|
2011-12-23 19:12:02 +00:00
|
|
|
u_int lalba; /* Lowest aligned LBA. */
|
Add support to CAM for devices with more than 2^32 blocks. (2TB if you're
using 512 byte blocks).
cam_ccb.h: Bump up volume_size and cylinders in ccb_calc_geometry to
64 bits and 32 bits respectively, so we can hold larger
device sizes. cylinders would overflow at about 500GB.
Bump CAM_VERSION for this change. Note that this will
require a recompile of all applications that talk to the
pass(4) driver.
scsi_all.c: Add descriptions for READ/WRITE(16), update READ/WRITE(12)
descriptions, add descriptions for SERVICE ACTION IN/OUT.
Add a new function, scsi_read_capacity_16(), that issues
the read capacity service action. (Necessary for arrays
larger than 2^32 sectors.) Update scsi_read_write() to use
a 64 bit LBA and issue READ(16) or WRITE(16) if necessary.
NOTE the API change. This should be largely transparnet
to most userland applications at compile time, but will
break binary compatibility. The CAM_VERSION bump, above,
also serves the purpose of forcing a recompile for any
applications that talk to CAM.
scsi_all.h: Add 16 byte READ/WRITE structures, structures for 16 byte
READ CAPACITY/SERVICE ACTION IN. Add scsi_u64to8b() and
scsi_8btou64.
scsi_da.c: The da(4) driver probe now has two stages for devices
larger than 2TB. If a standard READ CAPACITY(10) returns
0xffffffff, we issue the 16 byte version of read capacity
to determine the true array capacity. We also do the same
thing in daopen() -- use the 16 byte read capacity if the
device is large enough.
The sysctl/loader code has also been updated to accept
16 bytes as a minimum command size.
2003-04-30 00:35:22 +00:00
|
|
|
|
2013-04-26 16:17:04 +00:00
|
|
|
if (state == DA_CCB_PROBE_RC) {
|
Add support to CAM for devices with more than 2^32 blocks. (2TB if you're
using 512 byte blocks).
cam_ccb.h: Bump up volume_size and cylinders in ccb_calc_geometry to
64 bits and 32 bits respectively, so we can hold larger
device sizes. cylinders would overflow at about 500GB.
Bump CAM_VERSION for this change. Note that this will
require a recompile of all applications that talk to the
pass(4) driver.
scsi_all.c: Add descriptions for READ/WRITE(16), update READ/WRITE(12)
descriptions, add descriptions for SERVICE ACTION IN/OUT.
Add a new function, scsi_read_capacity_16(), that issues
the read capacity service action. (Necessary for arrays
larger than 2^32 sectors.) Update scsi_read_write() to use
a 64 bit LBA and issue READ(16) or WRITE(16) if necessary.
NOTE the API change. This should be largely transparnet
to most userland applications at compile time, but will
break binary compatibility. The CAM_VERSION bump, above,
also serves the purpose of forcing a recompile for any
applications that talk to CAM.
scsi_all.h: Add 16 byte READ/WRITE structures, structures for 16 byte
READ CAPACITY/SERVICE ACTION IN. Add scsi_u64to8b() and
scsi_8btou64.
scsi_da.c: The da(4) driver probe now has two stages for devices
larger than 2TB. If a standard READ CAPACITY(10) returns
0xffffffff, we issue the 16 byte version of read capacity
to determine the true array capacity. We also do the same
thing in daopen() -- use the 16 byte read capacity if the
device is large enough.
The sysctl/loader code has also been updated to accept
16 bytes as a minimum command size.
2003-04-30 00:35:22 +00:00
|
|
|
block_size = scsi_4btoul(rdcap->length);
|
|
|
|
maxsector = scsi_4btoul(rdcap->addr);
|
2011-12-23 19:12:02 +00:00
|
|
|
lalba = 0;
|
1998-09-15 06:36:34 +00:00
|
|
|
|
Add support to CAM for devices with more than 2^32 blocks. (2TB if you're
using 512 byte blocks).
cam_ccb.h: Bump up volume_size and cylinders in ccb_calc_geometry to
64 bits and 32 bits respectively, so we can hold larger
device sizes. cylinders would overflow at about 500GB.
Bump CAM_VERSION for this change. Note that this will
require a recompile of all applications that talk to the
pass(4) driver.
scsi_all.c: Add descriptions for READ/WRITE(16), update READ/WRITE(12)
descriptions, add descriptions for SERVICE ACTION IN/OUT.
Add a new function, scsi_read_capacity_16(), that issues
the read capacity service action. (Necessary for arrays
larger than 2^32 sectors.) Update scsi_read_write() to use
a 64 bit LBA and issue READ(16) or WRITE(16) if necessary.
NOTE the API change. This should be largely transparnet
to most userland applications at compile time, but will
break binary compatibility. The CAM_VERSION bump, above,
also serves the purpose of forcing a recompile for any
applications that talk to CAM.
scsi_all.h: Add 16 byte READ/WRITE structures, structures for 16 byte
READ CAPACITY/SERVICE ACTION IN. Add scsi_u64to8b() and
scsi_8btou64.
scsi_da.c: The da(4) driver probe now has two stages for devices
larger than 2TB. If a standard READ CAPACITY(10) returns
0xffffffff, we issue the 16 byte version of read capacity
to determine the true array capacity. We also do the same
thing in daopen() -- use the 16 byte read capacity if the
device is large enough.
The sysctl/loader code has also been updated to accept
16 bytes as a minimum command size.
2003-04-30 00:35:22 +00:00
|
|
|
/*
|
|
|
|
* According to SBC-2, if the standard 10
|
|
|
|
* byte READ CAPACITY command returns 2^32,
|
|
|
|
* we should issue the 16 byte version of
|
|
|
|
* the command, since the device in question
|
|
|
|
* has more sectors than can be represented
|
|
|
|
* with the short version of the command.
|
|
|
|
*/
|
|
|
|
if (maxsector == 0xffffffff) {
|
2007-05-14 21:48:53 +00:00
|
|
|
free(rdcap, M_SCSIDA);
|
Add support to CAM for devices with more than 2^32 blocks. (2TB if you're
using 512 byte blocks).
cam_ccb.h: Bump up volume_size and cylinders in ccb_calc_geometry to
64 bits and 32 bits respectively, so we can hold larger
device sizes. cylinders would overflow at about 500GB.
Bump CAM_VERSION for this change. Note that this will
require a recompile of all applications that talk to the
pass(4) driver.
scsi_all.c: Add descriptions for READ/WRITE(16), update READ/WRITE(12)
descriptions, add descriptions for SERVICE ACTION IN/OUT.
Add a new function, scsi_read_capacity_16(), that issues
the read capacity service action. (Necessary for arrays
larger than 2^32 sectors.) Update scsi_read_write() to use
a 64 bit LBA and issue READ(16) or WRITE(16) if necessary.
NOTE the API change. This should be largely transparnet
to most userland applications at compile time, but will
break binary compatibility. The CAM_VERSION bump, above,
also serves the purpose of forcing a recompile for any
applications that talk to CAM.
scsi_all.h: Add 16 byte READ/WRITE structures, structures for 16 byte
READ CAPACITY/SERVICE ACTION IN. Add scsi_u64to8b() and
scsi_8btou64.
scsi_da.c: The da(4) driver probe now has two stages for devices
larger than 2TB. If a standard READ CAPACITY(10) returns
0xffffffff, we issue the 16 byte version of read capacity
to determine the true array capacity. We also do the same
thing in daopen() -- use the 16 byte read capacity if the
device is large enough.
The sysctl/loader code has also been updated to accept
16 bytes as a minimum command size.
2003-04-30 00:35:22 +00:00
|
|
|
xpt_release_ccb(done_ccb);
|
2013-05-02 14:14:57 +00:00
|
|
|
softc->state = DA_STATE_PROBE_RC16;
|
2009-10-31 10:43:38 +00:00
|
|
|
xpt_schedule(periph, priority);
|
2003-05-03 00:21:40 +00:00
|
|
|
return;
|
Add support to CAM for devices with more than 2^32 blocks. (2TB if you're
using 512 byte blocks).
cam_ccb.h: Bump up volume_size and cylinders in ccb_calc_geometry to
64 bits and 32 bits respectively, so we can hold larger
device sizes. cylinders would overflow at about 500GB.
Bump CAM_VERSION for this change. Note that this will
require a recompile of all applications that talk to the
pass(4) driver.
scsi_all.c: Add descriptions for READ/WRITE(16), update READ/WRITE(12)
descriptions, add descriptions for SERVICE ACTION IN/OUT.
Add a new function, scsi_read_capacity_16(), that issues
the read capacity service action. (Necessary for arrays
larger than 2^32 sectors.) Update scsi_read_write() to use
a 64 bit LBA and issue READ(16) or WRITE(16) if necessary.
NOTE the API change. This should be largely transparnet
to most userland applications at compile time, but will
break binary compatibility. The CAM_VERSION bump, above,
also serves the purpose of forcing a recompile for any
applications that talk to CAM.
scsi_all.h: Add 16 byte READ/WRITE structures, structures for 16 byte
READ CAPACITY/SERVICE ACTION IN. Add scsi_u64to8b() and
scsi_8btou64.
scsi_da.c: The da(4) driver probe now has two stages for devices
larger than 2TB. If a standard READ CAPACITY(10) returns
0xffffffff, we issue the 16 byte version of read capacity
to determine the true array capacity. We also do the same
thing in daopen() -- use the 16 byte read capacity if the
device is large enough.
The sysctl/loader code has also been updated to accept
16 bytes as a minimum command size.
2003-04-30 00:35:22 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
block_size = scsi_4btoul(rcaplong->length);
|
|
|
|
maxsector = scsi_8btou64(rcaplong->addr);
|
2011-12-23 19:12:02 +00:00
|
|
|
lalba = scsi_2btoul(rcaplong->lalba_lbp);
|
Add support to CAM for devices with more than 2^32 blocks. (2TB if you're
using 512 byte blocks).
cam_ccb.h: Bump up volume_size and cylinders in ccb_calc_geometry to
64 bits and 32 bits respectively, so we can hold larger
device sizes. cylinders would overflow at about 500GB.
Bump CAM_VERSION for this change. Note that this will
require a recompile of all applications that talk to the
pass(4) driver.
scsi_all.c: Add descriptions for READ/WRITE(16), update READ/WRITE(12)
descriptions, add descriptions for SERVICE ACTION IN/OUT.
Add a new function, scsi_read_capacity_16(), that issues
the read capacity service action. (Necessary for arrays
larger than 2^32 sectors.) Update scsi_read_write() to use
a 64 bit LBA and issue READ(16) or WRITE(16) if necessary.
NOTE the API change. This should be largely transparnet
to most userland applications at compile time, but will
break binary compatibility. The CAM_VERSION bump, above,
also serves the purpose of forcing a recompile for any
applications that talk to CAM.
scsi_all.h: Add 16 byte READ/WRITE structures, structures for 16 byte
READ CAPACITY/SERVICE ACTION IN. Add scsi_u64to8b() and
scsi_8btou64.
scsi_da.c: The da(4) driver probe now has two stages for devices
larger than 2TB. If a standard READ CAPACITY(10) returns
0xffffffff, we issue the 16 byte version of read capacity
to determine the true array capacity. We also do the same
thing in daopen() -- use the 16 byte read capacity if the
device is large enough.
The sysctl/loader code has also been updated to accept
16 bytes as a minimum command size.
2003-04-30 00:35:22 +00:00
|
|
|
}
|
2006-09-16 21:21:07 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Because GEOM code just will panic us if we
|
|
|
|
* give them an 'illegal' value we'll avoid that
|
|
|
|
* here.
|
|
|
|
*/
|
2015-01-19 07:29:07 +00:00
|
|
|
if (block_size == 0) {
|
2015-01-08 15:10:25 +00:00
|
|
|
block_size = 512;
|
2015-01-19 07:29:07 +00:00
|
|
|
if (maxsector == 0)
|
|
|
|
maxsector = -1;
|
2013-05-03 11:53:06 +00:00
|
|
|
}
|
2015-01-08 15:10:25 +00:00
|
|
|
if (block_size >= MAXPHYS) {
|
2006-12-05 07:45:28 +00:00
|
|
|
xpt_print(periph->path,
|
|
|
|
"unsupportable block size %ju\n",
|
|
|
|
(uintmax_t) block_size);
|
2006-09-16 21:21:07 +00:00
|
|
|
announce_buf[0] = '\0';
|
|
|
|
cam_periph_invalidate(periph);
|
|
|
|
} else {
|
2012-01-26 18:09:28 +00:00
|
|
|
/*
|
|
|
|
* We pass rcaplong into dasetgeom(),
|
|
|
|
* because it will only use it if it is
|
|
|
|
* non-NULL.
|
|
|
|
*/
|
2011-12-23 19:12:02 +00:00
|
|
|
dasetgeom(periph, block_size, maxsector,
|
2012-01-26 18:09:28 +00:00
|
|
|
rcaplong, sizeof(*rcaplong));
|
2013-04-26 16:17:04 +00:00
|
|
|
lbp = (lalba & SRC16_LBPME_A);
|
2006-09-16 21:21:07 +00:00
|
|
|
dp = &softc->params;
|
|
|
|
snprintf(announce_buf, sizeof(announce_buf),
|
2015-10-11 13:48:20 +00:00
|
|
|
"%juMB (%ju %u byte sectors)",
|
|
|
|
((uintmax_t)dp->secsize * dp->sectors) /
|
|
|
|
(1024 * 1024),
|
|
|
|
(uintmax_t)dp->sectors, dp->secsize);
|
2006-09-16 21:21:07 +00:00
|
|
|
}
|
1998-09-15 06:36:34 +00:00
|
|
|
} else {
|
|
|
|
int error;
|
|
|
|
|
1999-08-15 23:34:40 +00:00
|
|
|
announce_buf[0] = '\0';
|
|
|
|
|
1998-09-15 06:36:34 +00:00
|
|
|
/*
|
|
|
|
* Retry any UNIT ATTENTION type errors. They
|
|
|
|
* are expected at boot.
|
|
|
|
*/
|
Rewrite of the CAM error recovery code.
Some of the major changes include:
- The SCSI error handling portion of cam_periph_error() has
been broken out into a number of subfunctions to better
modularize the code that handles the hierarchy of SCSI errors.
As a result, the code is now much easier to read.
- String handling and error printing has been significantly
revamped. We now use sbufs to do string formatting instead
of using printfs (for the kernel) and snprintf/strncat (for
userland) as before.
There is a new catchall error printing routine,
cam_error_print() and its string-based counterpart,
cam_error_string() that allow the kernel and userland
applications to pass in a CCB and have errors printed out
properly, whether or not they're SCSI errors. Among other
things, this helped eliminate a fair amount of duplicate code
in camcontrol.
We now print out more information than before, including
the CAM status and SCSI status and the error recovery action
taken to remedy the problem.
- sbufs are now available in userland, via libsbuf. This
change was necessary since most of the error printing code
is shared between libcam and the kernel.
- A new transfer settings interface is included in this checkin.
This code is #ifdef'ed out, and is primarily intended to aid
discussion with HBA driver authors on the final form the
interface should take. There is example code in the ahc(4)
driver that implements the HBA driver side of the new
interface. The new transfer settings code won't be enabled
until we're ready to switch all HBA drivers over to the new
interface.
src/Makefile.inc1,
lib/Makefile: Add libsbuf. It must be built before libcam,
since libcam uses sbuf routines.
libcam/Makefile: libcam now depends on libsbuf.
libsbuf/Makefile: Add a makefile for libsbuf. This pulls in the
sbuf sources from sys/kern.
bsd.libnames.mk: Add LIBSBUF.
camcontrol/Makefile: Add -lsbuf. Since camcontrol is statically
linked, we can't depend on the dynamic linker
to pull in libsbuf.
camcontrol.c: Use cam_error_print() instead of checking for
CAM_SCSI_STATUS_ERROR on every failed CCB.
sbuf.9: Change the prototypes for sbuf_cat() and
sbuf_cpy() so that the source string is now a
const char *. This is more in line wth the
standard system string functions, and helps
eliminate warnings when dealing with a const
source buffer.
Fix a typo.
cam.c: Add description strings for the various CAM
error status values, as well as routines to
look up those strings.
Add new cam_error_string() and
cam_error_print() routines for userland and
the kernel.
cam.h: Add a new CAM flag, CAM_RETRY_SELTO.
Add enumerated types for the various options
available with cam_error_print() and
cam_error_string().
cam_ccb.h: Add new transfer negotiation structures/types.
Change inq_len in the ccb_getdev structure to
be "reserved". This field has never been
filled in, and will be removed when we next
bump the CAM version.
cam_debug.h: Fix typo.
cam_periph.c: Modularize cam_periph_error(). The SCSI error
handling part of cam_periph_error() is now
in camperiphscsistatuserror() and
camperiphscsisenseerror().
In cam_periph_lock(), increase the reference
count on the periph while we wait for our lock
attempt to succeed so that the periph won't go
away while we're sleeping.
cam_xpt.c: Add new transfer negotiation code. (ifdefed
out)
Add a new function, xpt_path_string(). This
is a string/sbuf analog to xpt_print_path().
scsi_all.c: Revamp string handing and error printing code.
We now use sbufs for much of the string
formatting code. More of that code is shared
between userland the kernel.
scsi_all.h: Get rid of SS_TURSTART, it wasn't terribly
useful in the first place.
Add a new error action, SS_REQSENSE. (Send a
request sense and then retry the command.)
This is useful when the controller hasn't
performed autosense for some reason.
Change the default actions around a bit.
scsi_cd.c,
scsi_da.c,
scsi_pt.c,
scsi_ses.c: SF_RETRY_SELTO -> CAM_RETRY_SELTO. Selection
timeouts shouldn't be covered by a sense flag.
scsi_pass.[ch]: SF_RETRY_SELTO -> CAM_RETRY_SELTO.
Get rid of the last vestiges of a read/write
interface.
libkern/bsearch.c,
sys/libkern.h,
conf/files: Add bsearch.c, which is needed for some of the
new table lookup routines.
aic7xxx_freebsd.c: Define AHC_NEW_TRAN_SETTINGS if
CAM_NEW_TRAN_CODE is defined.
sbuf.h,
subr_sbuf.c: Add the appropriate #ifdefs so sbufs can
compile and run in userland.
Change sbuf_printf() to use vsnprintf()
instead of kvprintf(), which is only available
in the kernel.
Change the source string for sbuf_cpy() and
sbuf_cat() to be a const char *.
Add __BEGIN_DECLS and __END_DECLS around
function prototypes since they're now exported
to userland.
kdump/mkioctls: Include stdio.h before cam.h since cam.h now
includes a function with a FILE * argument.
Submitted by: gibbs (mostly)
Reviewed by: jdp, marcel (libsbuf makefile changes)
Reviewed by: des (sbuf changes)
Reviewed by: ken
2001-03-27 05:45:52 +00:00
|
|
|
error = daerror(done_ccb, CAM_RETRY_SELTO,
|
|
|
|
SF_RETRY_UA|SF_NO_PRINT);
|
1998-09-15 06:36:34 +00:00
|
|
|
if (error == ERESTART) {
|
|
|
|
/*
|
|
|
|
* A retry was scheuled, so
|
|
|
|
* just return.
|
|
|
|
*/
|
|
|
|
return;
|
|
|
|
} else if (error != 0) {
|
|
|
|
int asc, ascq;
|
|
|
|
int sense_key, error_code;
|
|
|
|
int have_sense;
|
|
|
|
cam_status status;
|
|
|
|
struct ccb_getdev cgd;
|
|
|
|
|
|
|
|
/* Don't wedge this device's queue */
|
|
|
|
status = done_ccb->ccb_h.status;
|
Rewrite of the CAM error recovery code.
Some of the major changes include:
- The SCSI error handling portion of cam_periph_error() has
been broken out into a number of subfunctions to better
modularize the code that handles the hierarchy of SCSI errors.
As a result, the code is now much easier to read.
- String handling and error printing has been significantly
revamped. We now use sbufs to do string formatting instead
of using printfs (for the kernel) and snprintf/strncat (for
userland) as before.
There is a new catchall error printing routine,
cam_error_print() and its string-based counterpart,
cam_error_string() that allow the kernel and userland
applications to pass in a CCB and have errors printed out
properly, whether or not they're SCSI errors. Among other
things, this helped eliminate a fair amount of duplicate code
in camcontrol.
We now print out more information than before, including
the CAM status and SCSI status and the error recovery action
taken to remedy the problem.
- sbufs are now available in userland, via libsbuf. This
change was necessary since most of the error printing code
is shared between libcam and the kernel.
- A new transfer settings interface is included in this checkin.
This code is #ifdef'ed out, and is primarily intended to aid
discussion with HBA driver authors on the final form the
interface should take. There is example code in the ahc(4)
driver that implements the HBA driver side of the new
interface. The new transfer settings code won't be enabled
until we're ready to switch all HBA drivers over to the new
interface.
src/Makefile.inc1,
lib/Makefile: Add libsbuf. It must be built before libcam,
since libcam uses sbuf routines.
libcam/Makefile: libcam now depends on libsbuf.
libsbuf/Makefile: Add a makefile for libsbuf. This pulls in the
sbuf sources from sys/kern.
bsd.libnames.mk: Add LIBSBUF.
camcontrol/Makefile: Add -lsbuf. Since camcontrol is statically
linked, we can't depend on the dynamic linker
to pull in libsbuf.
camcontrol.c: Use cam_error_print() instead of checking for
CAM_SCSI_STATUS_ERROR on every failed CCB.
sbuf.9: Change the prototypes for sbuf_cat() and
sbuf_cpy() so that the source string is now a
const char *. This is more in line wth the
standard system string functions, and helps
eliminate warnings when dealing with a const
source buffer.
Fix a typo.
cam.c: Add description strings for the various CAM
error status values, as well as routines to
look up those strings.
Add new cam_error_string() and
cam_error_print() routines for userland and
the kernel.
cam.h: Add a new CAM flag, CAM_RETRY_SELTO.
Add enumerated types for the various options
available with cam_error_print() and
cam_error_string().
cam_ccb.h: Add new transfer negotiation structures/types.
Change inq_len in the ccb_getdev structure to
be "reserved". This field has never been
filled in, and will be removed when we next
bump the CAM version.
cam_debug.h: Fix typo.
cam_periph.c: Modularize cam_periph_error(). The SCSI error
handling part of cam_periph_error() is now
in camperiphscsistatuserror() and
camperiphscsisenseerror().
In cam_periph_lock(), increase the reference
count on the periph while we wait for our lock
attempt to succeed so that the periph won't go
away while we're sleeping.
cam_xpt.c: Add new transfer negotiation code. (ifdefed
out)
Add a new function, xpt_path_string(). This
is a string/sbuf analog to xpt_print_path().
scsi_all.c: Revamp string handing and error printing code.
We now use sbufs for much of the string
formatting code. More of that code is shared
between userland the kernel.
scsi_all.h: Get rid of SS_TURSTART, it wasn't terribly
useful in the first place.
Add a new error action, SS_REQSENSE. (Send a
request sense and then retry the command.)
This is useful when the controller hasn't
performed autosense for some reason.
Change the default actions around a bit.
scsi_cd.c,
scsi_da.c,
scsi_pt.c,
scsi_ses.c: SF_RETRY_SELTO -> CAM_RETRY_SELTO. Selection
timeouts shouldn't be covered by a sense flag.
scsi_pass.[ch]: SF_RETRY_SELTO -> CAM_RETRY_SELTO.
Get rid of the last vestiges of a read/write
interface.
libkern/bsearch.c,
sys/libkern.h,
conf/files: Add bsearch.c, which is needed for some of the
new table lookup routines.
aic7xxx_freebsd.c: Define AHC_NEW_TRAN_SETTINGS if
CAM_NEW_TRAN_CODE is defined.
sbuf.h,
subr_sbuf.c: Add the appropriate #ifdefs so sbufs can
compile and run in userland.
Change sbuf_printf() to use vsnprintf()
instead of kvprintf(), which is only available
in the kernel.
Change the source string for sbuf_cpy() and
sbuf_cat() to be a const char *.
Add __BEGIN_DECLS and __END_DECLS around
function prototypes since they're now exported
to userland.
kdump/mkioctls: Include stdio.h before cam.h since cam.h now
includes a function with a FILE * argument.
Submitted by: gibbs (mostly)
Reviewed by: jdp, marcel (libsbuf makefile changes)
Reviewed by: des (sbuf changes)
Reviewed by: ken
2001-03-27 05:45:52 +00:00
|
|
|
if ((status & CAM_DEV_QFRZN) != 0)
|
|
|
|
cam_release_devq(done_ccb->ccb_h.path,
|
|
|
|
/*relsim_flags*/0,
|
|
|
|
/*reduction*/0,
|
|
|
|
/*timeout*/0,
|
|
|
|
/*getcount_only*/0);
|
|
|
|
|
1998-09-15 06:36:34 +00:00
|
|
|
|
|
|
|
xpt_setup_ccb(&cgd.ccb_h,
|
|
|
|
done_ccb->ccb_h.path,
|
2009-10-23 08:27:55 +00:00
|
|
|
CAM_PRIORITY_NORMAL);
|
1998-09-15 06:36:34 +00:00
|
|
|
cgd.ccb_h.func_code = XPT_GDEV_TYPE;
|
|
|
|
xpt_action((union ccb *)&cgd);
|
|
|
|
|
2012-06-23 12:32:53 +00:00
|
|
|
if (scsi_extract_sense_ccb(done_ccb,
|
|
|
|
&error_code, &sense_key, &asc, &ascq))
|
1998-09-15 06:36:34 +00:00
|
|
|
have_sense = TRUE;
|
2012-06-23 12:32:53 +00:00
|
|
|
else
|
|
|
|
have_sense = FALSE;
|
1998-09-15 06:36:34 +00:00
|
|
|
|
2011-12-23 19:12:02 +00:00
|
|
|
/*
|
|
|
|
* If we tried READ CAPACITY(16) and failed,
|
|
|
|
* fallback to READ CAPACITY(10).
|
|
|
|
*/
|
2013-04-26 16:17:04 +00:00
|
|
|
if ((state == DA_CCB_PROBE_RC16) &&
|
2011-12-23 19:12:02 +00:00
|
|
|
(softc->flags & DA_FLAG_CAN_RC16) &&
|
|
|
|
(((csio->ccb_h.status & CAM_STATUS_MASK) ==
|
|
|
|
CAM_REQ_INVALID) ||
|
|
|
|
((have_sense) &&
|
|
|
|
(error_code == SSD_CURRENT_ERROR) &&
|
|
|
|
(sense_key == SSD_KEY_ILLEGAL_REQUEST)))) {
|
|
|
|
softc->flags &= ~DA_FLAG_CAN_RC16;
|
|
|
|
free(rdcap, M_SCSIDA);
|
|
|
|
xpt_release_ccb(done_ccb);
|
2013-05-02 14:14:57 +00:00
|
|
|
softc->state = DA_STATE_PROBE_RC;
|
2011-12-23 19:12:02 +00:00
|
|
|
xpt_schedule(periph, priority);
|
|
|
|
return;
|
2016-02-18 15:12:52 +00:00
|
|
|
}
|
|
|
|
|
1998-09-15 06:36:34 +00:00
|
|
|
/*
|
Add a number of interrelated CAM feature enhancements and bug fixes.
NOTE: These changes will require recompilation of any userland
applications, like cdrecord, xmcd, etc., that use the CAM passthrough
interface. A make world is recommended.
camcontrol.[c8]:
- We now support two new commands, "tags" and "negotiate".
- The tags commands allows users to view the number of tagged
openings for a device as well as a number of other related
parameters, and it allows users to set tagged openings for
a device.
- The negotiate command allows users to enable and disable
disconnection and tagged queueing, set sync rates, offsets
and bus width. Note that not all of those features are
available for all controllers. Only the adv, ahc, and ncr
drivers fully support all of the features at this point.
Some cards do not allow the setting of sync rates, offsets and
the like, and some of the drivers don't have any facilities to
do so. Some drivers, like the adw driver, only support enabling
or disabling sync negotiation, but do not support setting sync
rates.
- new description in the camcontrol man page of how to format a disk
- cleanup of the camcontrol inquiry command
- add support in the 'devlist' command for skipping unconfigured devices if
-v was not specified on the command line.
- make use of the new base_transfer_speed in the path inquiry CCB.
- fix CCB bzero cases
cam_xpt.c, cam_sim.[ch], cam_ccb.h:
- new flags on many CCB function codes to designate whether they're
non-immediate, use a user-supplied CCB, and can only be passed from
userland programs via the xpt device. Use these flags in the transport
layer and pass driver to categorize CCBs.
- new flag in the transport layer device matching code for device nodes
that indicates whether a device is unconfigured
- bump the CAM version from 0x10 to 0x11
- Change the CAM ioctls to use the version as their group code, so we can
force users to recompile code even when the CCB size doesn't change.
- add + fill in a new value in the path inquiry CCB, base_transfer_speed.
Remove a corresponding field from the cam_sim structure, and add code to
every SIM to set this field to the proper value.
- Fix the set transfer settings code in the transport layer.
scsi_cd.c:
- make some variables volatile instead of just casting them in various
places
- fix a race condition in the changer code
- attach unless we get a "logical unit not supported" error. This should
fix all of the cases where people have devices that return weird errors
when they don't have media in the drive.
scsi_da.c:
- attach unless we get a "logical unit not supported" error
scsi_pass.c:
- for immediate CCBs, just malloc a CCB to send the user request in. This
gets rid of the 'held' count problem in camcontrol tags.
scsi_pass.h:
- change the CAM ioctls to use the CAM version as their group code.
adv driver:
- Allow changing the sync rate and offset separately.
adw driver
- Allow changing the sync rate and offset separately.
aha driver:
- Don't return CAM_REQ_CMP for SET_TRAN_SETTINGS CCBs.
ahc driver:
- Allow setting offset and sync rate separately
bt driver:
- Don't return CAM_REQ_CMP for SET_TRAN_SETTINGS CCBs.
NCR driver:
- Fix the ultra/ultra 2 negotiation bug
- allow setting both the sync rate and offset separately
Other HBA drivers:
- Put code in to set the base_transfer_speed field for
XPT_GET_TRAN_SETTINGS CCBs.
Reviewed by: gibbs, mjacob (isp), imp (aha)
1999-05-06 20:16:39 +00:00
|
|
|
* Attach to anything that claims to be a
|
|
|
|
* direct access or optical disk device,
|
|
|
|
* as long as it doesn't return a "Logical
|
|
|
|
* unit not supported" (0x25) error.
|
1998-09-15 06:36:34 +00:00
|
|
|
*/
|
Add a number of interrelated CAM feature enhancements and bug fixes.
NOTE: These changes will require recompilation of any userland
applications, like cdrecord, xmcd, etc., that use the CAM passthrough
interface. A make world is recommended.
camcontrol.[c8]:
- We now support two new commands, "tags" and "negotiate".
- The tags commands allows users to view the number of tagged
openings for a device as well as a number of other related
parameters, and it allows users to set tagged openings for
a device.
- The negotiate command allows users to enable and disable
disconnection and tagged queueing, set sync rates, offsets
and bus width. Note that not all of those features are
available for all controllers. Only the adv, ahc, and ncr
drivers fully support all of the features at this point.
Some cards do not allow the setting of sync rates, offsets and
the like, and some of the drivers don't have any facilities to
do so. Some drivers, like the adw driver, only support enabling
or disabling sync negotiation, but do not support setting sync
rates.
- new description in the camcontrol man page of how to format a disk
- cleanup of the camcontrol inquiry command
- add support in the 'devlist' command for skipping unconfigured devices if
-v was not specified on the command line.
- make use of the new base_transfer_speed in the path inquiry CCB.
- fix CCB bzero cases
cam_xpt.c, cam_sim.[ch], cam_ccb.h:
- new flags on many CCB function codes to designate whether they're
non-immediate, use a user-supplied CCB, and can only be passed from
userland programs via the xpt device. Use these flags in the transport
layer and pass driver to categorize CCBs.
- new flag in the transport layer device matching code for device nodes
that indicates whether a device is unconfigured
- bump the CAM version from 0x10 to 0x11
- Change the CAM ioctls to use the version as their group code, so we can
force users to recompile code even when the CCB size doesn't change.
- add + fill in a new value in the path inquiry CCB, base_transfer_speed.
Remove a corresponding field from the cam_sim structure, and add code to
every SIM to set this field to the proper value.
- Fix the set transfer settings code in the transport layer.
scsi_cd.c:
- make some variables volatile instead of just casting them in various
places
- fix a race condition in the changer code
- attach unless we get a "logical unit not supported" error. This should
fix all of the cases where people have devices that return weird errors
when they don't have media in the drive.
scsi_da.c:
- attach unless we get a "logical unit not supported" error
scsi_pass.c:
- for immediate CCBs, just malloc a CCB to send the user request in. This
gets rid of the 'held' count problem in camcontrol tags.
scsi_pass.h:
- change the CAM ioctls to use the CAM version as their group code.
adv driver:
- Allow changing the sync rate and offset separately.
adw driver
- Allow changing the sync rate and offset separately.
aha driver:
- Don't return CAM_REQ_CMP for SET_TRAN_SETTINGS CCBs.
ahc driver:
- Allow setting offset and sync rate separately
bt driver:
- Don't return CAM_REQ_CMP for SET_TRAN_SETTINGS CCBs.
NCR driver:
- Fix the ultra/ultra 2 negotiation bug
- allow setting both the sync rate and offset separately
Other HBA drivers:
- Put code in to set the base_transfer_speed field for
XPT_GET_TRAN_SETTINGS CCBs.
Reviewed by: gibbs, mjacob (isp), imp (aha)
1999-05-06 20:16:39 +00:00
|
|
|
if ((have_sense) && (asc != 0x25)
|
Rewrite of the CAM error recovery code.
Some of the major changes include:
- The SCSI error handling portion of cam_periph_error() has
been broken out into a number of subfunctions to better
modularize the code that handles the hierarchy of SCSI errors.
As a result, the code is now much easier to read.
- String handling and error printing has been significantly
revamped. We now use sbufs to do string formatting instead
of using printfs (for the kernel) and snprintf/strncat (for
userland) as before.
There is a new catchall error printing routine,
cam_error_print() and its string-based counterpart,
cam_error_string() that allow the kernel and userland
applications to pass in a CCB and have errors printed out
properly, whether or not they're SCSI errors. Among other
things, this helped eliminate a fair amount of duplicate code
in camcontrol.
We now print out more information than before, including
the CAM status and SCSI status and the error recovery action
taken to remedy the problem.
- sbufs are now available in userland, via libsbuf. This
change was necessary since most of the error printing code
is shared between libcam and the kernel.
- A new transfer settings interface is included in this checkin.
This code is #ifdef'ed out, and is primarily intended to aid
discussion with HBA driver authors on the final form the
interface should take. There is example code in the ahc(4)
driver that implements the HBA driver side of the new
interface. The new transfer settings code won't be enabled
until we're ready to switch all HBA drivers over to the new
interface.
src/Makefile.inc1,
lib/Makefile: Add libsbuf. It must be built before libcam,
since libcam uses sbuf routines.
libcam/Makefile: libcam now depends on libsbuf.
libsbuf/Makefile: Add a makefile for libsbuf. This pulls in the
sbuf sources from sys/kern.
bsd.libnames.mk: Add LIBSBUF.
camcontrol/Makefile: Add -lsbuf. Since camcontrol is statically
linked, we can't depend on the dynamic linker
to pull in libsbuf.
camcontrol.c: Use cam_error_print() instead of checking for
CAM_SCSI_STATUS_ERROR on every failed CCB.
sbuf.9: Change the prototypes for sbuf_cat() and
sbuf_cpy() so that the source string is now a
const char *. This is more in line wth the
standard system string functions, and helps
eliminate warnings when dealing with a const
source buffer.
Fix a typo.
cam.c: Add description strings for the various CAM
error status values, as well as routines to
look up those strings.
Add new cam_error_string() and
cam_error_print() routines for userland and
the kernel.
cam.h: Add a new CAM flag, CAM_RETRY_SELTO.
Add enumerated types for the various options
available with cam_error_print() and
cam_error_string().
cam_ccb.h: Add new transfer negotiation structures/types.
Change inq_len in the ccb_getdev structure to
be "reserved". This field has never been
filled in, and will be removed when we next
bump the CAM version.
cam_debug.h: Fix typo.
cam_periph.c: Modularize cam_periph_error(). The SCSI error
handling part of cam_periph_error() is now
in camperiphscsistatuserror() and
camperiphscsisenseerror().
In cam_periph_lock(), increase the reference
count on the periph while we wait for our lock
attempt to succeed so that the periph won't go
away while we're sleeping.
cam_xpt.c: Add new transfer negotiation code. (ifdefed
out)
Add a new function, xpt_path_string(). This
is a string/sbuf analog to xpt_print_path().
scsi_all.c: Revamp string handing and error printing code.
We now use sbufs for much of the string
formatting code. More of that code is shared
between userland the kernel.
scsi_all.h: Get rid of SS_TURSTART, it wasn't terribly
useful in the first place.
Add a new error action, SS_REQSENSE. (Send a
request sense and then retry the command.)
This is useful when the controller hasn't
performed autosense for some reason.
Change the default actions around a bit.
scsi_cd.c,
scsi_da.c,
scsi_pt.c,
scsi_ses.c: SF_RETRY_SELTO -> CAM_RETRY_SELTO. Selection
timeouts shouldn't be covered by a sense flag.
scsi_pass.[ch]: SF_RETRY_SELTO -> CAM_RETRY_SELTO.
Get rid of the last vestiges of a read/write
interface.
libkern/bsearch.c,
sys/libkern.h,
conf/files: Add bsearch.c, which is needed for some of the
new table lookup routines.
aic7xxx_freebsd.c: Define AHC_NEW_TRAN_SETTINGS if
CAM_NEW_TRAN_CODE is defined.
sbuf.h,
subr_sbuf.c: Add the appropriate #ifdefs so sbufs can
compile and run in userland.
Change sbuf_printf() to use vsnprintf()
instead of kvprintf(), which is only available
in the kernel.
Change the source string for sbuf_cpy() and
sbuf_cat() to be a const char *.
Add __BEGIN_DECLS and __END_DECLS around
function prototypes since they're now exported
to userland.
kdump/mkioctls: Include stdio.h before cam.h since cam.h now
includes a function with a FILE * argument.
Submitted by: gibbs (mostly)
Reviewed by: jdp, marcel (libsbuf makefile changes)
Reviewed by: des (sbuf changes)
Reviewed by: ken
2001-03-27 05:45:52 +00:00
|
|
|
&& (error_code == SSD_CURRENT_ERROR)) {
|
|
|
|
const char *sense_key_desc;
|
|
|
|
const char *asc_desc;
|
|
|
|
|
2013-05-03 11:53:06 +00:00
|
|
|
dasetgeom(periph, 512, -1, NULL, 0);
|
Rewrite of the CAM error recovery code.
Some of the major changes include:
- The SCSI error handling portion of cam_periph_error() has
been broken out into a number of subfunctions to better
modularize the code that handles the hierarchy of SCSI errors.
As a result, the code is now much easier to read.
- String handling and error printing has been significantly
revamped. We now use sbufs to do string formatting instead
of using printfs (for the kernel) and snprintf/strncat (for
userland) as before.
There is a new catchall error printing routine,
cam_error_print() and its string-based counterpart,
cam_error_string() that allow the kernel and userland
applications to pass in a CCB and have errors printed out
properly, whether or not they're SCSI errors. Among other
things, this helped eliminate a fair amount of duplicate code
in camcontrol.
We now print out more information than before, including
the CAM status and SCSI status and the error recovery action
taken to remedy the problem.
- sbufs are now available in userland, via libsbuf. This
change was necessary since most of the error printing code
is shared between libcam and the kernel.
- A new transfer settings interface is included in this checkin.
This code is #ifdef'ed out, and is primarily intended to aid
discussion with HBA driver authors on the final form the
interface should take. There is example code in the ahc(4)
driver that implements the HBA driver side of the new
interface. The new transfer settings code won't be enabled
until we're ready to switch all HBA drivers over to the new
interface.
src/Makefile.inc1,
lib/Makefile: Add libsbuf. It must be built before libcam,
since libcam uses sbuf routines.
libcam/Makefile: libcam now depends on libsbuf.
libsbuf/Makefile: Add a makefile for libsbuf. This pulls in the
sbuf sources from sys/kern.
bsd.libnames.mk: Add LIBSBUF.
camcontrol/Makefile: Add -lsbuf. Since camcontrol is statically
linked, we can't depend on the dynamic linker
to pull in libsbuf.
camcontrol.c: Use cam_error_print() instead of checking for
CAM_SCSI_STATUS_ERROR on every failed CCB.
sbuf.9: Change the prototypes for sbuf_cat() and
sbuf_cpy() so that the source string is now a
const char *. This is more in line wth the
standard system string functions, and helps
eliminate warnings when dealing with a const
source buffer.
Fix a typo.
cam.c: Add description strings for the various CAM
error status values, as well as routines to
look up those strings.
Add new cam_error_string() and
cam_error_print() routines for userland and
the kernel.
cam.h: Add a new CAM flag, CAM_RETRY_SELTO.
Add enumerated types for the various options
available with cam_error_print() and
cam_error_string().
cam_ccb.h: Add new transfer negotiation structures/types.
Change inq_len in the ccb_getdev structure to
be "reserved". This field has never been
filled in, and will be removed when we next
bump the CAM version.
cam_debug.h: Fix typo.
cam_periph.c: Modularize cam_periph_error(). The SCSI error
handling part of cam_periph_error() is now
in camperiphscsistatuserror() and
camperiphscsisenseerror().
In cam_periph_lock(), increase the reference
count on the periph while we wait for our lock
attempt to succeed so that the periph won't go
away while we're sleeping.
cam_xpt.c: Add new transfer negotiation code. (ifdefed
out)
Add a new function, xpt_path_string(). This
is a string/sbuf analog to xpt_print_path().
scsi_all.c: Revamp string handing and error printing code.
We now use sbufs for much of the string
formatting code. More of that code is shared
between userland the kernel.
scsi_all.h: Get rid of SS_TURSTART, it wasn't terribly
useful in the first place.
Add a new error action, SS_REQSENSE. (Send a
request sense and then retry the command.)
This is useful when the controller hasn't
performed autosense for some reason.
Change the default actions around a bit.
scsi_cd.c,
scsi_da.c,
scsi_pt.c,
scsi_ses.c: SF_RETRY_SELTO -> CAM_RETRY_SELTO. Selection
timeouts shouldn't be covered by a sense flag.
scsi_pass.[ch]: SF_RETRY_SELTO -> CAM_RETRY_SELTO.
Get rid of the last vestiges of a read/write
interface.
libkern/bsearch.c,
sys/libkern.h,
conf/files: Add bsearch.c, which is needed for some of the
new table lookup routines.
aic7xxx_freebsd.c: Define AHC_NEW_TRAN_SETTINGS if
CAM_NEW_TRAN_CODE is defined.
sbuf.h,
subr_sbuf.c: Add the appropriate #ifdefs so sbufs can
compile and run in userland.
Change sbuf_printf() to use vsnprintf()
instead of kvprintf(), which is only available
in the kernel.
Change the source string for sbuf_cpy() and
sbuf_cat() to be a const char *.
Add __BEGIN_DECLS and __END_DECLS around
function prototypes since they're now exported
to userland.
kdump/mkioctls: Include stdio.h before cam.h since cam.h now
includes a function with a FILE * argument.
Submitted by: gibbs (mostly)
Reviewed by: jdp, marcel (libsbuf makefile changes)
Reviewed by: des (sbuf changes)
Reviewed by: ken
2001-03-27 05:45:52 +00:00
|
|
|
scsi_sense_desc(sense_key, asc, ascq,
|
|
|
|
&cgd.inq_data,
|
|
|
|
&sense_key_desc,
|
|
|
|
&asc_desc);
|
1998-12-04 22:54:57 +00:00
|
|
|
snprintf(announce_buf,
|
|
|
|
sizeof(announce_buf),
|
1998-09-15 06:36:34 +00:00
|
|
|
"Attempt to query device "
|
|
|
|
"size failed: %s, %s",
|
Rewrite of the CAM error recovery code.
Some of the major changes include:
- The SCSI error handling portion of cam_periph_error() has
been broken out into a number of subfunctions to better
modularize the code that handles the hierarchy of SCSI errors.
As a result, the code is now much easier to read.
- String handling and error printing has been significantly
revamped. We now use sbufs to do string formatting instead
of using printfs (for the kernel) and snprintf/strncat (for
userland) as before.
There is a new catchall error printing routine,
cam_error_print() and its string-based counterpart,
cam_error_string() that allow the kernel and userland
applications to pass in a CCB and have errors printed out
properly, whether or not they're SCSI errors. Among other
things, this helped eliminate a fair amount of duplicate code
in camcontrol.
We now print out more information than before, including
the CAM status and SCSI status and the error recovery action
taken to remedy the problem.
- sbufs are now available in userland, via libsbuf. This
change was necessary since most of the error printing code
is shared between libcam and the kernel.
- A new transfer settings interface is included in this checkin.
This code is #ifdef'ed out, and is primarily intended to aid
discussion with HBA driver authors on the final form the
interface should take. There is example code in the ahc(4)
driver that implements the HBA driver side of the new
interface. The new transfer settings code won't be enabled
until we're ready to switch all HBA drivers over to the new
interface.
src/Makefile.inc1,
lib/Makefile: Add libsbuf. It must be built before libcam,
since libcam uses sbuf routines.
libcam/Makefile: libcam now depends on libsbuf.
libsbuf/Makefile: Add a makefile for libsbuf. This pulls in the
sbuf sources from sys/kern.
bsd.libnames.mk: Add LIBSBUF.
camcontrol/Makefile: Add -lsbuf. Since camcontrol is statically
linked, we can't depend on the dynamic linker
to pull in libsbuf.
camcontrol.c: Use cam_error_print() instead of checking for
CAM_SCSI_STATUS_ERROR on every failed CCB.
sbuf.9: Change the prototypes for sbuf_cat() and
sbuf_cpy() so that the source string is now a
const char *. This is more in line wth the
standard system string functions, and helps
eliminate warnings when dealing with a const
source buffer.
Fix a typo.
cam.c: Add description strings for the various CAM
error status values, as well as routines to
look up those strings.
Add new cam_error_string() and
cam_error_print() routines for userland and
the kernel.
cam.h: Add a new CAM flag, CAM_RETRY_SELTO.
Add enumerated types for the various options
available with cam_error_print() and
cam_error_string().
cam_ccb.h: Add new transfer negotiation structures/types.
Change inq_len in the ccb_getdev structure to
be "reserved". This field has never been
filled in, and will be removed when we next
bump the CAM version.
cam_debug.h: Fix typo.
cam_periph.c: Modularize cam_periph_error(). The SCSI error
handling part of cam_periph_error() is now
in camperiphscsistatuserror() and
camperiphscsisenseerror().
In cam_periph_lock(), increase the reference
count on the periph while we wait for our lock
attempt to succeed so that the periph won't go
away while we're sleeping.
cam_xpt.c: Add new transfer negotiation code. (ifdefed
out)
Add a new function, xpt_path_string(). This
is a string/sbuf analog to xpt_print_path().
scsi_all.c: Revamp string handing and error printing code.
We now use sbufs for much of the string
formatting code. More of that code is shared
between userland the kernel.
scsi_all.h: Get rid of SS_TURSTART, it wasn't terribly
useful in the first place.
Add a new error action, SS_REQSENSE. (Send a
request sense and then retry the command.)
This is useful when the controller hasn't
performed autosense for some reason.
Change the default actions around a bit.
scsi_cd.c,
scsi_da.c,
scsi_pt.c,
scsi_ses.c: SF_RETRY_SELTO -> CAM_RETRY_SELTO. Selection
timeouts shouldn't be covered by a sense flag.
scsi_pass.[ch]: SF_RETRY_SELTO -> CAM_RETRY_SELTO.
Get rid of the last vestiges of a read/write
interface.
libkern/bsearch.c,
sys/libkern.h,
conf/files: Add bsearch.c, which is needed for some of the
new table lookup routines.
aic7xxx_freebsd.c: Define AHC_NEW_TRAN_SETTINGS if
CAM_NEW_TRAN_CODE is defined.
sbuf.h,
subr_sbuf.c: Add the appropriate #ifdefs so sbufs can
compile and run in userland.
Change sbuf_printf() to use vsnprintf()
instead of kvprintf(), which is only available
in the kernel.
Change the source string for sbuf_cpy() and
sbuf_cat() to be a const char *.
Add __BEGIN_DECLS and __END_DECLS around
function prototypes since they're now exported
to userland.
kdump/mkioctls: Include stdio.h before cam.h since cam.h now
includes a function with a FILE * argument.
Submitted by: gibbs (mostly)
Reviewed by: jdp, marcel (libsbuf makefile changes)
Reviewed by: des (sbuf changes)
Reviewed by: ken
2001-03-27 05:45:52 +00:00
|
|
|
sense_key_desc,
|
|
|
|
asc_desc);
|
|
|
|
} else {
|
1998-10-07 02:57:57 +00:00
|
|
|
if (have_sense)
|
|
|
|
scsi_sense_print(
|
|
|
|
&done_ccb->csio);
|
|
|
|
else {
|
2006-12-05 07:45:28 +00:00
|
|
|
xpt_print(periph->path,
|
|
|
|
"got CAM status %#x\n",
|
|
|
|
done_ccb->ccb_h.status);
|
1998-10-07 02:57:57 +00:00
|
|
|
}
|
1999-01-07 20:19:09 +00:00
|
|
|
|
2006-12-05 07:45:28 +00:00
|
|
|
xpt_print(periph->path, "fatal error, "
|
|
|
|
"failed to attach to device\n");
|
1998-09-15 06:36:34 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Free up resources.
|
|
|
|
*/
|
|
|
|
cam_periph_invalidate(periph);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2007-05-14 21:48:53 +00:00
|
|
|
free(csio->data_ptr, M_SCSIDA);
|
2014-04-30 17:38:26 +00:00
|
|
|
if (announce_buf[0] != '\0' &&
|
|
|
|
((softc->flags & DA_FLAG_ANNOUNCED) == 0)) {
|
Move dynamic sysctl(8) variable creation for the cd(4) and da(4) drivers
out of cdregister() and daregister(), which are run from interrupt context.
The sysctl code does blocking mallocs (M_WAITOK), which causes problems
if malloc(9) actually needs to sleep.
The eventual fix for this issue will involve moving the CAM probe process
inside a kernel thread. For now, though, I have fixed the issue by moving
dynamic sysctl variable creation for these two drivers to a task queue
running in a kernel thread.
The existing task queues (taskqueue_swi and taskqueue_swi_giant) run in
software interrupt handlers, which wouldn't fix the problem at hand. So I
have created a new task queue, taskqueue_thread, that runs inside a kernel
thread. (It also runs outside of Giant -- clients must explicitly acquire
and release Giant in their taskqueue functions.)
scsi_cd.c: Remove sysctl variable creation code from cdregister(), and
move it to a new function, cdsysctlinit(). Queue
cdsysctlinit() to the taskqueue_thread taskqueue once we
have fully registered the cd(4) driver instance.
scsi_da.c: Remove sysctl variable creation code from daregister(), and
move it to move it to a new function, dasysctlinit().
Queue dasysctlinit() to the taskqueue_thread taskqueue once
we have fully registered the da(4) instance.
taskqueue.h: Declare the new taskqueue_thread taskqueue, update some
comments.
subr_taskqueue.c:
Create the new kernel thread taskqueue. This taskqueue
runs outside of Giant, so any functions queued to it would
need to explicitly acquire/release Giant if they need it.
cd.4: Update the cd(4) man page to talk about the minimum command
size sysctl/loader tunable. Also note that the changer
variables are available as loader tunables as well.
da.4: Update the da(4) man page to cover the retry_count,
default_timeout and minimum_cmd_size sysctl variables/loader
tunables. Remove references to /dev/r???, they aren't used
any longer.
cd.9: Update the cd(9) man page to describe the CD_Q_10_BYTE_ONLY
quirk.
taskqueue.9: Update the taskqueue(9) man page to describe the new thread
task queue, and the taskqueue_swi_giant queue.
MFC after: 3 days
2003-09-03 04:46:28 +00:00
|
|
|
/*
|
|
|
|
* Create our sysctl variables, now that we know
|
|
|
|
* we have successfully attached.
|
|
|
|
*/
|
Fix a race condition in CAM peripheral free handling, locking
in the CAM XPT bus traversal code, and a number of other periph level
issues.
cam_periph.h,
cam_periph.c: Modify cam_periph_acquire() to test the CAM_PERIPH_INVALID
flag prior to allowing a reference count to be gained
on a peripheral. Callers of this function will receive
CAM_REQ_CMP_ERR status in the situation of attempting to
reference an invalidated periph. This guarantees that
a peripheral scheduled for a deferred free will not
be accessed during its wait for destruction.
Panic during attempts to drop a reference count on
a peripheral that already has a zero reference count.
In cam_periph_list(), use a local sbuf with SBUF_FIXEDLEN
set so that mallocs do not occur while the xpt topology
lock is held, regardless of the allocation policy of the
passed in sbuf.
Add a new routine, cam_periph_release_locked_buses(),
that can be called when the caller already holds
the CAM topology lock.
Add some extra debugging for duplicate peripheral
allocations in cam_periph_alloc().
Treat CAM_DEV_NOT_THERE much the same as a selection
timeout (AC_LOST_DEVICE is emitted), but forgo retries.
cam_xpt.c: Revamp the way the EDT traversal code does locking
and reference counting. This was broken, since it
assumed that the EDT would not change during
traversal, but that assumption is no longer valid.
So, to prevent devices from going away while we
traverse the EDT, make sure we properly lock
everything and hold references on devices that
we are using.
The two peripheral driver traversal routines should
be examined. xptpdperiphtraverse() holds the
topology lock for the entire time it runs.
xptperiphtraverse() is now locked properly, but
only holds the topology lock while it is traversing
the list, and not while the traversal function is
running.
The bus locking code in xptbustraverse() should
also be revisited at a later time, since it is
complex and should probably be simplified.
scsi_da.c: Pay attention to the return value from cam_periph_acquire().
Return 0 always from daclose() even if the disk is now gone.
Add some rudimentary error injection support.
scsi_sg.c: Fix reference counting in the sg(4) driver.
The sg driver was calling cam_periph_release() on close,
but never called cam_periph_acquire() (which increments
the reference count) on open.
The periph code correctly complained that the sg(4)
driver was trying to decrement the refcount when it
was already 0.
Sponsored by: Spectra Logic
MFC after: 2 weeks
2012-01-12 00:41:48 +00:00
|
|
|
/* increase the refcount */
|
|
|
|
if (cam_periph_acquire(periph) == CAM_REQ_CMP) {
|
|
|
|
taskqueue_enqueue(taskqueue_thread,
|
|
|
|
&softc->sysctl_task);
|
|
|
|
xpt_announce_periph(periph, announce_buf);
|
2013-05-18 23:36:21 +00:00
|
|
|
xpt_announce_quirks(periph, softc->quirks,
|
|
|
|
DA_Q_BIT_STRING);
|
Fix a race condition in CAM peripheral free handling, locking
in the CAM XPT bus traversal code, and a number of other periph level
issues.
cam_periph.h,
cam_periph.c: Modify cam_periph_acquire() to test the CAM_PERIPH_INVALID
flag prior to allowing a reference count to be gained
on a peripheral. Callers of this function will receive
CAM_REQ_CMP_ERR status in the situation of attempting to
reference an invalidated periph. This guarantees that
a peripheral scheduled for a deferred free will not
be accessed during its wait for destruction.
Panic during attempts to drop a reference count on
a peripheral that already has a zero reference count.
In cam_periph_list(), use a local sbuf with SBUF_FIXEDLEN
set so that mallocs do not occur while the xpt topology
lock is held, regardless of the allocation policy of the
passed in sbuf.
Add a new routine, cam_periph_release_locked_buses(),
that can be called when the caller already holds
the CAM topology lock.
Add some extra debugging for duplicate peripheral
allocations in cam_periph_alloc().
Treat CAM_DEV_NOT_THERE much the same as a selection
timeout (AC_LOST_DEVICE is emitted), but forgo retries.
cam_xpt.c: Revamp the way the EDT traversal code does locking
and reference counting. This was broken, since it
assumed that the EDT would not change during
traversal, but that assumption is no longer valid.
So, to prevent devices from going away while we
traverse the EDT, make sure we properly lock
everything and hold references on devices that
we are using.
The two peripheral driver traversal routines should
be examined. xptpdperiphtraverse() holds the
topology lock for the entire time it runs.
xptperiphtraverse() is now locked properly, but
only holds the topology lock while it is traversing
the list, and not while the traversal function is
running.
The bus locking code in xptbustraverse() should
also be revisited at a later time, since it is
complex and should probably be simplified.
scsi_da.c: Pay attention to the return value from cam_periph_acquire().
Return 0 always from daclose() even if the disk is now gone.
Add some rudimentary error injection support.
scsi_sg.c: Fix reference counting in the sg(4) driver.
The sg driver was calling cam_periph_release() on close,
but never called cam_periph_acquire() (which increments
the reference count) on open.
The periph code correctly complained that the sg(4)
driver was trying to decrement the refcount when it
was already 0.
Sponsored by: Spectra Logic
MFC after: 2 weeks
2012-01-12 00:41:48 +00:00
|
|
|
} else {
|
|
|
|
xpt_print(periph->path, "fatal error, "
|
|
|
|
"could not acquire reference count\n");
|
|
|
|
}
|
Move dynamic sysctl(8) variable creation for the cd(4) and da(4) drivers
out of cdregister() and daregister(), which are run from interrupt context.
The sysctl code does blocking mallocs (M_WAITOK), which causes problems
if malloc(9) actually needs to sleep.
The eventual fix for this issue will involve moving the CAM probe process
inside a kernel thread. For now, though, I have fixed the issue by moving
dynamic sysctl variable creation for these two drivers to a task queue
running in a kernel thread.
The existing task queues (taskqueue_swi and taskqueue_swi_giant) run in
software interrupt handlers, which wouldn't fix the problem at hand. So I
have created a new task queue, taskqueue_thread, that runs inside a kernel
thread. (It also runs outside of Giant -- clients must explicitly acquire
and release Giant in their taskqueue functions.)
scsi_cd.c: Remove sysctl variable creation code from cdregister(), and
move it to a new function, cdsysctlinit(). Queue
cdsysctlinit() to the taskqueue_thread taskqueue once we
have fully registered the cd(4) driver instance.
scsi_da.c: Remove sysctl variable creation code from daregister(), and
move it to move it to a new function, dasysctlinit().
Queue dasysctlinit() to the taskqueue_thread taskqueue once
we have fully registered the da(4) instance.
taskqueue.h: Declare the new taskqueue_thread taskqueue, update some
comments.
subr_taskqueue.c:
Create the new kernel thread taskqueue. This taskqueue
runs outside of Giant, so any functions queued to it would
need to explicitly acquire/release Giant if they need it.
cd.4: Update the cd(4) man page to talk about the minimum command
size sysctl/loader tunable. Also note that the changer
variables are available as loader tunables as well.
da.4: Update the da(4) man page to cover the retry_count,
default_timeout and minimum_cmd_size sysctl variables/loader
tunables. Remove references to /dev/r???, they aren't used
any longer.
cd.9: Update the cd(9) man page to describe the CD_Q_10_BYTE_ONLY
quirk.
taskqueue.9: Update the taskqueue(9) man page to describe the new thread
task queue, and the taskqueue_swi_giant queue.
MFC after: 3 days
2003-09-03 04:46:28 +00:00
|
|
|
}
|
2013-04-26 16:17:04 +00:00
|
|
|
|
2014-04-30 17:38:26 +00:00
|
|
|
/* We already probed the device. */
|
|
|
|
if (softc->flags & DA_FLAG_PROBED) {
|
|
|
|
daprobedone(periph, done_ccb);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-05-02 14:14:57 +00:00
|
|
|
/* Ensure re-probe doesn't see old delete. */
|
|
|
|
softc->delete_available = 0;
|
2015-10-11 18:26:06 +00:00
|
|
|
dadeleteflag(softc, DA_DELETE_ZERO, 1);
|
2014-04-23 19:50:35 +00:00
|
|
|
if (lbp && (softc->quirks & DA_Q_NO_UNMAP) == 0) {
|
2013-05-02 14:14:57 +00:00
|
|
|
/*
|
|
|
|
* Based on older SBC-3 spec revisions
|
|
|
|
* any of the UNMAP methods "may" be
|
|
|
|
* available via LBP given this flag so
|
|
|
|
* we flag all of them as availble and
|
|
|
|
* then remove those which further
|
|
|
|
* probes confirm aren't available
|
|
|
|
* later.
|
|
|
|
*
|
|
|
|
* We could also check readcap(16) p_type
|
|
|
|
* flag to exclude one or more invalid
|
|
|
|
* write same (X) types here
|
|
|
|
*/
|
|
|
|
dadeleteflag(softc, DA_DELETE_WS16, 1);
|
|
|
|
dadeleteflag(softc, DA_DELETE_WS10, 1);
|
|
|
|
dadeleteflag(softc, DA_DELETE_UNMAP, 1);
|
|
|
|
|
|
|
|
xpt_release_ccb(done_ccb);
|
|
|
|
softc->state = DA_STATE_PROBE_LBP;
|
|
|
|
xpt_schedule(periph, priority);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-04-26 16:17:04 +00:00
|
|
|
xpt_release_ccb(done_ccb);
|
2013-04-26 16:31:03 +00:00
|
|
|
softc->state = DA_STATE_PROBE_BDC;
|
2013-04-26 16:17:04 +00:00
|
|
|
xpt_schedule(periph, priority);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
case DA_CCB_PROBE_LBP:
|
|
|
|
{
|
|
|
|
struct scsi_vpd_logical_block_prov *lbp;
|
|
|
|
|
|
|
|
lbp = (struct scsi_vpd_logical_block_prov *)csio->data_ptr;
|
|
|
|
|
|
|
|
if ((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
|
|
|
|
/*
|
|
|
|
* T10/1799-D Revision 31 states at least one of these
|
|
|
|
* must be supported but we don't currently enforce this.
|
|
|
|
*/
|
|
|
|
dadeleteflag(softc, DA_DELETE_WS16,
|
|
|
|
(lbp->flags & SVPD_LBP_WS16));
|
|
|
|
dadeleteflag(softc, DA_DELETE_WS10,
|
|
|
|
(lbp->flags & SVPD_LBP_WS10));
|
|
|
|
dadeleteflag(softc, DA_DELETE_UNMAP,
|
|
|
|
(lbp->flags & SVPD_LBP_UNMAP));
|
|
|
|
} else {
|
|
|
|
int error;
|
|
|
|
error = daerror(done_ccb, CAM_RETRY_SELTO,
|
|
|
|
SF_RETRY_UA|SF_NO_PRINT);
|
|
|
|
if (error == ERESTART)
|
|
|
|
return;
|
|
|
|
else if (error != 0) {
|
|
|
|
if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
|
|
|
|
/* Don't wedge this device's queue */
|
|
|
|
cam_release_devq(done_ccb->ccb_h.path,
|
|
|
|
/*relsim_flags*/0,
|
|
|
|
/*reduction*/0,
|
|
|
|
/*timeout*/0,
|
|
|
|
/*getcount_only*/0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Failure indicates we don't support any SBC-3
|
|
|
|
* delete methods with UNMAP
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
free(lbp, M_SCSIDA);
|
|
|
|
xpt_release_ccb(done_ccb);
|
2014-04-30 19:44:31 +00:00
|
|
|
softc->state = DA_STATE_PROBE_BLK_LIMITS;
|
2013-04-26 16:17:04 +00:00
|
|
|
xpt_schedule(periph, priority);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
case DA_CCB_PROBE_BLK_LIMITS:
|
|
|
|
{
|
|
|
|
struct scsi_vpd_block_limits *block_limits;
|
|
|
|
|
|
|
|
block_limits = (struct scsi_vpd_block_limits *)csio->data_ptr;
|
|
|
|
|
|
|
|
if ((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
|
2014-04-30 19:44:31 +00:00
|
|
|
uint32_t max_txfer_len = scsi_4btoul(
|
|
|
|
block_limits->max_txfer_len);
|
2013-04-26 16:17:04 +00:00
|
|
|
uint32_t max_unmap_lba_cnt = scsi_4btoul(
|
|
|
|
block_limits->max_unmap_lba_cnt);
|
|
|
|
uint32_t max_unmap_blk_cnt = scsi_4btoul(
|
|
|
|
block_limits->max_unmap_blk_cnt);
|
|
|
|
uint64_t ws_max_blks = scsi_8btou64(
|
|
|
|
block_limits->max_write_same_length);
|
2014-04-30 19:44:31 +00:00
|
|
|
|
|
|
|
if (max_txfer_len != 0) {
|
|
|
|
softc->disk->d_maxsize = MIN(softc->maxio,
|
|
|
|
(off_t)max_txfer_len * softc->params.secsize);
|
|
|
|
}
|
|
|
|
|
2013-04-26 16:17:04 +00:00
|
|
|
/*
|
|
|
|
* We should already support UNMAP but we check lba
|
|
|
|
* and block count to be sure
|
|
|
|
*/
|
|
|
|
if (max_unmap_lba_cnt != 0x00L &&
|
|
|
|
max_unmap_blk_cnt != 0x00L) {
|
|
|
|
softc->unmap_max_lba = max_unmap_lba_cnt;
|
|
|
|
softc->unmap_max_ranges = min(max_unmap_blk_cnt,
|
|
|
|
UNMAP_MAX_RANGES);
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* Unexpected UNMAP limits which means the
|
|
|
|
* device doesn't actually support UNMAP
|
|
|
|
*/
|
|
|
|
dadeleteflag(softc, DA_DELETE_UNMAP, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ws_max_blks != 0x00L)
|
|
|
|
softc->ws_max_blks = ws_max_blks;
|
|
|
|
} else {
|
|
|
|
int error;
|
|
|
|
error = daerror(done_ccb, CAM_RETRY_SELTO,
|
|
|
|
SF_RETRY_UA|SF_NO_PRINT);
|
|
|
|
if (error == ERESTART)
|
|
|
|
return;
|
|
|
|
else if (error != 0) {
|
|
|
|
if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
|
|
|
|
/* Don't wedge this device's queue */
|
|
|
|
cam_release_devq(done_ccb->ccb_h.path,
|
|
|
|
/*relsim_flags*/0,
|
|
|
|
/*reduction*/0,
|
|
|
|
/*timeout*/0,
|
|
|
|
/*getcount_only*/0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Failure here doesn't mean UNMAP is not
|
|
|
|
* supported as this is an optional page.
|
|
|
|
*/
|
|
|
|
softc->unmap_max_lba = 1;
|
|
|
|
softc->unmap_max_ranges = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
free(block_limits, M_SCSIDA);
|
|
|
|
xpt_release_ccb(done_ccb);
|
2013-05-02 14:14:57 +00:00
|
|
|
softc->state = DA_STATE_PROBE_BDC;
|
2013-04-26 16:17:04 +00:00
|
|
|
xpt_schedule(periph, priority);
|
|
|
|
return;
|
|
|
|
}
|
2013-04-26 16:31:03 +00:00
|
|
|
case DA_CCB_PROBE_BDC:
|
|
|
|
{
|
|
|
|
struct scsi_vpd_block_characteristics *bdc;
|
|
|
|
|
|
|
|
bdc = (struct scsi_vpd_block_characteristics *)csio->data_ptr;
|
|
|
|
|
|
|
|
if ((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
|
2013-04-28 21:14:23 +00:00
|
|
|
/*
|
|
|
|
* Disable queue sorting for non-rotational media
|
|
|
|
* by default.
|
|
|
|
*/
|
2013-11-07 23:21:52 +00:00
|
|
|
u_int16_t old_rate = softc->disk->d_rotation_rate;
|
Improve ZFS N-way mirror read performance by using load and locality
information.
The existing algorithm selects a preferred leaf vdev based on offset of the zio
request modulo the number of members in the mirror. It assumes the devices are
of equal performance and that spreading the requests randomly over both drives
will be sufficient to saturate them. In practice this results in the leaf vdevs
being under utilized.
The new algorithm takes into the following additional factors:
* Load of the vdevs (number outstanding I/O requests)
* The locality of last queued I/O vs the new I/O request.
Within the locality calculation additional knowledge about the underlying vdev
is considered such as; is the device backing the vdev a rotating media device.
This results in performance increases across the board as well as significant
increases for predominantly streaming loads and for configurations which don't
have evenly performing devices.
The following are results from a setup with 3 Way Mirror with 2 x HD's and
1 x SSD from a basic test running multiple parrallel dd's.
With pre-fetch disabled (vfs.zfs.prefetch_disable=1):
== Stripe Balanced (default) ==
Read 15360MB using bs: 1048576, readers: 3, took 161 seconds @ 95 MB/s
== Load Balanced (zfslinux) ==
Read 15360MB using bs: 1048576, readers: 3, took 297 seconds @ 51 MB/s
== Load Balanced (locality freebsd) ==
Read 15360MB using bs: 1048576, readers: 3, took 54 seconds @ 284 MB/s
With pre-fetch enabled (vfs.zfs.prefetch_disable=0):
== Stripe Balanced (default) ==
Read 15360MB using bs: 1048576, readers: 3, took 91 seconds @ 168 MB/s
== Load Balanced (zfslinux) ==
Read 15360MB using bs: 1048576, readers: 3, took 108 seconds @ 142 MB/s
== Load Balanced (locality freebsd) ==
Read 15360MB using bs: 1048576, readers: 3, took 48 seconds @ 320 MB/s
In addition to the performance changes the code was also restructured, with
the help of Justin Gibbs, to provide a more logical flow which also ensures
vdevs loads are only calculated from the set of valid candidates.
The following additional sysctls where added to allow the administrator
to tune the behaviour of the load algorithm:
* vfs.zfs.vdev.mirror.rotating_inc
* vfs.zfs.vdev.mirror.rotating_seek_inc
* vfs.zfs.vdev.mirror.rotating_seek_offset
* vfs.zfs.vdev.mirror.non_rotating_inc
* vfs.zfs.vdev.mirror.non_rotating_seek_inc
These changes where based on work started by the zfsonlinux developers:
https://github.com/zfsonlinux/zfs/pull/1487
Reviewed by: gibbs, mav, will
MFC after: 2 weeks
Sponsored by: Multiplay
2013-10-23 09:54:58 +00:00
|
|
|
|
|
|
|
softc->disk->d_rotation_rate =
|
|
|
|
scsi_2btoul(bdc->medium_rotation_rate);
|
|
|
|
if (softc->disk->d_rotation_rate ==
|
|
|
|
SVPD_BDC_RATE_NON_ROTATING) {
|
2013-04-26 16:31:03 +00:00
|
|
|
softc->sort_io_queue = 0;
|
Improve ZFS N-way mirror read performance by using load and locality
information.
The existing algorithm selects a preferred leaf vdev based on offset of the zio
request modulo the number of members in the mirror. It assumes the devices are
of equal performance and that spreading the requests randomly over both drives
will be sufficient to saturate them. In practice this results in the leaf vdevs
being under utilized.
The new algorithm takes into the following additional factors:
* Load of the vdevs (number outstanding I/O requests)
* The locality of last queued I/O vs the new I/O request.
Within the locality calculation additional knowledge about the underlying vdev
is considered such as; is the device backing the vdev a rotating media device.
This results in performance increases across the board as well as significant
increases for predominantly streaming loads and for configurations which don't
have evenly performing devices.
The following are results from a setup with 3 Way Mirror with 2 x HD's and
1 x SSD from a basic test running multiple parrallel dd's.
With pre-fetch disabled (vfs.zfs.prefetch_disable=1):
== Stripe Balanced (default) ==
Read 15360MB using bs: 1048576, readers: 3, took 161 seconds @ 95 MB/s
== Load Balanced (zfslinux) ==
Read 15360MB using bs: 1048576, readers: 3, took 297 seconds @ 51 MB/s
== Load Balanced (locality freebsd) ==
Read 15360MB using bs: 1048576, readers: 3, took 54 seconds @ 284 MB/s
With pre-fetch enabled (vfs.zfs.prefetch_disable=0):
== Stripe Balanced (default) ==
Read 15360MB using bs: 1048576, readers: 3, took 91 seconds @ 168 MB/s
== Load Balanced (zfslinux) ==
Read 15360MB using bs: 1048576, readers: 3, took 108 seconds @ 142 MB/s
== Load Balanced (locality freebsd) ==
Read 15360MB using bs: 1048576, readers: 3, took 48 seconds @ 320 MB/s
In addition to the performance changes the code was also restructured, with
the help of Justin Gibbs, to provide a more logical flow which also ensures
vdevs loads are only calculated from the set of valid candidates.
The following additional sysctls where added to allow the administrator
to tune the behaviour of the load algorithm:
* vfs.zfs.vdev.mirror.rotating_inc
* vfs.zfs.vdev.mirror.rotating_seek_inc
* vfs.zfs.vdev.mirror.rotating_seek_offset
* vfs.zfs.vdev.mirror.non_rotating_inc
* vfs.zfs.vdev.mirror.non_rotating_seek_inc
These changes where based on work started by the zfsonlinux developers:
https://github.com/zfsonlinux/zfs/pull/1487
Reviewed by: gibbs, mav, will
MFC after: 2 weeks
Sponsored by: Multiplay
2013-10-23 09:54:58 +00:00
|
|
|
}
|
|
|
|
if (softc->disk->d_rotation_rate != old_rate) {
|
|
|
|
disk_attr_changed(softc->disk,
|
|
|
|
"GEOM::rotation_rate", M_NOWAIT);
|
|
|
|
}
|
2013-04-26 16:31:03 +00:00
|
|
|
} else {
|
|
|
|
int error;
|
|
|
|
error = daerror(done_ccb, CAM_RETRY_SELTO,
|
|
|
|
SF_RETRY_UA|SF_NO_PRINT);
|
|
|
|
if (error == ERESTART)
|
|
|
|
return;
|
|
|
|
else if (error != 0) {
|
|
|
|
if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
|
|
|
|
/* Don't wedge this device's queue */
|
|
|
|
cam_release_devq(done_ccb->ccb_h.path,
|
|
|
|
/*relsim_flags*/0,
|
|
|
|
/*reduction*/0,
|
|
|
|
/*timeout*/0,
|
|
|
|
/*getcount_only*/0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
free(bdc, M_SCSIDA);
|
|
|
|
xpt_release_ccb(done_ccb);
|
2013-05-02 14:14:57 +00:00
|
|
|
softc->state = DA_STATE_PROBE_ATA;
|
2013-04-26 16:31:03 +00:00
|
|
|
xpt_schedule(periph, priority);
|
|
|
|
return;
|
|
|
|
}
|
2013-04-26 16:17:04 +00:00
|
|
|
case DA_CCB_PROBE_ATA:
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
struct ata_params *ata_params;
|
|
|
|
int16_t *ptr;
|
|
|
|
|
|
|
|
ata_params = (struct ata_params *)csio->data_ptr;
|
|
|
|
ptr = (uint16_t *)ata_params;
|
|
|
|
|
|
|
|
if ((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
|
Improve ZFS N-way mirror read performance by using load and locality
information.
The existing algorithm selects a preferred leaf vdev based on offset of the zio
request modulo the number of members in the mirror. It assumes the devices are
of equal performance and that spreading the requests randomly over both drives
will be sufficient to saturate them. In practice this results in the leaf vdevs
being under utilized.
The new algorithm takes into the following additional factors:
* Load of the vdevs (number outstanding I/O requests)
* The locality of last queued I/O vs the new I/O request.
Within the locality calculation additional knowledge about the underlying vdev
is considered such as; is the device backing the vdev a rotating media device.
This results in performance increases across the board as well as significant
increases for predominantly streaming loads and for configurations which don't
have evenly performing devices.
The following are results from a setup with 3 Way Mirror with 2 x HD's and
1 x SSD from a basic test running multiple parrallel dd's.
With pre-fetch disabled (vfs.zfs.prefetch_disable=1):
== Stripe Balanced (default) ==
Read 15360MB using bs: 1048576, readers: 3, took 161 seconds @ 95 MB/s
== Load Balanced (zfslinux) ==
Read 15360MB using bs: 1048576, readers: 3, took 297 seconds @ 51 MB/s
== Load Balanced (locality freebsd) ==
Read 15360MB using bs: 1048576, readers: 3, took 54 seconds @ 284 MB/s
With pre-fetch enabled (vfs.zfs.prefetch_disable=0):
== Stripe Balanced (default) ==
Read 15360MB using bs: 1048576, readers: 3, took 91 seconds @ 168 MB/s
== Load Balanced (zfslinux) ==
Read 15360MB using bs: 1048576, readers: 3, took 108 seconds @ 142 MB/s
== Load Balanced (locality freebsd) ==
Read 15360MB using bs: 1048576, readers: 3, took 48 seconds @ 320 MB/s
In addition to the performance changes the code was also restructured, with
the help of Justin Gibbs, to provide a more logical flow which also ensures
vdevs loads are only calculated from the set of valid candidates.
The following additional sysctls where added to allow the administrator
to tune the behaviour of the load algorithm:
* vfs.zfs.vdev.mirror.rotating_inc
* vfs.zfs.vdev.mirror.rotating_seek_inc
* vfs.zfs.vdev.mirror.rotating_seek_offset
* vfs.zfs.vdev.mirror.non_rotating_inc
* vfs.zfs.vdev.mirror.non_rotating_seek_inc
These changes where based on work started by the zfsonlinux developers:
https://github.com/zfsonlinux/zfs/pull/1487
Reviewed by: gibbs, mav, will
MFC after: 2 weeks
Sponsored by: Multiplay
2013-10-23 09:54:58 +00:00
|
|
|
uint16_t old_rate;
|
|
|
|
|
2013-04-26 16:17:04 +00:00
|
|
|
for (i = 0; i < sizeof(*ata_params) / 2; i++)
|
|
|
|
ptr[i] = le16toh(ptr[i]);
|
2014-04-23 19:50:35 +00:00
|
|
|
if (ata_params->support_dsm & ATA_SUPPORT_DSM_TRIM &&
|
|
|
|
(softc->quirks & DA_Q_NO_UNMAP) == 0) {
|
2013-04-26 16:17:04 +00:00
|
|
|
dadeleteflag(softc, DA_DELETE_ATA_TRIM, 1);
|
|
|
|
if (ata_params->max_dsm_blocks != 0)
|
|
|
|
softc->trim_max_ranges = min(
|
|
|
|
softc->trim_max_ranges,
|
|
|
|
ata_params->max_dsm_blocks *
|
|
|
|
ATA_DSM_BLK_RANGES);
|
|
|
|
}
|
2013-04-26 16:31:03 +00:00
|
|
|
/*
|
2013-04-28 21:14:23 +00:00
|
|
|
* Disable queue sorting for non-rotational media
|
|
|
|
* by default.
|
2013-04-26 16:31:03 +00:00
|
|
|
*/
|
Improve ZFS N-way mirror read performance by using load and locality
information.
The existing algorithm selects a preferred leaf vdev based on offset of the zio
request modulo the number of members in the mirror. It assumes the devices are
of equal performance and that spreading the requests randomly over both drives
will be sufficient to saturate them. In practice this results in the leaf vdevs
being under utilized.
The new algorithm takes into the following additional factors:
* Load of the vdevs (number outstanding I/O requests)
* The locality of last queued I/O vs the new I/O request.
Within the locality calculation additional knowledge about the underlying vdev
is considered such as; is the device backing the vdev a rotating media device.
This results in performance increases across the board as well as significant
increases for predominantly streaming loads and for configurations which don't
have evenly performing devices.
The following are results from a setup with 3 Way Mirror with 2 x HD's and
1 x SSD from a basic test running multiple parrallel dd's.
With pre-fetch disabled (vfs.zfs.prefetch_disable=1):
== Stripe Balanced (default) ==
Read 15360MB using bs: 1048576, readers: 3, took 161 seconds @ 95 MB/s
== Load Balanced (zfslinux) ==
Read 15360MB using bs: 1048576, readers: 3, took 297 seconds @ 51 MB/s
== Load Balanced (locality freebsd) ==
Read 15360MB using bs: 1048576, readers: 3, took 54 seconds @ 284 MB/s
With pre-fetch enabled (vfs.zfs.prefetch_disable=0):
== Stripe Balanced (default) ==
Read 15360MB using bs: 1048576, readers: 3, took 91 seconds @ 168 MB/s
== Load Balanced (zfslinux) ==
Read 15360MB using bs: 1048576, readers: 3, took 108 seconds @ 142 MB/s
== Load Balanced (locality freebsd) ==
Read 15360MB using bs: 1048576, readers: 3, took 48 seconds @ 320 MB/s
In addition to the performance changes the code was also restructured, with
the help of Justin Gibbs, to provide a more logical flow which also ensures
vdevs loads are only calculated from the set of valid candidates.
The following additional sysctls where added to allow the administrator
to tune the behaviour of the load algorithm:
* vfs.zfs.vdev.mirror.rotating_inc
* vfs.zfs.vdev.mirror.rotating_seek_inc
* vfs.zfs.vdev.mirror.rotating_seek_offset
* vfs.zfs.vdev.mirror.non_rotating_inc
* vfs.zfs.vdev.mirror.non_rotating_seek_inc
These changes where based on work started by the zfsonlinux developers:
https://github.com/zfsonlinux/zfs/pull/1487
Reviewed by: gibbs, mav, will
MFC after: 2 weeks
Sponsored by: Multiplay
2013-10-23 09:54:58 +00:00
|
|
|
old_rate = softc->disk->d_rotation_rate;
|
|
|
|
softc->disk->d_rotation_rate =
|
|
|
|
ata_params->media_rotation_rate;
|
|
|
|
if (softc->disk->d_rotation_rate ==
|
|
|
|
ATA_RATE_NON_ROTATING) {
|
2013-04-26 16:31:03 +00:00
|
|
|
softc->sort_io_queue = 0;
|
Improve ZFS N-way mirror read performance by using load and locality
information.
The existing algorithm selects a preferred leaf vdev based on offset of the zio
request modulo the number of members in the mirror. It assumes the devices are
of equal performance and that spreading the requests randomly over both drives
will be sufficient to saturate them. In practice this results in the leaf vdevs
being under utilized.
The new algorithm takes into the following additional factors:
* Load of the vdevs (number outstanding I/O requests)
* The locality of last queued I/O vs the new I/O request.
Within the locality calculation additional knowledge about the underlying vdev
is considered such as; is the device backing the vdev a rotating media device.
This results in performance increases across the board as well as significant
increases for predominantly streaming loads and for configurations which don't
have evenly performing devices.
The following are results from a setup with 3 Way Mirror with 2 x HD's and
1 x SSD from a basic test running multiple parrallel dd's.
With pre-fetch disabled (vfs.zfs.prefetch_disable=1):
== Stripe Balanced (default) ==
Read 15360MB using bs: 1048576, readers: 3, took 161 seconds @ 95 MB/s
== Load Balanced (zfslinux) ==
Read 15360MB using bs: 1048576, readers: 3, took 297 seconds @ 51 MB/s
== Load Balanced (locality freebsd) ==
Read 15360MB using bs: 1048576, readers: 3, took 54 seconds @ 284 MB/s
With pre-fetch enabled (vfs.zfs.prefetch_disable=0):
== Stripe Balanced (default) ==
Read 15360MB using bs: 1048576, readers: 3, took 91 seconds @ 168 MB/s
== Load Balanced (zfslinux) ==
Read 15360MB using bs: 1048576, readers: 3, took 108 seconds @ 142 MB/s
== Load Balanced (locality freebsd) ==
Read 15360MB using bs: 1048576, readers: 3, took 48 seconds @ 320 MB/s
In addition to the performance changes the code was also restructured, with
the help of Justin Gibbs, to provide a more logical flow which also ensures
vdevs loads are only calculated from the set of valid candidates.
The following additional sysctls where added to allow the administrator
to tune the behaviour of the load algorithm:
* vfs.zfs.vdev.mirror.rotating_inc
* vfs.zfs.vdev.mirror.rotating_seek_inc
* vfs.zfs.vdev.mirror.rotating_seek_offset
* vfs.zfs.vdev.mirror.non_rotating_inc
* vfs.zfs.vdev.mirror.non_rotating_seek_inc
These changes where based on work started by the zfsonlinux developers:
https://github.com/zfsonlinux/zfs/pull/1487
Reviewed by: gibbs, mav, will
MFC after: 2 weeks
Sponsored by: Multiplay
2013-10-23 09:54:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (softc->disk->d_rotation_rate != old_rate) {
|
|
|
|
disk_attr_changed(softc->disk,
|
|
|
|
"GEOM::rotation_rate", M_NOWAIT);
|
|
|
|
}
|
2013-04-26 16:17:04 +00:00
|
|
|
} else {
|
|
|
|
int error;
|
|
|
|
error = daerror(done_ccb, CAM_RETRY_SELTO,
|
2013-05-02 14:37:23 +00:00
|
|
|
SF_RETRY_UA|SF_NO_PRINT);
|
2013-04-26 16:17:04 +00:00
|
|
|
if (error == ERESTART)
|
|
|
|
return;
|
|
|
|
else if (error != 0) {
|
|
|
|
if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
|
|
|
|
/* Don't wedge this device's queue */
|
|
|
|
cam_release_devq(done_ccb->ccb_h.path,
|
|
|
|
/*relsim_flags*/0,
|
|
|
|
/*reduction*/0,
|
|
|
|
/*timeout*/0,
|
|
|
|
/*getcount_only*/0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
free(ata_params, M_SCSIDA);
|
2013-05-02 14:37:23 +00:00
|
|
|
daprobedone(periph, done_ccb);
|
1999-01-07 20:19:09 +00:00
|
|
|
return;
|
1998-09-15 06:36:34 +00:00
|
|
|
}
|
|
|
|
case DA_CCB_DUMP:
|
|
|
|
/* No-op. We're polling */
|
|
|
|
return;
|
2012-07-29 11:51:48 +00:00
|
|
|
case DA_CCB_TUR:
|
|
|
|
{
|
|
|
|
if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
|
|
|
|
|
|
|
|
if (daerror(done_ccb, CAM_RETRY_SELTO,
|
|
|
|
SF_RETRY_UA | SF_NO_RECOVERY | SF_NO_PRINT) ==
|
|
|
|
ERESTART)
|
|
|
|
return;
|
|
|
|
if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
|
|
|
|
cam_release_devq(done_ccb->ccb_h.path,
|
|
|
|
/*relsim_flags*/0,
|
|
|
|
/*reduction*/0,
|
|
|
|
/*timeout*/0,
|
|
|
|
/*getcount_only*/0);
|
|
|
|
}
|
|
|
|
xpt_release_ccb(done_ccb);
|
|
|
|
cam_periph_release_locked(periph);
|
|
|
|
return;
|
|
|
|
}
|
1999-01-07 20:19:09 +00:00
|
|
|
default:
|
|
|
|
break;
|
1998-09-15 06:36:34 +00:00
|
|
|
}
|
1999-01-07 20:19:09 +00:00
|
|
|
xpt_release_ccb(done_ccb);
|
1998-09-15 06:36:34 +00:00
|
|
|
}
|
|
|
|
|
2012-04-12 12:58:14 +00:00
|
|
|
static void
|
|
|
|
dareprobe(struct cam_periph *periph)
|
|
|
|
{
|
|
|
|
struct da_softc *softc;
|
|
|
|
cam_status status;
|
|
|
|
|
|
|
|
softc = (struct da_softc *)periph->softc;
|
|
|
|
|
|
|
|
/* Probe in progress; don't interfere. */
|
2013-05-02 14:19:42 +00:00
|
|
|
if (softc->state != DA_STATE_NORMAL)
|
2012-04-12 12:58:14 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
status = cam_periph_acquire(periph);
|
|
|
|
KASSERT(status == CAM_REQ_CMP,
|
|
|
|
("dareprobe: cam_periph_acquire failed"));
|
|
|
|
|
|
|
|
if (softc->flags & DA_FLAG_CAN_RC16)
|
2013-04-26 16:17:04 +00:00
|
|
|
softc->state = DA_STATE_PROBE_RC16;
|
2012-04-12 12:58:14 +00:00
|
|
|
else
|
2013-04-26 16:17:04 +00:00
|
|
|
softc->state = DA_STATE_PROBE_RC;
|
2012-04-12 12:58:14 +00:00
|
|
|
|
|
|
|
xpt_schedule(periph, CAM_PRIORITY_DEV);
|
|
|
|
}
|
|
|
|
|
1998-09-15 06:36:34 +00:00
|
|
|
static int
|
|
|
|
daerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags)
|
|
|
|
{
|
|
|
|
struct da_softc *softc;
|
|
|
|
struct cam_periph *periph;
|
2012-06-23 12:32:53 +00:00
|
|
|
int error, error_code, sense_key, asc, ascq;
|
1998-09-15 06:36:34 +00:00
|
|
|
|
|
|
|
periph = xpt_path_periph(ccb->ccb_h.path);
|
|
|
|
softc = (struct da_softc *)periph->softc;
|
|
|
|
|
2002-03-23 18:18:02 +00:00
|
|
|
/*
|
|
|
|
* Automatically detect devices that do not support
|
|
|
|
* READ(6)/WRITE(6) and upgrade to using 10 byte cdbs.
|
|
|
|
*/
|
|
|
|
error = 0;
|
Fix ATAPI/USB/Firewire CDROM drive handling in cd(4) and hopefully fix
a number of related problems along the way.
- Automatically detect CDROM drives that can't handle 6 byte mode
sense and mode select, and adjust our command size accordingly.
We have to handle this in the cd(4) driver (where the buffers are
allocated), since the parameter list length is different for the
6 and 10 byte mode sense commands.
- Remove MODE_SENSE and MODE_SELECT translation removed in ATAPICAM
and in the umass(4) driver, since there's no way for that to work
properly.
- Add a quirk entry for CDROM drives that just hang when they get a 6
byte mode sense or mode select. The reason for the quirk must be
documented in a PR, and all quirks must be approved by
ken@FreeBSD.org. This is to make sure that we fully understand why
each quirk is needed. Once the CAM_NEW_TRAN_CODE is finished, we
should be able to remove any such quirks, since we'll know what
protocol the drive speaks (SCSI, ATAPI, etc.) and therefore whether
we should use 6 or 10 byte mode sense/select commands.
- Change the way the da(4) handles the no_6_byte sysctl. There is
now a per-drive sysctl to set the minimum command size for that
particular disk. (Since you could have multiple disks with
multiple requirements in one system.)
- Loader tunable support for all the sysctls in the da(4) and cd(4)
drivers.
- Add a CDIOCCLOSE ioctl for cd(4) (bde pointed this out a long
time ago).
- Add a media validation routine (cdcheckmedia()) to the cd(4)
driver, to fix some problems bde pointed out a long time ago. We
now allow open() to succeed no matter what, but if we don't detect
valid media, the user can only issue CDIOCCLOSE or CDIOCEJECT
ioctls.
- The media validation routine also reads the table of contents off
the drive. We use the table of contents to implement the
CDIOCPLAYTRACKS ioctl using the PLAY AUDIO MSF command. The
PLAY AUDIO TRACK INDEX command that we previously used was
deprecated after SCSI-2. It works in every SCSI CDROM I've tried,
but doesn't seem to work on ATAPI CDROM drives. We still use the
play audio track index command if we don't have a valid TOC, but
I suppose it'll fail anyway in that case.
- Add _len() versions of scsi_mode_sense() and scsi_mode_select() so
that we can specify the minimum command length.
- Fix a couple of formatting problems in the sense printing code.
MFC after: 4 weeks
2003-02-21 06:19:38 +00:00
|
|
|
if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INVALID) {
|
|
|
|
error = cmd6workaround(ccb);
|
2012-06-23 12:32:53 +00:00
|
|
|
} else if (scsi_extract_sense_ccb(ccb,
|
|
|
|
&error_code, &sense_key, &asc, &ascq)) {
|
2002-03-23 18:18:02 +00:00
|
|
|
if (sense_key == SSD_KEY_ILLEGAL_REQUEST)
|
|
|
|
error = cmd6workaround(ccb);
|
2012-04-12 12:58:14 +00:00
|
|
|
/*
|
|
|
|
* If the target replied with CAPACITY DATA HAS CHANGED UA,
|
|
|
|
* query the capacity and notify upper layers.
|
|
|
|
*/
|
|
|
|
else if (sense_key == SSD_KEY_UNIT_ATTENTION &&
|
|
|
|
asc == 0x2A && ascq == 0x09) {
|
2014-04-30 17:38:26 +00:00
|
|
|
xpt_print(periph->path, "Capacity data has changed\n");
|
|
|
|
softc->flags &= ~DA_FLAG_PROBED;
|
2012-04-12 12:58:14 +00:00
|
|
|
dareprobe(periph);
|
|
|
|
sense_flags |= SF_NO_PRINT;
|
2012-07-29 11:51:48 +00:00
|
|
|
} else if (sense_key == SSD_KEY_UNIT_ATTENTION &&
|
2014-04-30 17:38:26 +00:00
|
|
|
asc == 0x28 && ascq == 0x00) {
|
|
|
|
softc->flags &= ~DA_FLAG_PROBED;
|
2012-07-29 11:51:48 +00:00
|
|
|
disk_media_changed(softc->disk, M_NOWAIT);
|
2014-04-30 17:38:26 +00:00
|
|
|
} else if (sense_key == SSD_KEY_UNIT_ATTENTION &&
|
|
|
|
asc == 0x3F && ascq == 0x03) {
|
|
|
|
xpt_print(periph->path, "INQUIRY data has changed\n");
|
|
|
|
softc->flags &= ~DA_FLAG_PROBED;
|
|
|
|
dareprobe(periph);
|
|
|
|
sense_flags |= SF_NO_PRINT;
|
|
|
|
} else if (sense_key == SSD_KEY_NOT_READY &&
|
2013-05-03 11:53:06 +00:00
|
|
|
asc == 0x3a && (softc->flags & DA_FLAG_PACK_INVALID) == 0) {
|
|
|
|
softc->flags |= DA_FLAG_PACK_INVALID;
|
2012-07-29 11:51:48 +00:00
|
|
|
disk_media_gone(softc->disk, M_NOWAIT);
|
2012-04-12 12:58:14 +00:00
|
|
|
}
|
2002-03-23 18:18:02 +00:00
|
|
|
}
|
|
|
|
if (error == ERESTART)
|
2002-08-16 22:05:19 +00:00
|
|
|
return (ERESTART);
|
2002-03-23 18:18:02 +00:00
|
|
|
|
1998-09-20 07:17:11 +00:00
|
|
|
/*
|
|
|
|
* XXX
|
|
|
|
* Until we have a better way of doing pack validation,
|
|
|
|
* don't treat UAs as errors.
|
|
|
|
*/
|
|
|
|
sense_flags |= SF_RETRY_UA;
|
2015-02-02 20:23:05 +00:00
|
|
|
|
|
|
|
if (softc->quirks & DA_Q_RETRY_BUSY)
|
|
|
|
sense_flags |= SF_RETRY_BUSY;
|
1998-09-15 06:36:34 +00:00
|
|
|
return(cam_periph_error(ccb, cam_flags, sense_flags,
|
|
|
|
&softc->saved_ccb));
|
|
|
|
}
|
|
|
|
|
2012-07-29 11:51:48 +00:00
|
|
|
static void
|
|
|
|
damediapoll(void *arg)
|
|
|
|
{
|
|
|
|
struct cam_periph *periph = arg;
|
|
|
|
struct da_softc *softc = periph->softc;
|
|
|
|
|
2013-10-24 14:05:44 +00:00
|
|
|
if (!softc->tur && LIST_EMPTY(&softc->pending_ccbs)) {
|
2012-07-29 11:51:48 +00:00
|
|
|
if (cam_periph_acquire(periph) == CAM_REQ_CMP) {
|
|
|
|
softc->tur = 1;
|
|
|
|
daschedule(periph);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* Queue us up again */
|
|
|
|
if (da_poll_period != 0)
|
|
|
|
callout_schedule(&softc->mediapoll_c, da_poll_period * hz);
|
|
|
|
}
|
|
|
|
|
1998-09-15 06:36:34 +00:00
|
|
|
static void
|
|
|
|
daprevent(struct cam_periph *periph, int action)
|
|
|
|
{
|
|
|
|
struct da_softc *softc;
|
|
|
|
union ccb *ccb;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
softc = (struct da_softc *)periph->softc;
|
|
|
|
|
|
|
|
if (((action == PR_ALLOW)
|
|
|
|
&& (softc->flags & DA_FLAG_PACK_LOCKED) == 0)
|
|
|
|
|| ((action == PR_PREVENT)
|
|
|
|
&& (softc->flags & DA_FLAG_PACK_LOCKED) != 0)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-10-23 08:27:55 +00:00
|
|
|
ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
|
1998-09-15 06:36:34 +00:00
|
|
|
|
|
|
|
scsi_prevent(&ccb->csio,
|
|
|
|
/*retries*/1,
|
|
|
|
/*cbcfp*/dadone,
|
|
|
|
MSG_SIMPLE_Q_TAG,
|
|
|
|
action,
|
|
|
|
SSD_FULL_SIZE,
|
|
|
|
5000);
|
|
|
|
|
2012-06-05 10:08:22 +00:00
|
|
|
error = cam_periph_runccb(ccb, daerror, CAM_RETRY_SELTO,
|
2013-05-12 09:33:33 +00:00
|
|
|
SF_RETRY_UA | SF_NO_PRINT, softc->disk->d_devstat);
|
1998-09-15 06:36:34 +00:00
|
|
|
|
|
|
|
if (error == 0) {
|
|
|
|
if (action == PR_ALLOW)
|
|
|
|
softc->flags &= ~DA_FLAG_PACK_LOCKED;
|
|
|
|
else
|
|
|
|
softc->flags |= DA_FLAG_PACK_LOCKED;
|
|
|
|
}
|
|
|
|
|
|
|
|
xpt_release_ccb(ccb);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2011-12-23 00:10:17 +00:00
|
|
|
dasetgeom(struct cam_periph *periph, uint32_t block_len, uint64_t maxsector,
|
2012-01-26 18:09:28 +00:00
|
|
|
struct scsi_read_capacity_data_long *rcaplong, size_t rcap_len)
|
1998-09-15 06:36:34 +00:00
|
|
|
{
|
|
|
|
struct ccb_calc_geometry ccg;
|
|
|
|
struct da_softc *softc;
|
|
|
|
struct disk_params *dp;
|
2012-01-26 18:09:28 +00:00
|
|
|
u_int lbppbe, lalba;
|
2012-10-29 17:52:43 +00:00
|
|
|
int error;
|
1998-09-15 06:36:34 +00:00
|
|
|
|
|
|
|
softc = (struct da_softc *)periph->softc;
|
|
|
|
|
|
|
|
dp = &softc->params;
|
Add support to CAM for devices with more than 2^32 blocks. (2TB if you're
using 512 byte blocks).
cam_ccb.h: Bump up volume_size and cylinders in ccb_calc_geometry to
64 bits and 32 bits respectively, so we can hold larger
device sizes. cylinders would overflow at about 500GB.
Bump CAM_VERSION for this change. Note that this will
require a recompile of all applications that talk to the
pass(4) driver.
scsi_all.c: Add descriptions for READ/WRITE(16), update READ/WRITE(12)
descriptions, add descriptions for SERVICE ACTION IN/OUT.
Add a new function, scsi_read_capacity_16(), that issues
the read capacity service action. (Necessary for arrays
larger than 2^32 sectors.) Update scsi_read_write() to use
a 64 bit LBA and issue READ(16) or WRITE(16) if necessary.
NOTE the API change. This should be largely transparnet
to most userland applications at compile time, but will
break binary compatibility. The CAM_VERSION bump, above,
also serves the purpose of forcing a recompile for any
applications that talk to CAM.
scsi_all.h: Add 16 byte READ/WRITE structures, structures for 16 byte
READ CAPACITY/SERVICE ACTION IN. Add scsi_u64to8b() and
scsi_8btou64.
scsi_da.c: The da(4) driver probe now has two stages for devices
larger than 2TB. If a standard READ CAPACITY(10) returns
0xffffffff, we issue the 16 byte version of read capacity
to determine the true array capacity. We also do the same
thing in daopen() -- use the 16 byte read capacity if the
device is large enough.
The sysctl/loader code has also been updated to accept
16 bytes as a minimum command size.
2003-04-30 00:35:22 +00:00
|
|
|
dp->secsize = block_len;
|
|
|
|
dp->sectors = maxsector + 1;
|
2012-01-26 18:09:28 +00:00
|
|
|
if (rcaplong != NULL) {
|
|
|
|
lbppbe = rcaplong->prot_lbppbe & SRC16_LBPPBE;
|
|
|
|
lalba = scsi_2btoul(rcaplong->lalba_lbp);
|
|
|
|
lalba &= SRC16_LALBA_A;
|
|
|
|
} else {
|
|
|
|
lbppbe = 0;
|
|
|
|
lalba = 0;
|
|
|
|
}
|
|
|
|
|
2011-12-23 00:10:17 +00:00
|
|
|
if (lbppbe > 0) {
|
|
|
|
dp->stripesize = block_len << lbppbe;
|
2011-12-23 20:59:13 +00:00
|
|
|
dp->stripeoffset = (dp->stripesize - block_len * lalba) %
|
|
|
|
dp->stripesize;
|
2011-12-23 00:10:17 +00:00
|
|
|
} else if (softc->quirks & DA_Q_4K) {
|
|
|
|
dp->stripesize = 4096;
|
|
|
|
dp->stripeoffset = 0;
|
|
|
|
} else {
|
|
|
|
dp->stripesize = 0;
|
|
|
|
dp->stripeoffset = 0;
|
|
|
|
}
|
1998-09-15 06:36:34 +00:00
|
|
|
/*
|
|
|
|
* Have the controller provide us with a geometry
|
|
|
|
* for this disk. The only time the geometry
|
|
|
|
* matters is when we boot and the controller
|
|
|
|
* is the only one knowledgeable enough to come
|
|
|
|
* up with something that will make this a bootable
|
|
|
|
* device.
|
|
|
|
*/
|
2009-10-23 08:27:55 +00:00
|
|
|
xpt_setup_ccb(&ccg.ccb_h, periph->path, CAM_PRIORITY_NORMAL);
|
1998-09-15 06:36:34 +00:00
|
|
|
ccg.ccb_h.func_code = XPT_CALC_GEOMETRY;
|
|
|
|
ccg.block_size = dp->secsize;
|
|
|
|
ccg.volume_size = dp->sectors;
|
|
|
|
ccg.heads = 0;
|
|
|
|
ccg.secs_per_track = 0;
|
|
|
|
ccg.cylinders = 0;
|
|
|
|
xpt_action((union ccb*)&ccg);
|
2006-04-18 22:01:59 +00:00
|
|
|
if ((ccg.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
|
|
|
|
/*
|
|
|
|
* We don't know what went wrong here- but just pick
|
|
|
|
* a geometry so we don't have nasty things like divide
|
|
|
|
* by zero.
|
|
|
|
*/
|
|
|
|
dp->heads = 255;
|
|
|
|
dp->secs_per_track = 255;
|
|
|
|
dp->cylinders = dp->sectors / (255 * 255);
|
|
|
|
if (dp->cylinders == 0) {
|
|
|
|
dp->cylinders = 1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
dp->heads = ccg.heads;
|
|
|
|
dp->secs_per_track = ccg.secs_per_track;
|
|
|
|
dp->cylinders = ccg.cylinders;
|
|
|
|
}
|
2012-01-26 18:09:28 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If the user supplied a read capacity buffer, and if it is
|
|
|
|
* different than the previous buffer, update the data in the EDT.
|
|
|
|
* If it's the same, we don't bother. This avoids sending an
|
|
|
|
* update every time someone opens this device.
|
|
|
|
*/
|
|
|
|
if ((rcaplong != NULL)
|
|
|
|
&& (bcmp(rcaplong, &softc->rcaplong,
|
|
|
|
min(sizeof(softc->rcaplong), rcap_len)) != 0)) {
|
|
|
|
struct ccb_dev_advinfo cdai;
|
|
|
|
|
|
|
|
xpt_setup_ccb(&cdai.ccb_h, periph->path, CAM_PRIORITY_NORMAL);
|
|
|
|
cdai.ccb_h.func_code = XPT_DEV_ADVINFO;
|
|
|
|
cdai.buftype = CDAI_TYPE_RCAPLONG;
|
Make sure that the flags for the XPT_DEV_ADVINFO CCB are initialized
properly.
If there is garbage in the flags field, it can sometimes include a
set CDAI_FLAG_STORE flag, which may cause either an error or
perhaps result in overwriting the field that was intended to be
read.
sys/cam/cam_ccb.h:
Add a new flag to the XPT_DEV_ADVINFO CCB, CDAI_FLAG_NONE,
that callers can use to set the flags field when no store
is desired.
sys/cam/scsi/scsi_enc_ses.c:
In ses_setphyspath_callback(), explicitly set the
XPT_DEV_ADVINFO flags to CDAI_FLAG_NONE when fetching the
physical path information. Instead of ORing in the
CDAI_FLAG_STORE flag when storing the physical path, set
the flags field to CDAI_FLAG_STORE.
sys/cam/scsi/scsi_sa.c:
Set the XPT_DEV_ADVINFO flags field to CDAI_FLAG_NONE when
fetching extended inquiry information.
sys/cam/scsi/scsi_da.c:
When storing extended READ CAPACITY information, set the
XPT_DEV_ADVINFO flags field to CDAI_FLAG_STORE instead of
ORing it into a field that isn't initialized.
sys/dev/mpr/mpr_sas.c,
sys/dev/mps/mps_sas.c:
When fetching extended READ CAPACITY information, set the
XPT_DEV_ADVINFO flags field to CDAI_FLAG_NONE instead of
setting it to 0.
sbin/camcontrol/camcontrol.c:
When fetching a device ID, set the XPT_DEV_ADVINFO flags
field to CDAI_FLAG_NONE instead of 0.
sys/sys/param.h:
Bump __FreeBSD_version to 1100061 for the new XPT_DEV_ADVINFO
CCB flag, CDAI_FLAG_NONE.
Sponsored by: Spectra Logic
MFC after: 1 week
2015-02-18 18:30:19 +00:00
|
|
|
cdai.flags = CDAI_FLAG_STORE;
|
2012-01-26 18:09:28 +00:00
|
|
|
cdai.bufsiz = rcap_len;
|
|
|
|
cdai.buf = (uint8_t *)rcaplong;
|
|
|
|
xpt_action((union ccb *)&cdai);
|
|
|
|
if ((cdai.ccb_h.status & CAM_DEV_QFRZN) != 0)
|
|
|
|
cam_release_devq(cdai.ccb_h.path, 0, 0, 0, FALSE);
|
|
|
|
if (cdai.ccb_h.status != CAM_REQ_CMP) {
|
|
|
|
xpt_print(periph->path, "%s: failed to set read "
|
|
|
|
"capacity advinfo\n", __func__);
|
|
|
|
/* Use cam_error_print() to decode the status */
|
|
|
|
cam_error_print((union ccb *)&cdai, CAM_ESF_CAM_STATUS,
|
|
|
|
CAM_EPF_ALL);
|
|
|
|
} else {
|
|
|
|
bcopy(rcaplong, &softc->rcaplong,
|
|
|
|
min(sizeof(softc->rcaplong), rcap_len));
|
|
|
|
}
|
|
|
|
}
|
2012-04-12 12:58:14 +00:00
|
|
|
|
|
|
|
softc->disk->d_sectorsize = softc->params.secsize;
|
|
|
|
softc->disk->d_mediasize = softc->params.secsize * (off_t)softc->params.sectors;
|
|
|
|
softc->disk->d_stripesize = softc->params.stripesize;
|
|
|
|
softc->disk->d_stripeoffset = softc->params.stripeoffset;
|
|
|
|
/* XXX: these are not actually "firmware" values, so they may be wrong */
|
|
|
|
softc->disk->d_fwsectors = softc->params.secs_per_track;
|
|
|
|
softc->disk->d_fwheads = softc->params.heads;
|
|
|
|
softc->disk->d_devstat->block_size = softc->params.secsize;
|
|
|
|
softc->disk->d_devstat->flags &= ~DEVSTAT_BS_UNAVAILABLE;
|
2012-07-07 22:19:51 +00:00
|
|
|
|
2012-10-29 17:52:43 +00:00
|
|
|
error = disk_resize(softc->disk, M_NOWAIT);
|
|
|
|
if (error != 0)
|
|
|
|
xpt_print(periph->path, "disk_resize(9) failed, error = %d\n", error);
|
1998-09-15 06:36:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
dasendorderedtag(void *arg)
|
|
|
|
{
|
2007-04-15 08:49:19 +00:00
|
|
|
struct da_softc *softc = arg;
|
1998-09-15 06:36:34 +00:00
|
|
|
|
2007-04-15 08:49:19 +00:00
|
|
|
if (da_send_ordered) {
|
2013-10-24 14:05:44 +00:00
|
|
|
if (!LIST_EMPTY(&softc->pending_ccbs)) {
|
|
|
|
if ((softc->flags & DA_FLAG_WAS_OTAG) == 0)
|
|
|
|
softc->flags |= DA_FLAG_NEED_OTAG;
|
|
|
|
softc->flags &= ~DA_FLAG_WAS_OTAG;
|
1998-09-15 06:36:34 +00:00
|
|
|
}
|
|
|
|
}
|
2007-04-15 08:49:19 +00:00
|
|
|
/* Queue us up again */
|
|
|
|
callout_reset(&softc->sendordered_c,
|
2012-02-02 19:02:15 +00:00
|
|
|
(da_default_timeout * hz) / DA_ORDEREDTAG_INTERVAL,
|
2007-04-15 08:49:19 +00:00
|
|
|
dasendorderedtag, softc);
|
1998-09-15 06:36:34 +00:00
|
|
|
}
|
1998-10-08 05:46:38 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Step through all DA peripheral drivers, and if the device is still open,
|
|
|
|
* sync the disk cache to physical media.
|
|
|
|
*/
|
|
|
|
static void
|
1999-08-21 06:24:40 +00:00
|
|
|
dashutdown(void * arg, int howto)
|
1998-10-08 05:46:38 +00:00
|
|
|
{
|
|
|
|
struct cam_periph *periph;
|
|
|
|
struct da_softc *softc;
|
2013-03-29 08:33:18 +00:00
|
|
|
union ccb *ccb;
|
One more major cam_periph_error() rewrite to improve error handling and
reporting. It includes:
- removing of error messages controlled by bootverbose, replacing them
with more universal and informative debugging on CAM_DEBUG_INFO level,
that is now built into the kernel by default;
- more close following to the arguments submitted by caller, such as
SF_PRINT_ALWAYS, SF_QUIET_IR and SF_NO_PRINT; consumer knows better which
errors are usual/expected at this point and which are really informative;
- adding two new flags SF_NO_RECOVERY and SF_NO_RETRY to allow caller
specify how much assistance it needs at this point; previously consumers
controlled that by not calling cam_periph_error() at all, but that made
behavior inconsistent and debugging complicated;
- tuning debug messages and taken actions order to make debugging output
more readable and cause-effect relationships visible;
- making camperiphdone() (common device recovery completion handler) to
also use cam_periph_error() in most cases, instead of own dumb code;
- removing manual sense fetching code from cam_periph_error(); I was told
by number of people that it is SIM obligation to fetch sense data, so this
code is useless and only significantly complicates recovery logic;
- making ada, da and pass driver to use cam_periph_error() with new limited
recovery options to handle error recovery and debugging in common way;
as one of results, CAM_REQUEUE_REQ and other retrying statuses are now
working fine with pass driver, that caused many problems before.
- reverting r186891 by raj@ to avoid burning few seconds in tight DELAY()
loops on device probe, while device simply loads media; I think that problem
may already be fixed in other way, and even if it is not, solution must be
different.
Sponsored by: iXsystems, Inc.
MFC after: 2 weeks
2012-06-09 13:07:44 +00:00
|
|
|
int error;
|
1998-10-08 05:46:38 +00:00
|
|
|
|
2013-03-29 07:50:47 +00:00
|
|
|
CAM_PERIPH_FOREACH(periph, &dadriver) {
|
1998-10-08 05:46:38 +00:00
|
|
|
softc = (struct da_softc *)periph->softc;
|
2013-06-15 12:46:38 +00:00
|
|
|
if (SCHEDULER_STOPPED()) {
|
|
|
|
/* If we paniced with the lock held, do not recurse. */
|
|
|
|
if (!cam_periph_owned(periph) &&
|
|
|
|
(softc->flags & DA_FLAG_OPEN)) {
|
|
|
|
dadump(softc->disk, NULL, 0, 0, 0);
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
cam_periph_lock(periph);
|
1998-10-08 05:46:38 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* We only sync the cache if the drive is still open, and
|
|
|
|
* if the drive is capable of it..
|
|
|
|
*/
|
|
|
|
if (((softc->flags & DA_FLAG_OPEN) == 0)
|
2007-04-19 22:18:15 +00:00
|
|
|
|| (softc->quirks & DA_Q_NO_SYNC_CACHE)) {
|
|
|
|
cam_periph_unlock(periph);
|
1998-10-08 05:46:38 +00:00
|
|
|
continue;
|
2007-04-19 22:18:15 +00:00
|
|
|
}
|
1998-10-08 05:46:38 +00:00
|
|
|
|
2013-03-29 08:33:18 +00:00
|
|
|
ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
|
|
|
|
scsi_synchronize_cache(&ccb->csio,
|
One more major cam_periph_error() rewrite to improve error handling and
reporting. It includes:
- removing of error messages controlled by bootverbose, replacing them
with more universal and informative debugging on CAM_DEBUG_INFO level,
that is now built into the kernel by default;
- more close following to the arguments submitted by caller, such as
SF_PRINT_ALWAYS, SF_QUIET_IR and SF_NO_PRINT; consumer knows better which
errors are usual/expected at this point and which are really informative;
- adding two new flags SF_NO_RECOVERY and SF_NO_RETRY to allow caller
specify how much assistance it needs at this point; previously consumers
controlled that by not calling cam_periph_error() at all, but that made
behavior inconsistent and debugging complicated;
- tuning debug messages and taken actions order to make debugging output
more readable and cause-effect relationships visible;
- making camperiphdone() (common device recovery completion handler) to
also use cam_periph_error() in most cases, instead of own dumb code;
- removing manual sense fetching code from cam_periph_error(); I was told
by number of people that it is SIM obligation to fetch sense data, so this
code is useless and only significantly complicates recovery logic;
- making ada, da and pass driver to use cam_periph_error() with new limited
recovery options to handle error recovery and debugging in common way;
as one of results, CAM_REQUEUE_REQ and other retrying statuses are now
working fine with pass driver, that caused many problems before.
- reverting r186891 by raj@ to avoid burning few seconds in tight DELAY()
loops on device probe, while device simply loads media; I think that problem
may already be fixed in other way, and even if it is not, solution must be
different.
Sponsored by: iXsystems, Inc.
MFC after: 2 weeks
2012-06-09 13:07:44 +00:00
|
|
|
/*retries*/0,
|
1998-10-08 05:46:38 +00:00
|
|
|
/*cbfcnp*/dadone,
|
|
|
|
MSG_SIMPLE_Q_TAG,
|
|
|
|
/*begin_lba*/0, /* whole disk */
|
|
|
|
/*lb_count*/0,
|
|
|
|
SSD_FULL_SIZE,
|
2001-11-17 18:26:00 +00:00
|
|
|
60 * 60 * 1000);
|
1998-10-08 05:46:38 +00:00
|
|
|
|
2013-03-29 08:33:18 +00:00
|
|
|
error = cam_periph_runccb(ccb, daerror, /*cam_flags*/0,
|
|
|
|
/*sense_flags*/ SF_NO_RECOVERY | SF_NO_RETRY | SF_QUIET_IR,
|
|
|
|
softc->disk->d_devstat);
|
One more major cam_periph_error() rewrite to improve error handling and
reporting. It includes:
- removing of error messages controlled by bootverbose, replacing them
with more universal and informative debugging on CAM_DEBUG_INFO level,
that is now built into the kernel by default;
- more close following to the arguments submitted by caller, such as
SF_PRINT_ALWAYS, SF_QUIET_IR and SF_NO_PRINT; consumer knows better which
errors are usual/expected at this point and which are really informative;
- adding two new flags SF_NO_RECOVERY and SF_NO_RETRY to allow caller
specify how much assistance it needs at this point; previously consumers
controlled that by not calling cam_periph_error() at all, but that made
behavior inconsistent and debugging complicated;
- tuning debug messages and taken actions order to make debugging output
more readable and cause-effect relationships visible;
- making camperiphdone() (common device recovery completion handler) to
also use cam_periph_error() in most cases, instead of own dumb code;
- removing manual sense fetching code from cam_periph_error(); I was told
by number of people that it is SIM obligation to fetch sense data, so this
code is useless and only significantly complicates recovery logic;
- making ada, da and pass driver to use cam_periph_error() with new limited
recovery options to handle error recovery and debugging in common way;
as one of results, CAM_REQUEUE_REQ and other retrying statuses are now
working fine with pass driver, that caused many problems before.
- reverting r186891 by raj@ to avoid burning few seconds in tight DELAY()
loops on device probe, while device simply loads media; I think that problem
may already be fixed in other way, and even if it is not, solution must be
different.
Sponsored by: iXsystems, Inc.
MFC after: 2 weeks
2012-06-09 13:07:44 +00:00
|
|
|
if (error != 0)
|
|
|
|
xpt_print(periph->path, "Synchronize cache failed\n");
|
2013-04-03 11:30:18 +00:00
|
|
|
xpt_release_ccb(ccb);
|
2007-04-18 05:14:16 +00:00
|
|
|
cam_periph_unlock(periph);
|
1998-10-08 05:46:38 +00:00
|
|
|
}
|
|
|
|
}
|
2000-05-21 23:57:52 +00:00
|
|
|
|
|
|
|
#else /* !_KERNEL */
|
|
|
|
|
|
|
|
/*
|
Improve camcontrol(8) handling of drive defect data.
This includes a new summary mode (-s) for camcontrol defects that
quickly tells the user the most important thing: how many defects
are in the requested list. The actual location of the defects is
less important.
Modern drives frequently have more than the 8191 defects that can
be reported by the READ DEFECT DATA (10) command. If they don't
have that many grown defects, they certainly have more than 8191
defects in the primary (i.e. factory) defect list.
The READ DEFECT DATA (12) command allows for longer parameter
lists, as well as indexing into the list of defects, and so allows
reporting many more defects.
This has been tested with HGST drives and Seagate drives, but
does not fully work with Seagate drives. Once I have a Seagate
spec I may be able to determine whether it is possible to make it
work with Seagate drives.
scsi_da.h: Add a definition for the new long block defect
format.
Add bit and mask definitions for the new extended
physical sector and bytes from index defect
formats.
Add a prototype for the new scsi_read_defects() CDB
building function.
scsi_da.c: Add a new scsi_read_defects() CDB building function.
camcontrol(8) was previously composing CDBs manually.
This is long overdue.
camcontrol.c: Revamp the camcontrol defects subcommand. We now
go through multiple stages in trying to get defect
data off the drive while avoiding various drive
firmware quirks.
We start off by requesting the defect header with
the 10 byte command. If we're in summary mode (-s)
and the drive reports fewer defects than can be
represented in the 10 byte header, we're done.
Otherwise, we know that we need to issue the
12 byte command if the drive reports the maximum
number of defects.
If we're in summary mode, we're done if we get a
good response back when asking for the 12 byte header.
If the user has asked for the full list, then we
use the address descriptor index field in the 12
byte CDB to step through the list in 64K chunks.
64K is small enough to work with most any ancient
or modern SCSI controller.
Add support for printing the new long block defect
format, as well as the extended physical sector and
bytes from index formats. I don't have any drives
that support the new formats.
Add a hexadecimal output format that can be turned
on with -X.
Add a quiet mode (-q) that can be turned on with
the summary mode (-s) to just print out a number.
Revamp the error detection and recovery code for
the defects command to work with HGST drives.
Call the new scsi_read_defects() CDB building
function instead of rolling the CDB ourselves.
Pay attention to the residual from the defect list
request when printing it out, so we don't run off
the end of the list.
Use the new scsi_nv library routines to convert
from strings to numbers and back.
camcontrol.8: Document the new defect formats (longblock, extbfi,
extphys) and command line options (-q, -s, -S and
-X) for the defects subcommand.
Explain a little more about what drives generally
do and don't support.
Sponsored by: Spectra Logic
MFC after: 1 week
2015-01-08 16:58:40 +00:00
|
|
|
* XXX These are only left out of the kernel build to silence warnings. If,
|
|
|
|
* for some reason these functions are used in the kernel, the ifdefs should
|
|
|
|
* be moved so they are included both in the kernel and userland.
|
2000-05-21 23:57:52 +00:00
|
|
|
*/
|
|
|
|
void
|
|
|
|
scsi_format_unit(struct ccb_scsiio *csio, u_int32_t retries,
|
|
|
|
void (*cbfcnp)(struct cam_periph *, union ccb *),
|
|
|
|
u_int8_t tag_action, u_int8_t byte2, u_int16_t ileave,
|
|
|
|
u_int8_t *data_ptr, u_int32_t dxfer_len, u_int8_t sense_len,
|
|
|
|
u_int32_t timeout)
|
|
|
|
{
|
|
|
|
struct scsi_format_unit *scsi_cmd;
|
|
|
|
|
|
|
|
scsi_cmd = (struct scsi_format_unit *)&csio->cdb_io.cdb_bytes;
|
|
|
|
scsi_cmd->opcode = FORMAT_UNIT;
|
|
|
|
scsi_cmd->byte2 = byte2;
|
|
|
|
scsi_ulto2b(ileave, scsi_cmd->interleave);
|
|
|
|
|
|
|
|
cam_fill_csio(csio,
|
|
|
|
retries,
|
|
|
|
cbfcnp,
|
|
|
|
/*flags*/ (dxfer_len > 0) ? CAM_DIR_OUT : CAM_DIR_NONE,
|
|
|
|
tag_action,
|
|
|
|
data_ptr,
|
|
|
|
dxfer_len,
|
|
|
|
sense_len,
|
|
|
|
sizeof(*scsi_cmd),
|
|
|
|
timeout);
|
|
|
|
}
|
|
|
|
|
Improve camcontrol(8) handling of drive defect data.
This includes a new summary mode (-s) for camcontrol defects that
quickly tells the user the most important thing: how many defects
are in the requested list. The actual location of the defects is
less important.
Modern drives frequently have more than the 8191 defects that can
be reported by the READ DEFECT DATA (10) command. If they don't
have that many grown defects, they certainly have more than 8191
defects in the primary (i.e. factory) defect list.
The READ DEFECT DATA (12) command allows for longer parameter
lists, as well as indexing into the list of defects, and so allows
reporting many more defects.
This has been tested with HGST drives and Seagate drives, but
does not fully work with Seagate drives. Once I have a Seagate
spec I may be able to determine whether it is possible to make it
work with Seagate drives.
scsi_da.h: Add a definition for the new long block defect
format.
Add bit and mask definitions for the new extended
physical sector and bytes from index defect
formats.
Add a prototype for the new scsi_read_defects() CDB
building function.
scsi_da.c: Add a new scsi_read_defects() CDB building function.
camcontrol(8) was previously composing CDBs manually.
This is long overdue.
camcontrol.c: Revamp the camcontrol defects subcommand. We now
go through multiple stages in trying to get defect
data off the drive while avoiding various drive
firmware quirks.
We start off by requesting the defect header with
the 10 byte command. If we're in summary mode (-s)
and the drive reports fewer defects than can be
represented in the 10 byte header, we're done.
Otherwise, we know that we need to issue the
12 byte command if the drive reports the maximum
number of defects.
If we're in summary mode, we're done if we get a
good response back when asking for the 12 byte header.
If the user has asked for the full list, then we
use the address descriptor index field in the 12
byte CDB to step through the list in 64K chunks.
64K is small enough to work with most any ancient
or modern SCSI controller.
Add support for printing the new long block defect
format, as well as the extended physical sector and
bytes from index formats. I don't have any drives
that support the new formats.
Add a hexadecimal output format that can be turned
on with -X.
Add a quiet mode (-q) that can be turned on with
the summary mode (-s) to just print out a number.
Revamp the error detection and recovery code for
the defects command to work with HGST drives.
Call the new scsi_read_defects() CDB building
function instead of rolling the CDB ourselves.
Pay attention to the residual from the defect list
request when printing it out, so we don't run off
the end of the list.
Use the new scsi_nv library routines to convert
from strings to numbers and back.
camcontrol.8: Document the new defect formats (longblock, extbfi,
extphys) and command line options (-q, -s, -S and
-X) for the defects subcommand.
Explain a little more about what drives generally
do and don't support.
Sponsored by: Spectra Logic
MFC after: 1 week
2015-01-08 16:58:40 +00:00
|
|
|
void
|
|
|
|
scsi_read_defects(struct ccb_scsiio *csio, uint32_t retries,
|
|
|
|
void (*cbfcnp)(struct cam_periph *, union ccb *),
|
|
|
|
uint8_t tag_action, uint8_t list_format,
|
|
|
|
uint32_t addr_desc_index, uint8_t *data_ptr,
|
|
|
|
uint32_t dxfer_len, int minimum_cmd_size,
|
|
|
|
uint8_t sense_len, uint32_t timeout)
|
|
|
|
{
|
|
|
|
uint8_t cdb_len;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* These conditions allow using the 10 byte command. Otherwise we
|
|
|
|
* need to use the 12 byte command.
|
|
|
|
*/
|
|
|
|
if ((minimum_cmd_size <= 10)
|
|
|
|
&& (addr_desc_index == 0)
|
|
|
|
&& (dxfer_len <= SRDD10_MAX_LENGTH)) {
|
|
|
|
struct scsi_read_defect_data_10 *cdb10;
|
|
|
|
|
|
|
|
cdb10 = (struct scsi_read_defect_data_10 *)
|
|
|
|
&csio->cdb_io.cdb_bytes;
|
|
|
|
|
|
|
|
cdb_len = sizeof(*cdb10);
|
|
|
|
bzero(cdb10, cdb_len);
|
|
|
|
cdb10->opcode = READ_DEFECT_DATA_10;
|
|
|
|
cdb10->format = list_format;
|
|
|
|
scsi_ulto2b(dxfer_len, cdb10->alloc_length);
|
|
|
|
} else {
|
|
|
|
struct scsi_read_defect_data_12 *cdb12;
|
|
|
|
|
|
|
|
cdb12 = (struct scsi_read_defect_data_12 *)
|
|
|
|
&csio->cdb_io.cdb_bytes;
|
|
|
|
|
|
|
|
cdb_len = sizeof(*cdb12);
|
|
|
|
bzero(cdb12, cdb_len);
|
|
|
|
cdb12->opcode = READ_DEFECT_DATA_12;
|
|
|
|
cdb12->format = list_format;
|
|
|
|
scsi_ulto4b(dxfer_len, cdb12->alloc_length);
|
|
|
|
scsi_ulto4b(addr_desc_index, cdb12->address_descriptor_index);
|
|
|
|
}
|
|
|
|
|
|
|
|
cam_fill_csio(csio,
|
|
|
|
retries,
|
|
|
|
cbfcnp,
|
|
|
|
/*flags*/ CAM_DIR_IN,
|
|
|
|
tag_action,
|
|
|
|
data_ptr,
|
|
|
|
dxfer_len,
|
|
|
|
sense_len,
|
|
|
|
cdb_len,
|
|
|
|
timeout);
|
|
|
|
}
|
|
|
|
|
2013-09-06 15:19:57 +00:00
|
|
|
void
|
|
|
|
scsi_sanitize(struct ccb_scsiio *csio, u_int32_t retries,
|
|
|
|
void (*cbfcnp)(struct cam_periph *, union ccb *),
|
|
|
|
u_int8_t tag_action, u_int8_t byte2, u_int16_t control,
|
|
|
|
u_int8_t *data_ptr, u_int32_t dxfer_len, u_int8_t sense_len,
|
|
|
|
u_int32_t timeout)
|
|
|
|
{
|
|
|
|
struct scsi_sanitize *scsi_cmd;
|
|
|
|
|
|
|
|
scsi_cmd = (struct scsi_sanitize *)&csio->cdb_io.cdb_bytes;
|
|
|
|
scsi_cmd->opcode = SANITIZE;
|
|
|
|
scsi_cmd->byte2 = byte2;
|
|
|
|
scsi_cmd->control = control;
|
|
|
|
scsi_ulto2b(dxfer_len, scsi_cmd->length);
|
|
|
|
|
|
|
|
cam_fill_csio(csio,
|
|
|
|
retries,
|
|
|
|
cbfcnp,
|
|
|
|
/*flags*/ (dxfer_len > 0) ? CAM_DIR_OUT : CAM_DIR_NONE,
|
|
|
|
tag_action,
|
|
|
|
data_ptr,
|
|
|
|
dxfer_len,
|
|
|
|
sense_len,
|
|
|
|
sizeof(*scsi_cmd),
|
|
|
|
timeout);
|
|
|
|
}
|
|
|
|
|
2000-05-21 23:57:52 +00:00
|
|
|
#endif /* _KERNEL */
|