svn commit: r252730 - in stable/9/sys: cam/ata cam/scsi geom
Steven Hartland
smh at FreeBSD.org
Thu Jul 4 21:57:10 UTC 2013
Author: smh
Date: Thu Jul 4 21:57:09 2013
New Revision: 252730
URL: http://svnweb.freebsd.org/changeset/base/252730
Log:
MFC r249940:
Teach GEOM and CAM about the difference between the max "size" of r/w and delete
requests.
MFC r252657:
Bump disk(9) ABI version to signify the addition of d_delmaxsize.
Make the addition of the d_delmaxsize binary compatible. This allows storage
drivers compiled for 9.0 and 9.1 to work by preserving the ABI for disks.
Reviewed by: mav
Modified:
stable/9/sys/cam/ata/ata_da.c
stable/9/sys/cam/scsi/scsi_da.c
stable/9/sys/geom/geom_disk.c
stable/9/sys/geom/geom_disk.h
Directory Properties:
stable/9/sys/ (props changed)
Modified: stable/9/sys/cam/ata/ata_da.c
==============================================================================
--- stable/9/sys/cam/ata/ata_da.c Thu Jul 4 21:31:28 2013 (r252729)
+++ stable/9/sys/cam/ata/ata_da.c Thu Jul 4 21:57:09 2013 (r252730)
@@ -1239,10 +1239,15 @@ adaregister(struct cam_periph *periph, v
softc->disk->d_flags |= DISKFLAG_CANFLUSHCACHE;
if (softc->flags & ADA_FLAG_CAN_TRIM) {
softc->disk->d_flags |= DISKFLAG_CANDELETE;
+ softc->disk->d_delmaxsize = softc->params.secsize *
+ ATA_DSM_RANGE_MAX *
+ softc->trim_max_ranges;
} else if ((softc->flags & ADA_FLAG_CAN_CFA) &&
!(softc->flags & ADA_FLAG_CAN_48BIT)) {
softc->disk->d_flags |= DISKFLAG_CANDELETE;
- }
+ softc->disk->d_delmaxsize = 256 * softc->params.secsize;
+ } else
+ softc->disk->d_delmaxsize = maxio;
if ((cpi.hba_misc & PIM_UNMAPPED) != 0)
softc->disk->d_flags |= DISKFLAG_UNMAPPED_BIO;
strlcpy(softc->disk->d_descr, cgd->ident_data.model,
Modified: stable/9/sys/cam/scsi/scsi_da.c
==============================================================================
--- stable/9/sys/cam/scsi/scsi_da.c Thu Jul 4 21:31:28 2013 (r252729)
+++ stable/9/sys/cam/scsi/scsi_da.c Thu Jul 4 21:57:09 2013 (r252730)
@@ -1064,8 +1064,11 @@ static void daasync(void *callback_arg,
static void dasysctlinit(void *context, int pending);
static int dacmdsizesysctl(SYSCTL_HANDLER_ARGS);
static int dadeletemethodsysctl(SYSCTL_HANDLER_ARGS);
+static int dadeletemaxsysctl(SYSCTL_HANDLER_ARGS);
static void dadeletemethodset(struct da_softc *softc,
da_delete_methods delete_method);
+static off_t dadeletemaxsize(struct da_softc *softc,
+ da_delete_methods delete_method);
static void dadeletemethodchoose(struct da_softc *softc,
da_delete_methods default_method);
static void daprobedone(struct cam_periph *periph, union ccb *ccb);
@@ -1692,6 +1695,10 @@ dasysctlinit(void *context, int pending)
softc, 0, dadeletemethodsysctl, "A",
"BIO_DELETE execution method");
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");
+ SYSCTL_ADD_PROC(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree),
OID_AUTO, "minimum_cmd_size", CTLTYPE_INT | CTLFLAG_RW,
&softc->minimum_cmd_size, 0, dacmdsizesysctl, "I",
"Minimum CDB size");
@@ -1737,6 +1744,29 @@ dasysctlinit(void *context, int pending)
}
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 */
+ if (value > dadeletemaxsize(softc, softc->delete_method)) {
+ return (EINVAL);
+ }
+ softc->disk->d_delmaxsize = value;
+
+ return (0);
+}
+
+static int
dacmdsizesysctl(SYSCTL_HANDLER_ARGS)
{
int error, value;
@@ -1774,6 +1804,7 @@ dadeletemethodset(struct da_softc *softc
softc->delete_method = delete_method;
+ softc->disk->d_delmaxsize = dadeletemaxsize(softc, delete_method);
if (softc->delete_method > DA_DELETE_DISABLE)
softc->disk->d_flags |= DISKFLAG_CANDELETE;
@@ -1781,6 +1812,33 @@ dadeletemethodset(struct da_softc *softc
softc->disk->d_flags &= ~DISKFLAG_CANDELETE;
}
+static off_t
+dadeletemaxsize(struct da_softc *softc, da_delete_methods delete_method)
+{
+ off_t sectors;
+
+ switch(delete_method) {
+ case DA_DELETE_UNMAP:
+ sectors = (off_t)softc->unmap_max_lba * softc->unmap_max_ranges;
+ break;
+ case DA_DELETE_ATA_TRIM:
+ sectors = (off_t)ATA_DSM_RANGE_MAX * softc->trim_max_ranges;
+ break;
+ case DA_DELETE_WS16:
+ sectors = (off_t)min(softc->ws_max_blks, WS16_MAX_BLKS);
+ break;
+ case DA_DELETE_ZERO:
+ case DA_DELETE_WS10:
+ sectors = (off_t)min(softc->ws_max_blks, WS10_MAX_BLKS);
+ break;
+ default:
+ return 0;
+ }
+
+ return (off_t)softc->params.secsize *
+ min(sectors, (off_t)softc->params.sectors);
+}
+
static void
daprobedone(struct cam_periph *periph, union ccb *ccb)
{
@@ -2304,8 +2362,13 @@ skipstate:
} else if (softc->delete_method == DA_DELETE_ZERO ||
softc->delete_method == DA_DELETE_WS10 ||
softc->delete_method == DA_DELETE_WS16) {
+ /*
+ * We calculate ws_max_blks here based off d_delmaxsize instead
+ * of using softc->ws_max_blks as it is absolute max for the
+ * device not the protocol max which may well be lower
+ */
uint64_t ws_max_blks;
- ws_max_blks = softc->ws_max_blks / softc->params.secsize;
+ ws_max_blks = softc->disk->d_delmaxsize / softc->params.secsize;
softc->delete_running = 1;
lba = bp->bio_pblkno;
count = 0;
Modified: stable/9/sys/geom/geom_disk.c
==============================================================================
--- stable/9/sys/geom/geom_disk.c Thu Jul 4 21:31:28 2013 (r252729)
+++ stable/9/sys/geom/geom_disk.c Thu Jul 4 21:57:09 2013 (r252730)
@@ -155,6 +155,13 @@ g_disk_access(struct g_provider *pp, int
dp->d_name, dp->d_unit);
dp->d_maxsize = DFLTPHYS;
}
+ if (dp->d_delmaxsize == 0) {
+ if (bootverbose && dp->d_flags & DISKFLAG_CANDELETE) {
+ printf("WARNING: Disk drive %s%d has no "
+ "d_delmaxsize\n", dp->d_name, dp->d_unit);
+ }
+ dp->d_delmaxsize = dp->d_maxsize;
+ }
} else if ((pp->acr + pp->acw + pp->ace) > 0 && (r + w + e) == 0) {
if (dp->d_close != NULL) {
g_disk_lock_giant(dp);
@@ -299,6 +306,12 @@ g_disk_start(struct bio *bp)
break;
}
do {
+ off_t d_maxsize;
+
+ d_maxsize = (bp->bio_cmd == BIO_DELETE &&
+ (dp->d_flags & DISKFLAG_LACKS_DELMAX) == 0) ?
+ dp->d_delmaxsize : dp->d_maxsize;
+
bp2->bio_offset += off;
bp2->bio_length -= off;
if ((bp->bio_flags & BIO_UNMAPPED) == 0) {
@@ -313,18 +326,20 @@ g_disk_start(struct bio *bp)
bp2->bio_ma_offset %= PAGE_SIZE;
bp2->bio_ma_n -= off / PAGE_SIZE;
}
- if (bp2->bio_length > dp->d_maxsize) {
+ if (bp2->bio_length > d_maxsize) {
/*
* XXX: If we have a stripesize we should really
- * use it here.
+ * use it here. Care should be taken in the delete
+ * case if this is done as deletes can be very
+ * sensitive to size given how they are processed.
*/
- bp2->bio_length = dp->d_maxsize;
+ bp2->bio_length = d_maxsize;
if ((bp->bio_flags & BIO_UNMAPPED) != 0) {
bp2->bio_ma_n = howmany(
bp2->bio_ma_offset +
bp2->bio_length, PAGE_SIZE);
}
- off += dp->d_maxsize;
+ off += d_maxsize;
/*
* To avoid a race, we need to grab the next bio
* before we schedule this one. See "notes".
@@ -603,7 +618,8 @@ void
disk_create(struct disk *dp, int version)
{
- if (version != DISK_VERSION_02 && version != DISK_VERSION_01) {
+ if (version != DISK_VERSION_03 && version != DISK_VERSION_02 &&
+ version != DISK_VERSION_01) {
printf("WARNING: Attempt to add disk %s%d %s",
dp->d_name, dp->d_unit,
" using incompatible ABI version of disk(9)\n");
@@ -613,6 +629,8 @@ disk_create(struct disk *dp, int version
}
if (version == DISK_VERSION_01)
dp->d_flags |= DISKFLAG_LACKS_GONE;
+ if (version < DISK_VERSION_03)
+ dp->d_flags |= DISKFLAG_LACKS_DELMAX;
KASSERT(dp->d_strategy != NULL, ("disk_create need d_strategy"));
KASSERT(dp->d_name != NULL, ("disk_create need d_name"));
KASSERT(*dp->d_name != 0, ("disk_create need d_name"));
Modified: stable/9/sys/geom/geom_disk.h
==============================================================================
--- stable/9/sys/geom/geom_disk.h Thu Jul 4 21:31:28 2013 (r252729)
+++ stable/9/sys/geom/geom_disk.h Thu Jul 4 21:57:09 2013 (r252730)
@@ -99,6 +99,9 @@ struct disk {
/* new fields in stable - don't use if DISKFLAG_LACKS_GONE is set */
disk_gone_t *d_gone;
+
+ /* new fields in stable - don't use if DISKFLAG_LACKS_DELMAX is set */
+ off_t d_delmaxsize;
};
#define DISKFLAG_NEEDSGIANT 0x1
@@ -106,7 +109,8 @@ struct disk {
#define DISKFLAG_CANDELETE 0x4
#define DISKFLAG_CANFLUSHCACHE 0x8
#define DISKFLAG_LACKS_GONE 0x10
-#define DISKFLAG_UNMAPPED_BIO 0x20
+#define DISKFLAG_UNMAPPED_BIO 0x20
+#define DISKFLAG_LACKS_DELMAX 0x40
struct disk *disk_alloc(void);
void disk_create(struct disk *disk, int version);
@@ -119,7 +123,8 @@ void disk_media_gone(struct disk *dp, in
#define DISK_VERSION_00 0x58561059
#define DISK_VERSION_01 0x5856105a
#define DISK_VERSION_02 0x5856105b
-#define DISK_VERSION DISK_VERSION_02
+#define DISK_VERSION_03 0x5856105c
+#define DISK_VERSION DISK_VERSION_03
#endif /* _KERNEL */
#endif /* _GEOM_GEOM_DISK_H_ */
More information about the svn-src-all
mailing list