From owner-svn-src-stable-9@FreeBSD.ORG Thu Jul 4 21:57:10 2013 Return-Path: Delivered-To: svn-src-stable-9@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by hub.freebsd.org (Postfix) with ESMTP id 6B9F4875; Thu, 4 Jul 2013 21:57:10 +0000 (UTC) (envelope-from smh@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) by mx1.freebsd.org (Postfix) with ESMTP id 5D38F1100; Thu, 4 Jul 2013 21:57:10 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.7/8.14.7) with ESMTP id r64LvAhV059228; Thu, 4 Jul 2013 21:57:10 GMT (envelope-from smh@svn.freebsd.org) Received: (from smh@localhost) by svn.freebsd.org (8.14.7/8.14.5/Submit) id r64Lv9FW059220; Thu, 4 Jul 2013 21:57:09 GMT (envelope-from smh@svn.freebsd.org) Message-Id: <201307042157.r64Lv9FW059220@svn.freebsd.org> From: Steven Hartland Date: Thu, 4 Jul 2013 21:57:09 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org Subject: svn commit: r252730 - in stable/9/sys: cam/ata cam/scsi geom X-SVN-Group: stable-9 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-9@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: SVN commit messages for only the 9-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 04 Jul 2013 21:57:10 -0000 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_ */