From owner-svn-src-stable@FreeBSD.ORG Wed Apr 24 23:39:41 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 AFCEB23E for ; Wed, 24 Apr 2013 23:39:41 +0000 (UTC) (envelope-from scott4long@yahoo.com) Received: from nm30-vm0.bullet.mail.bf1.yahoo.com (nm30-vm0.bullet.mail.bf1.yahoo.com [98.139.213.126]) by mx1.freebsd.org (Postfix) with ESMTP id C5F781452 for ; Wed, 24 Apr 2013 23:39:40 +0000 (UTC) Received: from [98.139.212.149] by nm30.bullet.mail.bf1.yahoo.com with NNFMP; 24 Apr 2013 23:39:33 -0000 Received: from [98.139.213.2] by tm6.bullet.mail.bf1.yahoo.com with NNFMP; 24 Apr 2013 23:39:33 -0000 Received: from [127.0.0.1] by smtp102.mail.bf1.yahoo.com with NNFMP; 24 Apr 2013 23:39:33 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.com; s=s1024; t=1366846773; bh=0/qTGcaGGbpkiHp74xKa2YuRXgIyLm5LQmhjFqyKyfM=; h=X-Yahoo-Newman-Id:X-Yahoo-Newman-Property:X-YMail-OSG:X-Yahoo-SMTP:X-Rocket-Received:Content-Type:Mime-Version:Subject:From:In-Reply-To:Date:Cc:Content-Transfer-Encoding:Message-Id:References:To:X-Mailer; b=eOYxII5KWbPbE+01TcVuoDumbserA07tO4iRxQgNNDFq0E7wSOuR/1Vdyz+FUaUuHCGmeSRSBPSTBm7TZZIi0M9CeO8W7L471fVytnKX+3ffrvofCnmxA6LcHGPNXL+coxTBCzyr0xFtKu6S4taK0nP+a28hNDfI+mHSr1MzNjk= X-Yahoo-Newman-Id: 81895.61328.bm@smtp102.mail.bf1.yahoo.com X-Yahoo-Newman-Property: ymail-3 X-YMail-OSG: yBlNZqcVM1lyfwpwxDvMgGZHGGBBT2Wjt1JKfXmqHL.RwzU t7rlMhZiEqukMtgSZAvdwhEWmn7qMzZT_x.A.ErxaVCtfDr_WW3y00ItKs_U dF8bQ5xPTEH9Bm4pATYcMdLfnAF8PIwqYaraPWTv0xnzohMuhWXD9m7pt7sG lWfep3MTe04m3R0g.ggECXaJcqPuya.kr1aklc7seoxwuKZR173FPaRaMvTN zkQHqIDls9YDOa4eP3bETaOcdkQ9rIYORKUmQY9G2aEfZNDuixLN21ICFjwS d0jVFHfNw6N7KCil0ehzSovzdPYYc7l8zjU8OXWKI0BCZjRqK9pdQFUaaubK mwqIxewSXgjrvnxUBx6Vwvo5daGw6E0xwaCPtjNGc4BLPx7gpLrDvKPlKfQG 4froaneFkE4wbtL5e0xAl8y6FXNaaj3pg_PlwW6xOItLxTuQmGG3YYznoRfU ftNouxXVLQE4- X-Yahoo-SMTP: clhABp.swBB7fs.LwIJpv3jkWgo2NU8- X-Rocket-Received: from phobos.corp.netflix.com (scott4long@69.53.237.66 with ) by smtp102.mail.bf1.yahoo.com with SMTP; 24 Apr 2013 16:39:32 -0700 PDT Content-Type: text/plain; charset=us-ascii Mime-Version: 1.0 (Mac OS X Mail 6.3 \(1503\)) Subject: Re: svn commit: r249152 - in stable/9/sys: cam cam/ata cam/scsi geom geom/part From: Scott Long In-Reply-To: <201304051141.r35Bfui1062429@svn.freebsd.org> Date: Wed, 24 Apr 2013 16:39:31 -0700 Content-Transfer-Encoding: quoted-printable Message-Id: <363EF017-CFC2-4006-8F1B-E18A4091F2CC@yahoo.com> References: <201304051141.r35Bfui1062429@svn.freebsd.org> To: Alexander Motin X-Mailer: Apple Mail (2.1503) 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: Wed, 24 Apr 2013 23:39:41 -0000 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. Scott 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 >=20 > 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. >=20 > 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) >=20 > Modified: stable/9/sys/cam/ata/ata_all.h > = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D > --- 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; >=20 > +#define SID_AEN 0x04 /* Abuse inq_flags bit to track = enabled AEN. */ > #define SID_DMA 0x10 /* Abuse inq_flags bit to track = enabled DMA. */ >=20 > struct ata_cmd { >=20 > Modified: stable/9/sys/cam/ata/ata_xpt.c > = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D > --- 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 |=3D SID_AEN; > + else > + path->device->inq_flags &=3D ~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 =3D CTS_SATA_VALID_CAPS; > xpt_action((union ccb *)&cts); > softc->caps =3D caps; > + /* Remember what transport thinks about AEN. */ > + if (softc->caps & CTS_SATA_CAPS_H_AN) > + path->device->inq_flags |=3D SID_AEN; > + else > + path->device->inq_flags &=3D ~SID_AEN; > + xpt_async(AC_GETDEV_CHANGED, path, NULL); > if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) = { > path->device->flags &=3D ~CAM_DEV_UNCONFIGURED; > xpt_acquire_device(path->device); >=20 > Modified: stable/9/sys/cam/cam_ccb.h > = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D > --- 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 =3D 0x4000,/* Device reported UNIT = ATTENTION */ > AC_ADVINFO_CHANGED =3D 0x2000,/* Advance info might have = changes */ > AC_CONTRACT =3D 0x1000,/* A contractual callback */ > AC_GETDEV_CHANGED =3D 0x800,/* Getdev info might have = changed */ >=20 > Modified: stable/9/sys/cam/cam_periph.c > = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D > --- 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; >=20 > print =3D 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 =3D=3D SSD_KEY_UNIT_ATTENTION) { > + xpt_async(AC_UNIT_ATTENTION, orig_ccb->ccb_h.path, = orig_ccb); > } >=20 > /* Attempt a retry */ >=20 > Modified: stable/9/sys/cam/cam_xpt.c > = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D > --- 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"); > } >=20 > Modified: stable/9/sys/cam/scsi/scsi_cd.c > = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D > --- 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 =3D 0x0002, > CD_FLAG_DISC_LOCKED =3D 0x0004, > CD_FLAG_DISC_REMOVABLE =3D 0x0008, > + CD_FLAG_SAW_MEDIA =3D 0x0010, > CD_FLAG_CHANGER =3D 0x0040, > CD_FLAG_ACTIVE =3D 0x0080, > CD_FLAG_SCHED_ON_COMP =3D 0x0100, > @@ -110,6 +111,7 @@ typedef enum { > CD_CCB_PROBE =3D 0x01, > CD_CCB_BUFFER_IO =3D 0x02, > CD_CCB_WAITING =3D 0x03, > + CD_CCB_TUR =3D 0x04, > CD_CCB_TYPE_MASK =3D 0x0F, > CD_CCB_RETRY_UA =3D 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; > }; >=20 > struct cd_page_sizes { > @@ -281,6 +285,7 @@ static int cdsendkey(struct = cam_periph=20 > struct dvd_authinfo *authinfo); > static int cdreaddvdstructure(struct cam_periph = *periph, > struct dvd_struct = *dvdstruct); > +static timeout_t cdmediapoll; >=20 > static struct periph_driver cddriver =3D > { > @@ -290,6 +295,9 @@ static struct periph_driver cddriver =3D >=20 > PERIPHDRIVER_DECLARE(cd, cddriver); >=20 > +#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 >=20 > +static int cd_poll_period =3D CD_DEFAULT_POLL_PERIOD; > static int cd_retry_count =3D CD_DEFAULT_RETRY; > static int cd_timeout =3D CD_DEFAULT_TIMEOUT; > static int changer_min_busy_seconds =3D CHANGER_MIN_BUSY_SECONDS; > @@ -311,6 +320,9 @@ static int changer_max_busy_seconds =3D 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"); > } >=20 > + 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; >=20 > periph =3D (struct cam_periph *)callback_arg; > switch (code) { > @@ -541,10 +555,39 @@ cdasync(void *callback_arg, u_int32_t co >=20 > break; > } > + case AC_UNIT_ATTENTION: > + { > + union ccb *ccb; > + int error_code, sense_key, asc, ascq; > + > + softc =3D (struct cd_softc *)periph->softc; > + ccb =3D (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) !=3D periph && > + scsi_extract_sense_ccb(ccb, > + &error_code, &sense_key, &asc, &ascq)) { > + if (asc =3D=3D 0x28 && ascq =3D=3D 0x00) > + disk_media_changed(softc->disk, = M_NOWAIT); > + } > + cam_periph_async(periph, code, path, arg); > + break; > + } > + case AC_SCSI_AEN: > + softc =3D (struct cd_softc *)periph->softc; > + if (softc->state =3D=3D CD_STATE_NORMAL && !softc->tur) = { > + if (cam_periph_acquire(periph) =3D=3D = CAM_REQ_CMP) { > + softc->tur =3D 1; > + xpt_schedule(periph, CAM_PRIORITY_DEV); > + } > + } > + /* FALLTHROUGH */ > case AC_SENT_BDR: > case AC_BUS_RESET: > { > - struct cd_softc *softc; > struct ccb_hdr *ccbh; >=20 > softc =3D (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); >=20 > /* > * If the target lun is greater than 0, we most likely have a CD > @@ -1001,6 +1044,17 @@ cdregister(struct cam_periph *periph, vo > } > } >=20 > + /* > + * 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) =3D=3D 0 && > + (cgd->inq_flags & SID_AEN) =3D=3D 0 && > + cd_poll_period !=3D 0) > + callout_reset(&softc->mediapoll_c, cd_poll_period * hz, > + cdmediapoll, periph); > + > cdregisterexit: >=20 > if ((softc->flags & CD_FLAG_CHANGER) =3D=3D 0) > @@ -1496,8 +1550,25 @@ cdstart(struct cam_periph *periph, union > periph->immediate_priority =3D = CAM_PRIORITY_NONE; > wakeup(&periph->ccb_list); > } else if (bp =3D=3D NULL) { > - xpt_release_ccb(start_ccb); > + if (softc->tur) { > + softc->tur =3D 0; > + csio =3D &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 =3D NULL; > + start_ccb->ccb_h.ccb_state =3D = CD_CCB_TUR; > + xpt_action(start_ccb); > + } else > + xpt_release_ccb(start_ccb); > } else { > + if (softc->tur) { > + softc->tur =3D 0; > + cam_periph_release_locked(periph); > + } > bioq_remove(&softc->bio_queue, bp); >=20 > scsi_read_write(&start_ccb->csio, > @@ -1541,7 +1612,7 @@ cdstart(struct cam_periph *periph, union >=20 > xpt_action(start_ccb); > } > - if (bp !=3D NULL) { > + if (bp !=3D 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=20 > wakeup(&done_ccb->ccb_h.cbfcnp); > return; > } > + case CD_CCB_TUR: > + { > + if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) !=3D = CAM_REQ_CMP) { > + > + if (cderror(done_ccb, CAM_RETRY_SELTO, > + SF_RETRY_UA | SF_NO_RECOVERY | SF_NO_PRINT) = =3D=3D > + ERESTART) > + return; > + if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) !=3D = 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 |=3D CD_FLAG_VALID_MEDIA; > + softc->flags |=3D CD_FLAG_SAW_MEDIA | = CD_FLAG_VALID_MEDIA; > softc->disk->d_sectorsize =3D softc->params.blksize; > softc->disk->d_mediasize =3D > (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 =3D=3D SSD_KEY_ILLEGAL_REQUEST) > error =3D cd6byteworkaround(ccb); > + else if (sense_key =3D=3D SSD_KEY_UNIT_ATTENTION && > + asc =3D=3D 0x28 && ascq =3D=3D 0x00) > + disk_media_changed(softc->disk, M_NOWAIT); > + else if (sense_key =3D=3D SSD_KEY_NOT_READY && > + asc =3D=3D 0x3a && (softc->flags & = CD_FLAG_SAW_MEDIA)) { > + softc->flags &=3D ~CD_FLAG_SAW_MEDIA; > + disk_media_gone(softc->disk, M_NOWAIT); > + } > } >=20 > if (error =3D=3D ERESTART) > @@ -3186,6 +3284,26 @@ cderror(union ccb *ccb, u_int32_t cam_fl > &softc->saved_ccb)); > } >=20 > +static void > +cdmediapoll(void *arg) > +{ > + struct cam_periph *periph =3D arg; > + struct cd_softc *softc =3D periph->softc; > + > + if (softc->flags & CD_FLAG_CHANGER) > + return; > + > + if (softc->state =3D=3D CD_STATE_NORMAL && !softc->tur) { > + if (cam_periph_acquire(periph) =3D=3D CAM_REQ_CMP) { > + softc->tur =3D 1; > + xpt_schedule(periph, CAM_PRIORITY_DEV); > + } > + } > + /* Queue us up again */ > + if (cd_poll_period !=3D 0) > + callout_schedule(&softc->mediapoll_c, cd_poll_period * = hz); > +} > + > /* > * Read table of contents > */ >=20 > Modified: stable/9/sys/cam/scsi/scsi_da.c > = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D > --- 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 =3D 0x002, > DA_FLAG_PACK_LOCKED =3D 0x004, > DA_FLAG_PACK_REMOVABLE =3D 0x008, > + DA_FLAG_SAW_MEDIA =3D 0x010, > DA_FLAG_NEED_OTAG =3D 0x020, > DA_FLAG_WENT_IDLE =3D 0x040, > DA_FLAG_RETRY_UA =3D 0x080, > @@ -101,6 +102,7 @@ typedef enum { > DA_CCB_WAITING =3D 0x04, > DA_CCB_DUMP =3D 0x05, > DA_CCB_DELETE =3D 0x06, > + DA_CCB_TUR =3D 0x07, > DA_CCB_TYPE_MASK =3D 0x0F, > DA_CCB_RETRY_UA =3D 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; > }; >=20 > 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 >=20 > #ifndef DA_DEFAULT_TIMEOUT > #define DA_DEFAULT_TIMEOUT 60 /* Timeout in seconds */ > @@ -889,12 +898,16 @@ static void dashutdown(void *arg, = int h > #endif >=20 >=20 > +static int da_poll_period =3D DA_DEFAULT_POLL_PERIOD; > static int da_retry_count =3D DA_DEFAULT_RETRY; > static int da_default_timeout =3D DA_DEFAULT_TIMEOUT; > static int da_send_ordered =3D DA_DEFAULT_SEND_ORDERED; >=20 > 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) =3D=3D 0) > daprevent(periph, PR_PREVENT); >=20 > + if (error =3D=3D 0) > + softc->flags |=3D DA_FLAG_SAW_MEDIA; > + > cam_periph_unhold(periph); > cam_periph_unlock(periph); >=20 > @@ -1068,7 +1084,8 @@ daschedule(struct cam_periph *periph) >=20 > /* 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 =3D CAM_PRIORITY_NORMAL; > } >=20 > @@ -1315,6 +1332,7 @@ dacleanup(struct cam_periph *periph) > xpt_print(periph->path, "can't remove sysctl = context\n"); > } >=20 > + 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; >=20 > periph =3D (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 =3D (struct da_softc *)periph->softc; > + ccb =3D (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) !=3D periph && > + scsi_extract_sense_ccb(ccb, > + &error_code, &sense_key, &asc, &ascq)) { > + if (asc =3D=3D 0x2A && ascq =3D=3D 0x09) { > + xpt_print(ccb->ccb_h.path, > + "capacity data has changed\n"); > + dareprobe(periph); > + } else if (asc =3D=3D 0x28 && ascq =3D=3D 0x00) > + disk_media_changed(softc->disk, = M_NOWAIT); > + } > + cam_periph_async(periph, code, path, arg); > + break; > + } > + case AC_SCSI_AEN: > + softc =3D (struct da_softc *)periph->softc; > + if (softc->state =3D=3D DA_STATE_NORMAL && !softc->tur) = { > + if (cam_periph_acquire(periph) =3D=3D = CAM_REQ_CMP) { > + softc->tur =3D 1; > + xpt_schedule(periph, CAM_PRIORITY_DEV); > + } > + } > + /* FALLTHROUGH */ > case AC_SENT_BDR: > case AC_BUS_RESET: > { > - struct da_softc *softc; > struct ccb_hdr *ccbh; >=20 > softc =3D (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); >=20 > /* > * Emit an attribute changed notification just in case=20 > @@ -1723,6 +1775,16 @@ daregister(struct cam_periph *periph, vo > */ > disk_attr_changed(softc->disk, "GEOM::physpath", M_NOWAIT); >=20 > + /* > + * 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) =3D=3D 0 && > + da_poll_period !=3D 0) > + callout_reset(&softc->mediapoll_c, da_poll_period * hz, > + damediapoll, periph); > + > xpt_schedule(periph, CAM_PRIORITY_DEV); >=20 > return(CAM_REQ_CMP); > @@ -1860,9 +1922,25 @@ dastart(struct cam_periph *periph, union > /* Run regular command. */ > bp =3D bioq_takefirst(&softc->bio_queue); > if (bp =3D=3D NULL) { > - xpt_release_ccb(start_ccb); > + if (softc->tur) { > + softc->tur =3D 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 =3D NULL; > + start_ccb->ccb_h.ccb_state =3D = DA_CCB_TUR; > + xpt_action(start_ccb); > + } else > + xpt_release_ccb(start_ccb); > break; > } > + if (softc->tur) { > + softc->tur =3D 0; > + cam_periph_release_locked(periph); > + } >=20 > if ((bp->bio_flags & BIO_ORDERED) !=3D 0 || > (softc->flags & DA_FLAG_NEED_OTAG) !=3D 0) { > @@ -2429,6 +2507,25 @@ dadone(struct cam_periph *periph, union=20 > case DA_CCB_DUMP: > /* No-op. We're polling */ > return; > + case DA_CCB_TUR: > + { > + if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) !=3D = CAM_REQ_CMP) { > + > + if (daerror(done_ccb, CAM_RETRY_SELTO, > + SF_RETRY_UA | SF_NO_RECOVERY | SF_NO_PRINT) = =3D=3D > + ERESTART) > + return; > + if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) !=3D = 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 |=3D SF_NO_PRINT; > + } else if (sense_key =3D=3D SSD_KEY_UNIT_ATTENTION && > + asc =3D=3D 0x28 && ascq =3D=3D 0x00) > + disk_media_changed(softc->disk, M_NOWAIT); > + else if (sense_key =3D=3D SSD_KEY_NOT_READY && > + asc =3D=3D 0x3a && (softc->flags & = DA_FLAG_SAW_MEDIA)) { > + softc->flags &=3D ~DA_FLAG_SAW_MEDIA; > + disk_media_gone(softc->disk, M_NOWAIT); > } > } > if (error =3D=3D ERESTART) > @@ -2505,6 +2609,23 @@ daerror(union ccb *ccb, u_int32_t cam_fl > } >=20 > static void > +damediapoll(void *arg) > +{ > + struct cam_periph *periph =3D arg; > + struct da_softc *softc =3D periph->softc; > + > + if (softc->state =3D=3D DA_STATE_NORMAL && !softc->tur) { > + if (cam_periph_acquire(periph) =3D=3D CAM_REQ_CMP) { > + softc->tur =3D 1; > + daschedule(periph); > + } > + } > + /* Queue us up again */ > + if (da_poll_period !=3D 0) > + callout_schedule(&softc->mediapoll_c, da_poll_period * = hz); > +} > + > +static void > daprevent(struct cam_periph *periph, int action) > { > struct da_softc *softc; >=20 > Modified: stable/9/sys/geom/geom.h > = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D > --- 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; >=20 > @@ -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); >=20 >=20 > Modified: stable/9/sys/geom/geom_dev.c > = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D > --- 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") =3D=3D 0) { > + dev =3D cp->geom->softc; > + snprintf(buf, sizeof(buf), "cdev=3D%s", dev->si_name); > + devctl_notify_f("DEVFS", "CDEV", "MEDIACHANGE", buf, = M_WAITOK); > + dev =3D cp->cp_alias_dev; > + if (dev !=3D NULL) { > + snprintf(buf, sizeof(buf), "cdev=3D%s", = dev->si_name); > + devctl_notify_f("DEVFS", "CDEV", "MEDIACHANGE", = buf, > + M_WAITOK); > + } > + return; > + } >=20 > if (strcmp(attr, "GEOM::physpath") !=3D 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 =3D=3D 0 && strlen(physpath) !=3D 0) { > - struct cdev *dev; > struct cdev *old_alias_dev; > struct cdev **alias_devp; >=20 > @@ -161,9 +176,6 @@ g_dev_taste(struct g_class *mp, struct g >=20 > 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 =3D=3D mp) > - return (NULL); > gp =3D g_new_geomf(mp, "%s", pp->name); > cp =3D g_new_consumer(gp); > error =3D g_attach(cp, pp); >=20 > Modified: stable/9/sys/geom/geom_disk.c > = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D > --- 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); > } >=20 > +void > +disk_media_changed(struct disk *dp, int flag) > +{ > + struct g_geom *gp; > + struct g_provider *pp; > + > + gp =3D dp->d_geom; > + if (gp !=3D 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 =3D dp->d_geom; > + if (gp !=3D NULL) { > + LIST_FOREACH(pp, &gp->provider, provider) > + g_media_gone(pp, flag); > + } > +} > + > static void > g_kern_disks(void *p, int flag __unused) > { >=20 > Modified: stable/9/sys/geom/geom_disk.h > = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D > --- 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=20 > 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); >=20 > #define DISK_VERSION_00 0x58561059 > #define DISK_VERSION_01 0x5856105a >=20 > Modified: stable/9/sys/geom/geom_event.c > = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D > --- 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 =3D LIST_FIRST(&pp->consumers); > - while (cp !=3D NULL) { > - cp2 =3D LIST_NEXT(cp, consumers); > + LIST_FOREACH_SAFE(cp, &pp->consumers, consumers, cp2) { > KASSERT(cp->geom->orphan !=3D NULL, > ("geom %s has no orphan, class %s", > cp->geom->name, cp->geom->class->name)); > + cp->flags |=3D G_CF_ORPHAN; > cp->geom->orphan(cp); > - cp =3D cp2; > } > if (LIST_EMPTY(&pp->consumers) && wf) > g_destroy_provider(pp); >=20 > Modified: stable/9/sys/geom/geom_io.c > = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D > --- 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); >=20 > switch(bp->bio_cmd) { > case BIO_READ: >=20 > Modified: stable/9/sys/geom/geom_slice.c > = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D > --- 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 =3D cp->geom; > g_trace(G_T_TOPOLOGY, "g_slice_spoiled(%p/%s)", cp, gp->name); > + cp->flags |=3D G_CF_ORPHAN; > gsp =3D gp->softc; > gp->softc =3D NULL; > g_slice_free(gsp); >=20 > Modified: stable/9/sys/geom/geom_subr.c > = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D > --- 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=20 > 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; >=20 > g_topology_assert(); > if (flag =3D=3D 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); >=20 > - 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 =3D=3D mp && > + (cp->flags & G_CF_ORPHAN) =3D=3D= 0) > break; > } > - if (gp2 !=3D NULL) > - g_wither_geom(gp2, ENXIO); > + if (cp !=3D NULL) { > + cp->flags |=3D 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; >=20 > g_topology_assert(); > if (flag =3D=3D 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) =3D=3D 0 && > + cp->geom->attrchanged !=3D NULL) > + cp->geom->attrchanged(cp, "GEOM::media"); > + } > LIST_FOREACH(mp, &g_classes, class) { > if (mp->taste =3D=3D NULL) > continue; > LIST_FOREACH(cp, &pp->consumers, consumers) > - if (cp->geom->class =3D=3D mp) > + if (cp->geom->class =3D=3D mp && > + (cp->flags & G_CF_ORPHAN) =3D=3D 0) > break; > if (cp !=3D 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 !=3D NULL && cp->spoiled && > + if (cp->geom->spoiled !=3D NULL && (cp->flags & G_CF_SPOILED) && > (dcr > 0 || dcw > 0 || dce > 0)) > return (ENXIO); >=20 > @@ -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 |=3D G_CF_ORPHAN; > g_detach(cp); > gp =3D 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 =3D LIST_FIRST(&pp->consumers); cp !=3D NULL; cp =3D = cp2) { > cp2 =3D LIST_NEXT(cp, consumers); > - if (!cp->spoiled) > + if ((cp->flags & G_CF_SPOILED) =3D=3D 0) > continue; > - cp->spoiled =3D 0; > + cp->flags &=3D ~G_CF_SPOILED; > if (cp->geom->spoiled =3D=3D NULL) > continue; > cp->geom->spoiled(cp); > @@ -1015,11 +1026,54 @@ g_spoil(struct g_provider *pp, struct g_ > KASSERT(cp2->acw =3D=3D 0, ("spoiling cp->acw =3D %d", = cp2->acw)); > */ > KASSERT(cp2->ace =3D=3D 0, ("spoiling cp->ace =3D %d", = cp2->ace)); > - cp2->spoiled++; > + cp2->flags |=3D G_CF_SPOILED; > } > g_post_event(g_spoil_event, pp, M_WAITOK, pp, NULL); > } >=20 > +static void > +g_media_changed_event(void *arg, int flag) > +{ > + struct g_provider *pp; > + int retaste; > + > + g_topology_assert(); > + if (flag =3D=3D EV_CANCEL) > + return; > + pp =3D 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 =3D (pp->acw =3D=3D 0 && pp->error =3D=3D 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 |=3D 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 |=3D 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=3Dr%dw%de%d", cp, > cp->provider !=3D NULL ? cp->provider->name : = "none", > cp->acr, cp->acw, cp->ace); > - if (cp->spoiled) > - db_printf(", spoiled=3D%d", cp->spoiled); > + if (cp->flags) > + db_printf(", flags=3D0x%04x", cp->flags); > db_printf("\n"); > } > } >=20 > Modified: stable/9/sys/geom/part/g_part.c > = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D > --- 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(); >=20 > + cp