From owner-svn-src-stable@FreeBSD.ORG Thu Apr 25 04:26:26 2013 Return-Path: Delivered-To: svn-src-stable@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 9DDC9855; Thu, 25 Apr 2013 04:26:26 +0000 (UTC) (envelope-from mavbsd@gmail.com) Received: from mail-ea0-x22f.google.com (mail-ea0-x22f.google.com [IPv6:2a00:1450:4013:c01::22f]) by mx1.freebsd.org (Postfix) with ESMTP id 768821E49; Thu, 25 Apr 2013 04:26:25 +0000 (UTC) Received: by mail-ea0-f175.google.com with SMTP id f15so1020269eak.20 for ; Wed, 24 Apr 2013 21:26:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=x-received:sender:message-id:date:from:user-agent:mime-version:to :cc:subject:references:in-reply-to:content-type :content-transfer-encoding; bh=bs51cOwQ/AR188Ii/cVtaLFRl6O1Fgqdng+O/rsdHr8=; b=obklsvDZVbKi12VcZn2XPkcZskhBGbOMWD8w1kBNw6KvOg9/waP78jWC3VQRslK0zu i2N3NTWy4IExg6w4ks5avHeDIMRb19MheYjCei24xBFSVTiF9oh5vzp1Yz5HPQOD96zw Y3IuEVHfU6Mpfd9gBxVrDP56cbnPUr30BXruz7J1/XgPwkCTJpEz2AYdyQcABrslZMIr q67G6jFXA/J1na9IywaahdAiNE+y4WISOHDHTtNrcFpB+y7Yc0xiN0q5uok8fOr4j7Ip FipZY05ewomU8hS/FmfcadNtTTtLaFqlzRtEcFc4dUDsXXL89EHeH2gc+MUI390sVp8e uPUA== X-Received: by 10.15.27.195 with SMTP id p43mr70622957eeu.8.1366863983652; Wed, 24 Apr 2013 21:26:23 -0700 (PDT) Received: from mavbook.mavhome.dp.ua (mavhome.mavhome.dp.ua. [213.227.240.37]) by mx.google.com with ESMTPSA id i53sm7998362eeu.5.2013.04.24.21.26.20 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 24 Apr 2013 21:26:22 -0700 (PDT) Sender: Alexander Motin Message-ID: <5178B068.10300@FreeBSD.org> Date: Thu, 25 Apr 2013 07:26:16 +0300 From: Alexander Motin User-Agent: Mozilla/5.0 (X11; FreeBSD amd64; rv:17.0) Gecko/20130413 Thunderbird/17.0.5 MIME-Version: 1.0 To: Scott Long Subject: Re: svn commit: r249152 - in stable/9/sys: cam cam/ata cam/scsi geom geom/part References: <201304051141.r35Bfui1062429@svn.freebsd.org> <363EF017-CFC2-4006-8F1B-E18A4091F2CC@yahoo.com> In-Reply-To: <363EF017-CFC2-4006-8F1B-E18A4091F2CC@yahoo.com> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Cc: svn-src-stable@freebsd.org, svn-src-all@freebsd.org, src-committers@freebsd.org, svn-src-stable-9@freebsd.org X-BeenThere: svn-src-stable@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: SVN commit messages for all the -stable branches of the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 25 Apr 2013 04:26:26 -0000 On 25.04.2013 02:39, Scott Long wrote: > I've already responded to Alexander in private, but in case he doesn't respond, I'm stating publicly that I object to this commit (and the corresponding one in HEAD) and I'd like to have it reviewed and reverted. The commit was announced on scsi@ and geom@ lists before reaching head, and it waited for more then half a year before being merged to 9-STABLE. If you still have objections, I would like to discuss them. Could you not start each email from request of reverting others work? > On Apr 5, 2013, at 4:41 AM, Alexander Motin wrote: > >> Author: mav >> Date: Fri Apr 5 11:41:56 2013 >> New Revision: 249152 >> URL: http://svnweb.freebsd.org/changeset/base/249152 >> >> Log: >> MFC r238886, r238892: >> Implement media change notification for DA and CD removable media devices. >> It includes three parts: >> 1) Modifications to CAM to detect media media changes and report them to >> disk(9) layer. For modern SATA (and potentially UAS) devices it utilizes >> Asynchronous Notification mechanism to receive events from hardware. >> Active polling with TEST UNIT READY commands with 3 seconds period is used >> for incapable hardware. After that both CD and DA drivers work the same way, >> detecting two conditions: "NOT READY: Medium not present" after medium was >> detected previously, and "UNIT ATTENTION: Not ready to ready change, medium >> may have changed". First one reported to disk(9) as media removal, second >> as media insert/change. To reliably receive second event new >> AC_UNIT_ATTENTION async added to make UAs broadcasted to all periphs by >> generic error handling code in cam_periph_error(). >> 2) Modifications to GEOM core to handle media remove and change events. >> Media removal handled by spoiling all consumers attached to the provider. >> Media change event also schedules provider retaste after spoiling to probe >> new media. New flag G_CF_ORPHAN was added to consumers to reflect that >> consumer is in process of destruction. It allows retaste to create new >> geom instance of the same class, while previous one is still dying. >> 3) Modifications to some GEOM classes: DEV -- to report media change >> events to devd; PART class already handles spoiling alike to orphan. >> >> Modified: >> stable/9/sys/cam/ata/ata_all.h >> stable/9/sys/cam/ata/ata_xpt.c >> stable/9/sys/cam/cam_ccb.h >> stable/9/sys/cam/cam_periph.c >> stable/9/sys/cam/cam_xpt.c >> stable/9/sys/cam/scsi/scsi_cd.c >> stable/9/sys/cam/scsi/scsi_da.c >> stable/9/sys/geom/geom.h >> stable/9/sys/geom/geom_dev.c >> stable/9/sys/geom/geom_disk.c >> stable/9/sys/geom/geom_disk.h >> stable/9/sys/geom/geom_event.c >> stable/9/sys/geom/geom_io.c >> stable/9/sys/geom/geom_slice.c >> stable/9/sys/geom/geom_subr.c >> stable/9/sys/geom/part/g_part.c >> Directory Properties: >> stable/9/sys/ (props changed) >> >> Modified: stable/9/sys/cam/ata/ata_all.h >> ============================================================================== >> --- stable/9/sys/cam/ata/ata_all.h Fri Apr 5 11:30:31 2013 (r249151) >> +++ stable/9/sys/cam/ata/ata_all.h Fri Apr 5 11:41:56 2013 (r249152) >> @@ -35,6 +35,7 @@ struct ccb_ataio; >> struct cam_periph; >> union ccb; >> >> +#define SID_AEN 0x04 /* Abuse inq_flags bit to track enabled AEN. */ >> #define SID_DMA 0x10 /* Abuse inq_flags bit to track enabled DMA. */ >> >> struct ata_cmd { >> >> Modified: stable/9/sys/cam/ata/ata_xpt.c >> ============================================================================== >> --- stable/9/sys/cam/ata/ata_xpt.c Fri Apr 5 11:30:31 2013 (r249151) >> +++ stable/9/sys/cam/ata/ata_xpt.c Fri Apr 5 11:41:56 2013 (r249152) >> @@ -463,6 +463,12 @@ negotiate: >> 0, 0x02); >> break; >> case PROBE_SETAN: >> + /* Remember what transport thinks about AEN. */ >> + if (softc->caps & CTS_SATA_CAPS_H_AN) >> + path->device->inq_flags |= SID_AEN; >> + else >> + path->device->inq_flags &= ~SID_AEN; >> + xpt_async(AC_GETDEV_CHANGED, path, NULL); >> cam_fill_ataio(ataio, >> 1, >> probedone, >> @@ -1157,6 +1163,12 @@ notsata: >> cts.xport_specific.sata.valid = CTS_SATA_VALID_CAPS; >> xpt_action((union ccb *)&cts); >> softc->caps = caps; >> + /* Remember what transport thinks about AEN. */ >> + if (softc->caps & CTS_SATA_CAPS_H_AN) >> + path->device->inq_flags |= SID_AEN; >> + else >> + path->device->inq_flags &= ~SID_AEN; >> + xpt_async(AC_GETDEV_CHANGED, path, NULL); >> if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) { >> path->device->flags &= ~CAM_DEV_UNCONFIGURED; >> xpt_acquire_device(path->device); >> >> Modified: stable/9/sys/cam/cam_ccb.h >> ============================================================================== >> --- stable/9/sys/cam/cam_ccb.h Fri Apr 5 11:30:31 2013 (r249151) >> +++ stable/9/sys/cam/cam_ccb.h Fri Apr 5 11:41:56 2013 (r249152) >> @@ -755,6 +755,7 @@ struct ccb_relsim { >> * Definitions for the asynchronous callback CCB fields. >> */ >> typedef enum { >> + AC_UNIT_ATTENTION = 0x4000,/* Device reported UNIT ATTENTION */ >> AC_ADVINFO_CHANGED = 0x2000,/* Advance info might have changes */ >> AC_CONTRACT = 0x1000,/* A contractual callback */ >> AC_GETDEV_CHANGED = 0x800,/* Getdev info might have changed */ >> >> Modified: stable/9/sys/cam/cam_periph.c >> ============================================================================== >> --- stable/9/sys/cam/cam_periph.c Fri Apr 5 11:30:31 2013 (r249151) >> +++ stable/9/sys/cam/cam_periph.c Fri Apr 5 11:41:56 2013 (r249152) >> @@ -1604,6 +1604,7 @@ cam_periph_error(union ccb *ccb, cam_fla >> const char *action_string; >> cam_status status; >> int frozen, error, openings, print, lost_device; >> + int error_code, sense_key, asc, ascq; >> u_int32_t relsim_flags, timeout; >> >> print = 1; >> @@ -1770,6 +1771,12 @@ cam_periph_error(union ccb *ccb, cam_fla >> xpt_async(AC_LOST_DEVICE, newpath, NULL); >> xpt_free_path(newpath); >> } >> + >> + /* Broadcast UNIT ATTENTIONs to all periphs. */ >> + } else if (scsi_extract_sense_ccb(ccb, >> + &error_code, &sense_key, &asc, &ascq) && >> + sense_key == SSD_KEY_UNIT_ATTENTION) { >> + xpt_async(AC_UNIT_ATTENTION, orig_ccb->ccb_h.path, orig_ccb); >> } >> >> /* Attempt a retry */ >> >> Modified: stable/9/sys/cam/cam_xpt.c >> ============================================================================== >> --- stable/9/sys/cam/cam_xpt.c Fri Apr 5 11:30:31 2013 (r249151) >> +++ stable/9/sys/cam/cam_xpt.c Fri Apr 5 11:41:56 2013 (r249152) >> @@ -4053,6 +4053,7 @@ xpt_async_string(u_int32_t async_code) >> case AC_GETDEV_CHANGED: return ("AC_GETDEV_CHANGED"); >> case AC_CONTRACT: return ("AC_CONTRACT"); >> case AC_ADVINFO_CHANGED: return ("AC_ADVINFO_CHANGED"); >> + case AC_UNIT_ATTENTION: return ("AC_UNIT_ATTENTION"); >> } >> return ("AC_UNKNOWN"); >> } >> >> Modified: stable/9/sys/cam/scsi/scsi_cd.c >> ============================================================================== >> --- stable/9/sys/cam/scsi/scsi_cd.c Fri Apr 5 11:30:31 2013 (r249151) >> +++ stable/9/sys/cam/scsi/scsi_cd.c Fri Apr 5 11:41:56 2013 (r249152) >> @@ -97,6 +97,7 @@ typedef enum { >> CD_FLAG_NEW_DISC = 0x0002, >> CD_FLAG_DISC_LOCKED = 0x0004, >> CD_FLAG_DISC_REMOVABLE = 0x0008, >> + CD_FLAG_SAW_MEDIA = 0x0010, >> CD_FLAG_CHANGER = 0x0040, >> CD_FLAG_ACTIVE = 0x0080, >> CD_FLAG_SCHED_ON_COMP = 0x0100, >> @@ -110,6 +111,7 @@ typedef enum { >> CD_CCB_PROBE = 0x01, >> CD_CCB_BUFFER_IO = 0x02, >> CD_CCB_WAITING = 0x03, >> + CD_CCB_TUR = 0x04, >> CD_CCB_TYPE_MASK = 0x0F, >> CD_CCB_RETRY_UA = 0x10 >> } cd_ccb_state; >> @@ -154,12 +156,14 @@ struct cd_softc { >> struct cam_periph *periph; >> int minimum_command_size; >> int outstanding_cmds; >> + int tur; >> struct task sysctl_task; >> struct sysctl_ctx_list sysctl_ctx; >> struct sysctl_oid *sysctl_tree; >> STAILQ_HEAD(, cd_mode_params) mode_queue; >> struct cd_tocdata toc; >> struct disk *disk; >> + struct callout mediapoll_c; >> }; >> >> struct cd_page_sizes { >> @@ -281,6 +285,7 @@ static int cdsendkey(struct cam_periph >> struct dvd_authinfo *authinfo); >> static int cdreaddvdstructure(struct cam_periph *periph, >> struct dvd_struct *dvdstruct); >> +static timeout_t cdmediapoll; >> >> static struct periph_driver cddriver = >> { >> @@ -290,6 +295,9 @@ static struct periph_driver cddriver = >> >> PERIPHDRIVER_DECLARE(cd, cddriver); >> >> +#ifndef CD_DEFAULT_POLL_PERIOD >> +#define CD_DEFAULT_POLL_PERIOD 3 >> +#endif >> #ifndef CD_DEFAULT_RETRY >> #define CD_DEFAULT_RETRY 4 >> #endif >> @@ -303,6 +311,7 @@ PERIPHDRIVER_DECLARE(cd, cddriver); >> #define CHANGER_MAX_BUSY_SECONDS 15 >> #endif >> >> +static int cd_poll_period = CD_DEFAULT_POLL_PERIOD; >> static int cd_retry_count = CD_DEFAULT_RETRY; >> static int cd_timeout = CD_DEFAULT_TIMEOUT; >> static int changer_min_busy_seconds = CHANGER_MIN_BUSY_SECONDS; >> @@ -311,6 +320,9 @@ static int changer_max_busy_seconds = CH >> static SYSCTL_NODE(_kern_cam, OID_AUTO, cd, CTLFLAG_RD, 0, "CAM CDROM driver"); >> static SYSCTL_NODE(_kern_cam_cd, OID_AUTO, changer, CTLFLAG_RD, 0, >> "CD Changer"); >> +SYSCTL_INT(_kern_cam_cd, OID_AUTO, poll_period, CTLFLAG_RW, >> + &cd_poll_period, 0, "Media polling period in seconds"); >> +TUNABLE_INT("kern.cam.cd.poll_period", &cd_poll_period); >> SYSCTL_INT(_kern_cam_cd, OID_AUTO, retry_count, CTLFLAG_RW, >> &cd_retry_count, 0, "Normal I/O retry count"); >> TUNABLE_INT("kern.cam.cd.retry_count", &cd_retry_count); >> @@ -494,6 +506,7 @@ cdcleanup(struct cam_periph *periph) >> xpt_print(periph->path, "can't remove sysctl context\n"); >> } >> >> + callout_drain(&softc->mediapoll_c); >> disk_destroy(softc->disk); >> free(softc, M_DEVBUF); >> cam_periph_lock(periph); >> @@ -504,6 +517,7 @@ cdasync(void *callback_arg, u_int32_t co >> struct cam_path *path, void *arg) >> { >> struct cam_periph *periph; >> + struct cd_softc *softc; >> >> periph = (struct cam_periph *)callback_arg; >> switch (code) { >> @@ -541,10 +555,39 @@ cdasync(void *callback_arg, u_int32_t co >> >> break; >> } >> + case AC_UNIT_ATTENTION: >> + { >> + union ccb *ccb; >> + int error_code, sense_key, asc, ascq; >> + >> + softc = (struct cd_softc *)periph->softc; >> + ccb = (union ccb *)arg; >> + >> + /* >> + * Handle all media change UNIT ATTENTIONs except >> + * our own, as they will be handled by cderror(). >> + */ >> + if (xpt_path_periph(ccb->ccb_h.path) != periph && >> + scsi_extract_sense_ccb(ccb, >> + &error_code, &sense_key, &asc, &ascq)) { >> + if (asc == 0x28 && ascq == 0x00) >> + disk_media_changed(softc->disk, M_NOWAIT); >> + } >> + cam_periph_async(periph, code, path, arg); >> + break; >> + } >> + case AC_SCSI_AEN: >> + softc = (struct cd_softc *)periph->softc; >> + if (softc->state == CD_STATE_NORMAL && !softc->tur) { >> + if (cam_periph_acquire(periph) == CAM_REQ_CMP) { >> + softc->tur = 1; >> + xpt_schedule(periph, CAM_PRIORITY_DEV); >> + } >> + } >> + /* FALLTHROUGH */ >> case AC_SENT_BDR: >> case AC_BUS_RESET: >> { >> - struct cd_softc *softc; >> struct ccb_hdr *ccbh; >> >> softc = (struct cd_softc *)periph->softc; >> @@ -784,8 +827,8 @@ cdregister(struct cam_periph *periph, vo >> * Add an async callback so that we get >> * notified if this device goes away. >> */ >> - xpt_register_async(AC_SENT_BDR | AC_BUS_RESET | AC_LOST_DEVICE, >> - cdasync, periph, periph->path); >> + xpt_register_async(AC_SENT_BDR | AC_BUS_RESET | AC_LOST_DEVICE | >> + AC_SCSI_AEN | AC_UNIT_ATTENTION, cdasync, periph, periph->path); >> >> /* >> * If the target lun is greater than 0, we most likely have a CD >> @@ -1001,6 +1044,17 @@ cdregister(struct cam_periph *periph, vo >> } >> } >> >> + /* >> + * Schedule a periodic media polling events. >> + */ >> + callout_init_mtx(&softc->mediapoll_c, periph->sim->mtx, 0); >> + if ((softc->flags & CD_FLAG_DISC_REMOVABLE) && >> + (softc->flags & CD_FLAG_CHANGER) == 0 && >> + (cgd->inq_flags & SID_AEN) == 0 && >> + cd_poll_period != 0) >> + callout_reset(&softc->mediapoll_c, cd_poll_period * hz, >> + cdmediapoll, periph); >> + >> cdregisterexit: >> >> if ((softc->flags & CD_FLAG_CHANGER) == 0) >> @@ -1496,8 +1550,25 @@ cdstart(struct cam_periph *periph, union >> periph->immediate_priority = CAM_PRIORITY_NONE; >> wakeup(&periph->ccb_list); >> } else if (bp == NULL) { >> - xpt_release_ccb(start_ccb); >> + if (softc->tur) { >> + softc->tur = 0; >> + csio = &start_ccb->csio; >> + scsi_test_unit_ready(csio, >> + /*retries*/ cd_retry_count, >> + cddone, >> + MSG_SIMPLE_Q_TAG, >> + SSD_FULL_SIZE, >> + cd_timeout); >> + start_ccb->ccb_h.ccb_bp = NULL; >> + start_ccb->ccb_h.ccb_state = CD_CCB_TUR; >> + xpt_action(start_ccb); >> + } else >> + xpt_release_ccb(start_ccb); >> } else { >> + if (softc->tur) { >> + softc->tur = 0; >> + cam_periph_release_locked(periph); >> + } >> bioq_remove(&softc->bio_queue, bp); >> >> scsi_read_write(&start_ccb->csio, >> @@ -1541,7 +1612,7 @@ cdstart(struct cam_periph *periph, union >> >> xpt_action(start_ccb); >> } >> - if (bp != NULL) { >> + if (bp != NULL || softc->tur) { >> /* Have more work to do, so ensure we stay scheduled */ >> xpt_schedule(periph, CAM_PRIORITY_NORMAL); >> } >> @@ -1835,6 +1906,25 @@ cddone(struct cam_periph *periph, union >> wakeup(&done_ccb->ccb_h.cbfcnp); >> return; >> } >> + case CD_CCB_TUR: >> + { >> + if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { >> + >> + if (cderror(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; >> + } >> default: >> break; >> } >> @@ -2826,7 +2916,7 @@ cdcheckmedia(struct cam_periph *periph) >> cdprevent(periph, PR_ALLOW); >> return (error); >> } else { >> - softc->flags |= CD_FLAG_VALID_MEDIA; >> + softc->flags |= CD_FLAG_SAW_MEDIA | CD_FLAG_VALID_MEDIA; >> softc->disk->d_sectorsize = softc->params.blksize; >> softc->disk->d_mediasize = >> (off_t)softc->params.blksize * softc->params.disksize; >> @@ -3171,6 +3261,14 @@ cderror(union ccb *ccb, u_int32_t cam_fl >> &error_code, &sense_key, &asc, &ascq)) { >> if (sense_key == SSD_KEY_ILLEGAL_REQUEST) >> error = cd6byteworkaround(ccb); >> + else if (sense_key == SSD_KEY_UNIT_ATTENTION && >> + asc == 0x28 && ascq == 0x00) >> + disk_media_changed(softc->disk, M_NOWAIT); >> + else if (sense_key == SSD_KEY_NOT_READY && >> + asc == 0x3a && (softc->flags & CD_FLAG_SAW_MEDIA)) { >> + softc->flags &= ~CD_FLAG_SAW_MEDIA; >> + disk_media_gone(softc->disk, M_NOWAIT); >> + } >> } >> >> if (error == ERESTART) >> @@ -3186,6 +3284,26 @@ cderror(union ccb *ccb, u_int32_t cam_fl >> &softc->saved_ccb)); >> } >> >> +static void >> +cdmediapoll(void *arg) >> +{ >> + struct cam_periph *periph = arg; >> + struct cd_softc *softc = periph->softc; >> + >> + if (softc->flags & CD_FLAG_CHANGER) >> + return; >> + >> + if (softc->state == CD_STATE_NORMAL && !softc->tur) { >> + if (cam_periph_acquire(periph) == CAM_REQ_CMP) { >> + softc->tur = 1; >> + xpt_schedule(periph, CAM_PRIORITY_DEV); >> + } >> + } >> + /* Queue us up again */ >> + if (cd_poll_period != 0) >> + callout_schedule(&softc->mediapoll_c, cd_poll_period * hz); >> +} >> + >> /* >> * Read table of contents >> */ >> >> Modified: stable/9/sys/cam/scsi/scsi_da.c >> ============================================================================== >> --- stable/9/sys/cam/scsi/scsi_da.c Fri Apr 5 11:30:31 2013 (r249151) >> +++ stable/9/sys/cam/scsi/scsi_da.c Fri Apr 5 11:41:56 2013 (r249152) >> @@ -77,6 +77,7 @@ typedef enum { >> DA_FLAG_NEW_PACK = 0x002, >> DA_FLAG_PACK_LOCKED = 0x004, >> DA_FLAG_PACK_REMOVABLE = 0x008, >> + DA_FLAG_SAW_MEDIA = 0x010, >> DA_FLAG_NEED_OTAG = 0x020, >> DA_FLAG_WENT_IDLE = 0x040, >> DA_FLAG_RETRY_UA = 0x080, >> @@ -101,6 +102,7 @@ typedef enum { >> DA_CCB_WAITING = 0x04, >> DA_CCB_DUMP = 0x05, >> DA_CCB_DELETE = 0x06, >> + DA_CCB_TUR = 0x07, >> DA_CCB_TYPE_MASK = 0x0F, >> DA_CCB_RETRY_UA = 0x10 >> } da_ccb_state; >> @@ -150,6 +152,7 @@ struct da_softc { >> int unmap_max_ranges; >> int unmap_max_lba; >> int delete_running; >> + int tur; >> da_delete_methods delete_method; >> struct disk_params params; >> struct disk *disk; >> @@ -161,6 +164,7 @@ struct da_softc { >> uint64_t wwpn; >> uint8_t unmap_buf[UNMAP_MAX_RANGES * 16 + 8]; >> struct scsi_read_capacity_data_long rcaplong; >> + struct callout mediapoll_c; >> }; >> >> struct da_quirk_entry { >> @@ -875,6 +879,11 @@ static void dasetgeom(struct cam_periph >> size_t rcap_size); >> static timeout_t dasendorderedtag; >> static void dashutdown(void *arg, int howto); >> +static timeout_t damediapoll; >> + >> +#ifndef DA_DEFAULT_POLL_PERIOD >> +#define DA_DEFAULT_POLL_PERIOD 3 >> +#endif >> >> #ifndef DA_DEFAULT_TIMEOUT >> #define DA_DEFAULT_TIMEOUT 60 /* Timeout in seconds */ >> @@ -889,12 +898,16 @@ static void dashutdown(void *arg, int h >> #endif >> >> >> +static int da_poll_period = DA_DEFAULT_POLL_PERIOD; >> static int da_retry_count = DA_DEFAULT_RETRY; >> static int da_default_timeout = DA_DEFAULT_TIMEOUT; >> static int da_send_ordered = DA_DEFAULT_SEND_ORDERED; >> >> static SYSCTL_NODE(_kern_cam, OID_AUTO, da, CTLFLAG_RD, 0, >> "CAM Direct Access Disk driver"); >> +SYSCTL_INT(_kern_cam_da, OID_AUTO, poll_period, CTLFLAG_RW, >> + &da_poll_period, 0, "Media polling period in seconds"); >> +TUNABLE_INT("kern.cam.da.poll_period", &da_poll_period); >> SYSCTL_INT(_kern_cam_da, OID_AUTO, retry_count, CTLFLAG_RW, >> &da_retry_count, 0, "Normal I/O retry count"); >> TUNABLE_INT("kern.cam.da.retry_count", &da_retry_count); >> @@ -984,6 +997,9 @@ daopen(struct disk *dp) >> (softc->quirks & DA_Q_NO_PREVENT) == 0) >> daprevent(periph, PR_PREVENT); >> >> + if (error == 0) >> + softc->flags |= DA_FLAG_SAW_MEDIA; >> + >> cam_periph_unhold(periph); >> cam_periph_unlock(periph); >> >> @@ -1068,7 +1084,8 @@ daschedule(struct cam_periph *periph) >> >> /* Check if we have more work to do. */ >> if (bioq_first(&softc->bio_queue) || >> - (!softc->delete_running && bioq_first(&softc->delete_queue))) { >> + (!softc->delete_running && bioq_first(&softc->delete_queue)) || >> + softc->tur) { >> prio = CAM_PRIORITY_NORMAL; >> } >> >> @@ -1315,6 +1332,7 @@ dacleanup(struct cam_periph *periph) >> xpt_print(periph->path, "can't remove sysctl context\n"); >> } >> >> + callout_drain(&softc->mediapoll_c); >> disk_destroy(softc->disk); >> callout_drain(&softc->sendordered_c); >> free(softc, M_DEVBUF); >> @@ -1326,6 +1344,7 @@ daasync(void *callback_arg, u_int32_t co >> struct cam_path *path, void *arg) >> { >> struct cam_periph *periph; >> + struct da_softc *softc; >> >> periph = (struct cam_periph *)callback_arg; >> switch (code) { >> @@ -1377,10 +1396,43 @@ daasync(void *callback_arg, u_int32_t co >> } >> break; >> } >> + 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, >> + "capacity data has changed\n"); >> + dareprobe(periph); >> + } else if (asc == 0x28 && ascq == 0x00) >> + disk_media_changed(softc->disk, M_NOWAIT); >> + } >> + cam_periph_async(periph, code, path, arg); >> + break; >> + } >> + case AC_SCSI_AEN: >> + softc = (struct da_softc *)periph->softc; >> + if (softc->state == DA_STATE_NORMAL && !softc->tur) { >> + if (cam_periph_acquire(periph) == CAM_REQ_CMP) { >> + softc->tur = 1; >> + xpt_schedule(periph, CAM_PRIORITY_DEV); >> + } >> + } >> + /* FALLTHROUGH */ >> case AC_SENT_BDR: >> case AC_BUS_RESET: >> { >> - struct da_softc *softc; >> struct ccb_hdr *ccbh; >> >> softc = (struct da_softc *)periph->softc; >> @@ -1711,9 +1763,9 @@ daregister(struct cam_periph *periph, vo >> * fine without them and the only alternative >> * would be to not attach the device on failure. >> */ >> - xpt_register_async(AC_SENT_BDR | AC_BUS_RESET >> - | AC_LOST_DEVICE | AC_ADVINFO_CHANGED, >> - daasync, periph, periph->path); >> + 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); >> >> /* >> * Emit an attribute changed notification just in case >> @@ -1723,6 +1775,16 @@ daregister(struct cam_periph *periph, vo >> */ >> disk_attr_changed(softc->disk, "GEOM::physpath", M_NOWAIT); >> >> + /* >> + * Schedule a periodic media polling events. >> + */ >> + callout_init_mtx(&softc->mediapoll_c, periph->sim->mtx, 0); >> + 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); >> + >> xpt_schedule(periph, CAM_PRIORITY_DEV); >> >> return(CAM_REQ_CMP); >> @@ -1860,9 +1922,25 @@ dastart(struct cam_periph *periph, union >> /* Run regular command. */ >> bp = bioq_takefirst(&softc->bio_queue); >> if (bp == NULL) { >> - xpt_release_ccb(start_ccb); >> + 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); >> break; >> } >> + if (softc->tur) { >> + softc->tur = 0; >> + cam_periph_release_locked(periph); >> + } >> >> if ((bp->bio_flags & BIO_ORDERED) != 0 || >> (softc->flags & DA_FLAG_NEED_OTAG) != 0) { >> @@ -2429,6 +2507,25 @@ dadone(struct cam_periph *periph, union >> case DA_CCB_DUMP: >> /* No-op. We're polling */ >> return; >> + 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; >> + } >> default: >> break; >> } >> @@ -2489,6 +2586,13 @@ daerror(union ccb *ccb, u_int32_t cam_fl >> xpt_print(periph->path, "capacity data has changed\n"); >> dareprobe(periph); >> sense_flags |= SF_NO_PRINT; >> + } else if (sense_key == SSD_KEY_UNIT_ATTENTION && >> + asc == 0x28 && ascq == 0x00) >> + disk_media_changed(softc->disk, M_NOWAIT); >> + else if (sense_key == SSD_KEY_NOT_READY && >> + asc == 0x3a && (softc->flags & DA_FLAG_SAW_MEDIA)) { >> + softc->flags &= ~DA_FLAG_SAW_MEDIA; >> + disk_media_gone(softc->disk, M_NOWAIT); >> } >> } >> if (error == ERESTART) >> @@ -2505,6 +2609,23 @@ daerror(union ccb *ccb, u_int32_t cam_fl >> } >> >> static void >> +damediapoll(void *arg) >> +{ >> + struct cam_periph *periph = arg; >> + struct da_softc *softc = periph->softc; >> + >> + if (softc->state == DA_STATE_NORMAL && !softc->tur) { >> + 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); >> +} >> + >> +static void >> daprevent(struct cam_periph *periph, int action) >> { >> struct da_softc *softc; >> >> Modified: stable/9/sys/geom/geom.h >> ============================================================================== >> --- stable/9/sys/geom/geom.h Fri Apr 5 11:30:31 2013 (r249151) >> +++ stable/9/sys/geom/geom.h Fri Apr 5 11:41:56 2013 (r249152) >> @@ -169,7 +169,9 @@ struct g_consumer { >> struct g_provider *provider; >> LIST_ENTRY(g_consumer) consumers; /* XXX: better name */ >> int acr, acw, ace; >> - int spoiled; >> + int flags; >> +#define G_CF_SPOILED 0x1 >> +#define G_CF_ORPHAN 0x4 >> struct devstat *stat; >> u_int nstart, nend; >> >> @@ -242,6 +244,8 @@ int g_post_event(g_event_t *func, void * >> int g_waitfor_event(g_event_t *func, void *arg, int flag, ...); >> void g_cancel_event(void *ref); >> int g_attr_changed(struct g_provider *pp, const char *attr, int flag); >> +int g_media_changed(struct g_provider *pp, int flag); >> +int g_media_gone(struct g_provider *pp, int flag); >> void g_orphan_provider(struct g_provider *pp, int error); >> void g_waitidlelock(void); >> >> >> Modified: stable/9/sys/geom/geom_dev.c >> ============================================================================== >> --- stable/9/sys/geom/geom_dev.c Fri Apr 5 11:30:31 2013 (r249151) >> +++ stable/9/sys/geom/geom_dev.c Fri Apr 5 11:41:56 2013 (r249152) >> @@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$"); >> #include >> #include >> #include >> +#include >> #include >> #include >> #include >> @@ -105,6 +106,21 @@ g_dev_print(void) >> static void >> g_dev_attrchanged(struct g_consumer *cp, const char *attr) >> { >> + struct cdev *dev; >> + char buf[SPECNAMELEN + 6]; >> + >> + if (strcmp(attr, "GEOM::media") == 0) { >> + dev = cp->geom->softc; >> + snprintf(buf, sizeof(buf), "cdev=%s", dev->si_name); >> + devctl_notify_f("DEVFS", "CDEV", "MEDIACHANGE", buf, M_WAITOK); >> + dev = cp->cp_alias_dev; >> + if (dev != NULL) { >> + snprintf(buf, sizeof(buf), "cdev=%s", dev->si_name); >> + devctl_notify_f("DEVFS", "CDEV", "MEDIACHANGE", buf, >> + M_WAITOK); >> + } >> + return; >> + } >> >> if (strcmp(attr, "GEOM::physpath") != 0) >> return; >> @@ -119,7 +135,6 @@ g_dev_attrchanged(struct g_consumer *cp, >> g_io_getattr("GEOM::physpath", cp, &physpath_len, physpath); >> g_access(cp, -1, 0, 0); >> if (error == 0 && strlen(physpath) != 0) { >> - struct cdev *dev; >> struct cdev *old_alias_dev; >> struct cdev **alias_devp; >> >> @@ -161,9 +176,6 @@ g_dev_taste(struct g_class *mp, struct g >> >> g_trace(G_T_TOPOLOGY, "dev_taste(%s,%s)", mp->name, pp->name); >> g_topology_assert(); >> - LIST_FOREACH(cp, &pp->consumers, consumers) >> - if (cp->geom->class == mp) >> - return (NULL); >> gp = g_new_geomf(mp, "%s", pp->name); >> cp = g_new_consumer(gp); >> error = g_attach(cp, pp); >> >> Modified: stable/9/sys/geom/geom_disk.c >> ============================================================================== >> --- stable/9/sys/geom/geom_disk.c Fri Apr 5 11:30:31 2013 (r249151) >> +++ stable/9/sys/geom/geom_disk.c Fri Apr 5 11:41:56 2013 (r249152) >> @@ -649,6 +649,32 @@ disk_attr_changed(struct disk *dp, const >> (void)g_attr_changed(pp, attr, flag); >> } >> >> +void >> +disk_media_changed(struct disk *dp, int flag) >> +{ >> + struct g_geom *gp; >> + struct g_provider *pp; >> + >> + gp = dp->d_geom; >> + if (gp != NULL) { >> + LIST_FOREACH(pp, &gp->provider, provider) >> + g_media_changed(pp, flag); >> + } >> +} >> + >> +void >> +disk_media_gone(struct disk *dp, int flag) >> +{ >> + struct g_geom *gp; >> + struct g_provider *pp; >> + >> + gp = dp->d_geom; >> + if (gp != NULL) { >> + LIST_FOREACH(pp, &gp->provider, provider) >> + g_media_gone(pp, flag); >> + } >> +} >> + >> static void >> g_kern_disks(void *p, int flag __unused) >> { >> >> Modified: stable/9/sys/geom/geom_disk.h >> ============================================================================== >> --- stable/9/sys/geom/geom_disk.h Fri Apr 5 11:30:31 2013 (r249151) >> +++ stable/9/sys/geom/geom_disk.h Fri Apr 5 11:41:56 2013 (r249152) >> @@ -112,6 +112,8 @@ void disk_create(struct disk *disk, int >> void disk_destroy(struct disk *disk); >> void disk_gone(struct disk *disk); >> void disk_attr_changed(struct disk *dp, const char *attr, int flag); >> +void disk_media_changed(struct disk *dp, int flag); >> +void disk_media_gone(struct disk *dp, int flag); >> >> #define DISK_VERSION_00 0x58561059 >> #define DISK_VERSION_01 0x5856105a >> >> Modified: stable/9/sys/geom/geom_event.c >> ============================================================================== >> --- stable/9/sys/geom/geom_event.c Fri Apr 5 11:30:31 2013 (r249151) >> +++ stable/9/sys/geom/geom_event.c Fri Apr 5 11:41:56 2013 (r249152) >> @@ -202,14 +202,12 @@ g_orphan_register(struct g_provider *pp) >> * Tell all consumers the bad news. >> * Don't be surprised if they self-destruct. >> */ >> - cp = LIST_FIRST(&pp->consumers); >> - while (cp != NULL) { >> - cp2 = LIST_NEXT(cp, consumers); >> + LIST_FOREACH_SAFE(cp, &pp->consumers, consumers, cp2) { >> KASSERT(cp->geom->orphan != NULL, >> ("geom %s has no orphan, class %s", >> cp->geom->name, cp->geom->class->name)); >> + cp->flags |= G_CF_ORPHAN; >> cp->geom->orphan(cp); >> - cp = cp2; >> } >> if (LIST_EMPTY(&pp->consumers) && wf) >> g_destroy_provider(pp); >> >> Modified: stable/9/sys/geom/geom_io.c >> ============================================================================== >> --- stable/9/sys/geom/geom_io.c Fri Apr 5 11:30:31 2013 (r249151) >> +++ stable/9/sys/geom/geom_io.c Fri Apr 5 11:41:56 2013 (r249152) >> @@ -311,6 +311,8 @@ g_io_check(struct bio *bp) >> /* if provider is marked for error, don't disturb. */ >> if (pp->error) >> return (pp->error); >> + if (cp->flags & G_CF_ORPHAN) >> + return (ENXIO); >> >> switch(bp->bio_cmd) { >> case BIO_READ: >> >> Modified: stable/9/sys/geom/geom_slice.c >> ============================================================================== >> --- stable/9/sys/geom/geom_slice.c Fri Apr 5 11:30:31 2013 (r249151) >> +++ stable/9/sys/geom/geom_slice.c Fri Apr 5 11:41:56 2013 (r249152) >> @@ -465,6 +465,7 @@ g_slice_spoiled(struct g_consumer *cp) >> g_topology_assert(); >> gp = cp->geom; >> g_trace(G_T_TOPOLOGY, "g_slice_spoiled(%p/%s)", cp, gp->name); >> + cp->flags |= G_CF_ORPHAN; >> gsp = gp->softc; >> gp->softc = NULL; >> g_slice_free(gsp); >> >> Modified: stable/9/sys/geom/geom_subr.c >> ============================================================================== >> --- stable/9/sys/geom/geom_subr.c Fri Apr 5 11:30:31 2013 (r249151) >> +++ stable/9/sys/geom/geom_subr.c Fri Apr 5 11:41:56 2013 (r249152) >> @@ -260,10 +260,11 @@ g_modevent(module_t mod, int type, void >> static void >> g_retaste_event(void *arg, int flag) >> { >> - struct g_class *cp, *mp; >> - struct g_geom *gp, *gp2; >> + struct g_class *mp, *mp2; >> + struct g_geom *gp; >> struct g_hh00 *hh; >> struct g_provider *pp; >> + struct g_consumer *cp; >> >> g_topology_assert(); >> if (flag == EV_CANCEL) /* XXX: can't happen ? */ >> @@ -280,17 +281,20 @@ g_retaste_event(void *arg, int flag) >> } >> g_trace(G_T_TOPOLOGY, "g_retaste(%s)", mp->name); >> >> - LIST_FOREACH(cp, &g_classes, class) { >> - LIST_FOREACH(gp, &cp->geom, geom) { >> + LIST_FOREACH(mp2, &g_classes, class) { >> + LIST_FOREACH(gp, &mp2->geom, geom) { >> LIST_FOREACH(pp, &gp->provider, provider) { >> if (pp->acr || pp->acw || pp->ace) >> continue; >> - LIST_FOREACH(gp2, &mp->geom, geom) { >> - if (!strcmp(pp->name, gp2->name)) >> + LIST_FOREACH(cp, &pp->consumers, consumers) { >> + if (cp->geom->class == mp && >> + (cp->flags & G_CF_ORPHAN) == 0) >> break; >> } >> - if (gp2 != NULL) >> - g_wither_geom(gp2, ENXIO); >> + if (cp != NULL) { >> + cp->flags |= G_CF_ORPHAN; >> + g_wither_geom(cp->geom, ENXIO); >> + } >> mp->taste(mp, pp, 0); >> g_topology_assert(); >> } >> @@ -531,7 +535,7 @@ g_new_provider_event(void *arg, int flag >> { >> struct g_class *mp; >> struct g_provider *pp; >> - struct g_consumer *cp; >> + struct g_consumer *cp, *next_cp; >> >> g_topology_assert(); >> if (flag == EV_CANCEL) >> @@ -542,11 +546,17 @@ g_new_provider_event(void *arg, int flag >> G_VALID_PROVIDER(pp); >> KASSERT(!(pp->flags & G_PF_WITHER), >> ("g_new_provider_event but withered")); >> + LIST_FOREACH_SAFE(cp, &pp->consumers, consumers, next_cp) { >> + if ((cp->flags & G_CF_ORPHAN) == 0 && >> + cp->geom->attrchanged != NULL) >> + cp->geom->attrchanged(cp, "GEOM::media"); >> + } >> LIST_FOREACH(mp, &g_classes, class) { >> if (mp->taste == NULL) >> continue; >> LIST_FOREACH(cp, &pp->consumers, consumers) >> - if (cp->geom->class == mp) >> + if (cp->geom->class == mp && >> + (cp->flags & G_CF_ORPHAN) == 0) >> break; >> if (cp != NULL) >> continue; >> @@ -803,7 +813,7 @@ g_access(struct g_consumer *cp, int dcr, >> * are probably just ahead of the event telling us that. Fail >> * now rather than having to unravel this later. >> */ >> - if (cp->geom->spoiled != NULL && cp->spoiled && >> + if (cp->geom->spoiled != NULL && (cp->flags & G_CF_SPOILED) && >> (dcr > 0 || dcw > 0 || dce > 0)) >> return (ENXIO); >> >> @@ -953,6 +963,7 @@ g_std_spoiled(struct g_consumer *cp) >> g_topology_assert(); >> G_VALID_CONSUMER(cp); >> g_trace(G_T_TOPOLOGY, "g_std_spoiled(%p)", cp); >> + cp->flags |= G_CF_ORPHAN; >> g_detach(cp); >> gp = cp->geom; >> LIST_FOREACH(pp, &gp->provider, provider) >> @@ -988,9 +999,9 @@ g_spoil_event(void *arg, int flag) >> G_VALID_PROVIDER(pp); >> for (cp = LIST_FIRST(&pp->consumers); cp != NULL; cp = cp2) { >> cp2 = LIST_NEXT(cp, consumers); >> - if (!cp->spoiled) >> + if ((cp->flags & G_CF_SPOILED) == 0) >> continue; >> - cp->spoiled = 0; >> + cp->flags &= ~G_CF_SPOILED; >> if (cp->geom->spoiled == NULL) >> continue; >> cp->geom->spoiled(cp); >> @@ -1015,11 +1026,54 @@ g_spoil(struct g_provider *pp, struct g_ >> KASSERT(cp2->acw == 0, ("spoiling cp->acw = %d", cp2->acw)); >> */ >> KASSERT(cp2->ace == 0, ("spoiling cp->ace = %d", cp2->ace)); >> - cp2->spoiled++; >> + cp2->flags |= G_CF_SPOILED; >> } >> g_post_event(g_spoil_event, pp, M_WAITOK, pp, NULL); >> } >> >> +static void >> +g_media_changed_event(void *arg, int flag) >> +{ >> + struct g_provider *pp; >> + int retaste; >> + >> + g_topology_assert(); >> + if (flag == EV_CANCEL) >> + return; >> + pp = arg; >> + G_VALID_PROVIDER(pp); >> + >> + /* >> + * If provider was not open for writing, queue retaste after spoiling. >> + * If it was, retaste will happen automatically on close. >> + */ >> + retaste = (pp->acw == 0 && pp->error == 0 && >> + !(pp->geom->flags & G_GEOM_WITHER)); >> + g_spoil_event(arg, flag); >> + if (retaste) >> + g_post_event(g_new_provider_event, pp, M_WAITOK, pp, NULL); >> +} >> + >> +int >> +g_media_changed(struct g_provider *pp, int flag) >> +{ >> + struct g_consumer *cp; >> + >> + LIST_FOREACH(cp, &pp->consumers, consumers) >> + cp->flags |= G_CF_SPOILED; >> + return (g_post_event(g_media_changed_event, pp, flag, pp, NULL)); >> +} >> + >> +int >> +g_media_gone(struct g_provider *pp, int flag) >> +{ >> + struct g_consumer *cp; >> + >> + LIST_FOREACH(cp, &pp->consumers, consumers) >> + cp->flags |= G_CF_SPOILED; >> + return (g_post_event(g_spoil_event, pp, flag, pp, NULL)); >> +} >> + >> int >> g_getattr__(const char *attr, struct g_consumer *cp, void *var, int len) >> { >> @@ -1175,15 +1229,15 @@ db_show_geom_consumer(int indent, struct >> cp->provider); >> } >> gprintln(" access: r%dw%de%d", cp->acr, cp->acw, cp->ace); >> - gprintln(" spoiled: %d", cp->spoiled); >> + gprintln(" flags: 0x%04x", cp->flags); >> gprintln(" nstart: %u", cp->nstart); >> gprintln(" nend: %u", cp->nend); >> } else { >> gprintf("consumer: %p (%s), access=r%dw%de%d", cp, >> cp->provider != NULL ? cp->provider->name : "none", >> cp->acr, cp->acw, cp->ace); >> - if (cp->spoiled) >> - db_printf(", spoiled=%d", cp->spoiled); >> + if (cp->flags) >> + db_printf(", flags=0x%04x", cp->flags); >> db_printf("\n"); >> } >> } >> >> Modified: stable/9/sys/geom/part/g_part.c >> ============================================================================== >> --- stable/9/sys/geom/part/g_part.c Fri Apr 5 11:30:31 2013 (r249151) >> +++ stable/9/sys/geom/part/g_part.c Fri Apr 5 11:41:56 2013 (r249152) >> @@ -2055,6 +2055,7 @@ g_part_spoiled(struct g_consumer *cp) >> G_PART_TRACE((G_T_TOPOLOGY, "%s(%s)", __func__, cp->provider->name)); >> g_topology_assert(); >> >> + cp > -- Alexander Motin