Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F107147954
D35784.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
15 KB
Referenced Files
None
Subscribers
None
D35784.diff
View Options
diff --git a/sys/cam/ata/ata_da.c b/sys/cam/ata/ata_da.c
--- a/sys/cam/ata/ata_da.c
+++ b/sys/cam/ata/ata_da.c
@@ -1845,9 +1845,11 @@
TASK_INIT(&softc->sysctl_task, 0, adasysctlinit, periph);
/*
- * Register this media as a disk
+ * Take a reference on the periph while adastart is called to finish
+ * the probe. The reference will be dropped in adaprobedone at the
+ * end of probe.
*/
- (void)cam_periph_hold(periph, PRIBIO);
+ (void)cam_periph_acquire(periph);
cam_periph_unlock(periph);
snprintf(announce_buf, ADA_ANNOUNCETMP_SZ,
"kern.cam.ada.%d.quirks", periph->unit_number);
@@ -1905,19 +1907,6 @@
softc->disk->d_name = "ada";
softc->disk->d_drv1 = periph;
softc->disk->d_unit = periph->unit_number;
-
- /*
- * Acquire a reference to the periph before we register with GEOM.
- * We'll release this reference once GEOM calls us back (via
- * adadiskgonecb()) telling us that our provider has been freed.
- */
- if (cam_periph_acquire(periph) != 0) {
- xpt_print(periph->path, "%s: lost periph during "
- "registration!\n", __func__);
- cam_periph_lock(periph);
- return (CAM_REQ_CMP_ERR);
- }
- disk_create(softc->disk, DISK_VERSION);
cam_periph_lock(periph);
dp = &softc->params;
@@ -1960,6 +1949,9 @@
SBT_1S / ADA_ORDEREDTAG_INTERVAL * ada_default_timeout, 0,
adasendorderedtag, softc, C_PREL(1));
+ /* Released after probe when disk_create() call pass it to GEOM. */
+ cam_periph_hold_boot(periph);
+
if (ADA_RA >= 0 && softc->flags & ADA_FLAG_CAN_RAHEAD) {
softc->state = ADA_STATE_RAHEAD;
} else if (ADA_WC >= 0 && softc->flags & ADA_FLAG_CAN_WCACHE) {
@@ -1977,7 +1969,6 @@
}
xpt_schedule(periph, CAM_PRIORITY_DEV);
-
return(CAM_REQ_CMP);
}
@@ -2705,10 +2696,17 @@
adaschedule(periph);
if ((softc->flags & ADA_FLAG_ANNOUNCED) == 0) {
softc->flags |= ADA_FLAG_ANNOUNCED;
- cam_periph_unhold(periph);
- } else {
- cam_periph_release_locked(periph);
+
+ /*
+ * We'll release this reference once GEOM calls us back via
+ * adadiskgonecb(), telling us that our provider has been freed.
+ */
+ if (cam_periph_acquire(periph) == 0)
+ disk_create(softc->disk, DISK_VERSION);
+
+ cam_periph_release_boot(periph);
}
+ cam_periph_release_locked(periph);
}
static void
diff --git a/sys/cam/cam_periph.h b/sys/cam/cam_periph.h
--- a/sys/cam/cam_periph.h
+++ b/sys/cam/cam_periph.h
@@ -150,6 +150,7 @@
ac_code deferred_ac;
struct task periph_run_task;
uma_zone_t ccb_zone;
+ struct root_hold_token periph_rootmount;
};
#define CAM_PERIPH_MAXMAPS 2
@@ -175,6 +176,8 @@
void cam_periph_release_locked_buses(struct cam_periph *periph);
int cam_periph_hold(struct cam_periph *periph, int priority);
void cam_periph_unhold(struct cam_periph *periph);
+void cam_periph_hold_boot(struct cam_periph *periph);
+void cam_periph_release_boot(struct cam_periph *periph);
void cam_periph_invalidate(struct cam_periph *periph);
int cam_periph_mapmem(union ccb *ccb,
struct cam_periph_map_info *mapinfo,
diff --git a/sys/cam/cam_periph.c b/sys/cam/cam_periph.c
--- a/sys/cam/cam_periph.c
+++ b/sys/cam/cam_periph.c
@@ -530,6 +530,20 @@
cam_periph_release_locked(periph);
}
+void
+cam_periph_hold_boot(struct cam_periph *periph)
+{
+
+ root_mount_hold_token(periph->periph_name, &periph->periph_rootmount);
+}
+
+void
+cam_periph_release_boot(struct cam_periph *periph)
+{
+
+ root_mount_rel(&periph->periph_rootmount);
+}
+
/*
* Look for the next unit number that is not currently in use for this
* peripheral type starting at "newunit". Also exclude unit numbers that
diff --git a/sys/cam/nvme/nvme_da.c b/sys/cam/nvme/nvme_da.c
--- a/sys/cam/nvme/nvme_da.c
+++ b/sys/cam/nvme/nvme_da.c
@@ -886,7 +886,7 @@
/*
* Register this media as a disk
*/
- (void)cam_periph_hold(periph, PRIBIO);
+ (void)cam_periph_acquire(periph);
cam_periph_unlock(periph);
snprintf(announce_buf, sizeof(announce_buf),
"kern.cam.nda.%d.quirks", periph->unit_number);
@@ -964,20 +964,7 @@
if (nda_nvd_compat)
disk_add_alias(disk, "nvd");
- /*
- * Acquire a reference to the periph before we register with GEOM.
- * We'll release this reference once GEOM calls us back (via
- * ndadiskgonecb()) telling us that our provider has been freed.
- */
- if (cam_periph_acquire(periph) != 0) {
- xpt_print(periph->path, "%s: lost periph during "
- "registration!\n", __func__);
- cam_periph_lock(periph);
- return (CAM_REQ_CMP_ERR);
- }
- disk_create(softc->disk, DISK_VERSION);
cam_periph_lock(periph);
- cam_periph_unhold(periph);
snprintf(announce_buf, sizeof(announce_buf),
"%juMB (%ju %u byte sectors)",
@@ -1002,6 +989,15 @@
ndaasync, periph, periph->path);
softc->state = NDA_STATE_NORMAL;
+
+ /*
+ * We'll release this reference once GEOM calls us back via
+ * ndadiskgonecb(), telling us that our provider has been freed.
+ */
+ if (cam_periph_acquire(periph) == 0)
+ disk_create(softc->disk, DISK_VERSION);
+
+ cam_periph_release_locked(periph);
return(CAM_REQ_CMP);
}
diff --git a/sys/cam/scsi/scsi_cd.c b/sys/cam/scsi/scsi_cd.c
--- a/sys/cam/scsi/scsi_cd.c
+++ b/sys/cam/scsi/scsi_cd.c
@@ -650,10 +650,10 @@
softc->minimum_command_size = 6;
/*
- * Refcount and block open attempts until we are setup
- * Can't block
+ * Take a reference on the periph while cdstart is called to finish the
+ * probe. The reference will be dropped in cddone at the end of probe.
*/
- (void)cam_periph_hold(periph, PRIBIO);
+ (void)cam_periph_acquire(periph);
cam_periph_unlock(periph);
/*
* Load the user's default, if any.
@@ -714,20 +714,6 @@
softc->disk->d_hba_subdevice = cpi.hba_subdevice;
snprintf(softc->disk->d_attachment, sizeof(softc->disk->d_attachment),
"%s%d", cpi.dev_name, cpi.unit_number);
-
- /*
- * Acquire a reference to the periph before we register with GEOM.
- * We'll release this reference once GEOM calls us back (via
- * dadiskgonecb()) telling us that our provider has been freed.
- */
- if (cam_periph_acquire(periph) != 0) {
- xpt_print(periph->path, "%s: lost periph during "
- "registration!\n", __func__);
- cam_periph_lock(periph);
- return (CAM_REQ_CMP_ERR);
- }
-
- disk_create(softc->disk, DISK_VERSION);
cam_periph_lock(periph);
/*
@@ -748,6 +734,9 @@
0, cdmediapoll, periph, C_PREL(1));
}
+ /* Released after probe when disk_create() call pass it to GEOM. */
+ cam_periph_hold_boot(periph);
+
xpt_schedule(periph, CAM_PRIORITY_DEV);
return(CAM_REQ_CMP);
}
@@ -1385,7 +1374,16 @@
* operation.
*/
xpt_release_ccb(done_ccb);
- cam_periph_unhold(periph);
+
+ /*
+ * We'll release this reference once GEOM calls us back via
+ * cddiskgonecb(), telling us that our provider has been freed.
+ */
+ if (cam_periph_acquire(periph) == 0)
+ disk_create(softc->disk, DISK_VERSION);
+
+ cam_periph_release_boot(periph);
+ cam_periph_release_locked(periph);
return;
}
case CD_CCB_TUR:
diff --git a/sys/cam/scsi/scsi_da.c b/sys/cam/scsi/scsi_da.c
--- a/sys/cam/scsi/scsi_da.c
+++ b/sys/cam/scsi/scsi_da.c
@@ -329,7 +329,6 @@
DA_REF_OPEN = 1,
DA_REF_OPEN_HOLD,
DA_REF_CLOSE_HOLD,
- DA_REF_PROBE_HOLD,
DA_REF_TUR,
DA_REF_GEOM,
DA_REF_SYSCTL,
@@ -2602,9 +2601,17 @@
wakeup(&softc->disk->d_mediasize);
if ((softc->flags & DA_FLAG_ANNOUNCED) == 0) {
softc->flags |= DA_FLAG_ANNOUNCED;
- da_periph_unhold(periph, DA_REF_PROBE_HOLD);
- } else
- da_periph_release_locked(periph, DA_REF_REPROBE);
+
+ /*
+ * We'll release this reference once GEOM calls us back via
+ * dadiskgonecb(), telling us that our provider has been freed.
+ */
+ if (da_periph_acquire(periph, DA_REF_GEOM) == 0)
+ disk_create(softc->disk, DISK_VERSION);
+
+ cam_periph_release_boot(periph);
+ }
+ da_periph_release_locked(periph, DA_REF_REPROBE);
}
static void
@@ -2864,14 +2871,10 @@
}
/*
- * Take an exclusive section lock on the periph while dastart is called
- * to finish the probe. The lock will be dropped in dadone at the end
- * of probe. This locks out daopen and daclose from racing with the
- * probe.
- *
- * XXX if cam_periph_hold returns an error, we don't hold a refcount.
+ * Take a reference on the periph while dastart is called to finish the
+ * probe. The reference will be dropped in dadone at the end of probe.
*/
- (void)da_periph_hold(periph, PRIBIO, DA_REF_PROBE_HOLD);
+ (void)da_periph_acquire(periph, DA_REF_REPROBE);
/*
* Schedule a periodic event to occasionally send an
@@ -2967,20 +2970,6 @@
softc->disk->d_hba_subdevice = cpi.hba_subdevice;
snprintf(softc->disk->d_attachment, sizeof(softc->disk->d_attachment),
"%s%d", cpi.dev_name, cpi.unit_number);
-
- /*
- * Acquire a reference to the periph before we register with GEOM.
- * We'll release this reference once GEOM calls us back (via
- * dadiskgonecb()) telling us that our provider has been freed.
- */
- if (da_periph_acquire(periph, DA_REF_GEOM) != 0) {
- xpt_print(periph->path, "%s: lost periph during "
- "registration!\n", __func__);
- cam_periph_lock(periph);
- return (CAM_REQ_CMP_ERR);
- }
-
- disk_create(softc->disk, DISK_VERSION);
cam_periph_lock(periph);
/*
@@ -2994,14 +2983,6 @@
AC_ADVINFO_CHANGED | AC_SCSI_AEN | AC_UNIT_ATTENTION |
AC_INQ_CHANGED, daasync, periph, periph->path);
- /*
- * Emit an attribute changed notification just in case
- * physical path information arrived before our async
- * event handler was registered, but after anyone attaching
- * to our disk device polled it.
- */
- disk_attr_changed(softc->disk, "GEOM::physpath", M_NOWAIT);
-
/*
* Schedule a periodic media polling events.
*/
@@ -3013,8 +2994,10 @@
0, damediapoll, periph, C_PREL(1));
}
- xpt_schedule(periph, CAM_PRIORITY_DEV);
+ /* Released after probe when disk_create() call pass it to GEOM. */
+ cam_periph_hold_boot(periph);
+ xpt_schedule(periph, CAM_PRIORITY_DEV);
return(CAM_REQ_CMP);
}
diff --git a/sys/cam/scsi/scsi_enc.c b/sys/cam/scsi/scsi_enc.c
--- a/sys/cam/scsi/scsi_enc.c
+++ b/sys/cam/scsi/scsi_enc.c
@@ -205,7 +205,7 @@
if (enc->enc_vec.softc_cleanup != NULL)
enc->enc_vec.softc_cleanup(enc);
- root_mount_rel(&enc->enc_rootmount);
+ cam_periph_release_boot(periph);
ENC_FREE(enc);
}
@@ -842,7 +842,7 @@
* We've been through our state machine at least
* once. Allow the transition to userland.
*/
- root_mount_rel(&enc->enc_rootmount);
+ cam_periph_release_boot(enc->periph);
callout_reset_sbt(&enc->status_updater, 60 * SBT_1S, 0,
enc_status_updater, enc, C_PREL(1));
@@ -937,9 +937,8 @@
* through our state machine so that physical path data is
* present.
*/
- if (enc->enc_vec.poll_status != NULL) {
- root_mount_hold_token(periph->periph_name, &enc->enc_rootmount);
- }
+ if (enc->enc_vec.poll_status != NULL)
+ cam_periph_hold_boot(periph);
/*
* The softc field is set only once the enc is fully initialized
diff --git a/sys/cam/scsi/scsi_enc_internal.h b/sys/cam/scsi/scsi_enc_internal.h
--- a/sys/cam/scsi/scsi_enc_internal.h
+++ b/sys/cam/scsi/scsi_enc_internal.h
@@ -161,8 +161,6 @@
struct enc_fsm_state *enc_fsm_states;
- struct root_hold_token enc_rootmount;
-
#define ENC_ANNOUNCE_SZ 400
char announce_buf[ENC_ANNOUNCE_SZ];
};
diff --git a/sys/geom/geom_disk.h b/sys/geom/geom_disk.h
--- a/sys/geom/geom_disk.h
+++ b/sys/geom/geom_disk.h
@@ -69,6 +69,7 @@
typedef enum {
DISK_INIT_NONE,
+ DISK_INIT_CREATE,
DISK_INIT_START,
DISK_INIT_DONE
} disk_init_level;
@@ -125,7 +126,8 @@
/* Fields private to geom_disk, to be moved on next version bump */
LIST_HEAD(,disk_alias) d_aliases;
- struct g_event *d_event;
+ struct g_event *d_cevent;
+ struct g_event *d_devent;
};
#define DISKFLAG_RESERVED 0x0001 /* Was NEEDSGIANT */
diff --git a/sys/geom/geom_disk.c b/sys/geom/geom_disk.c
--- a/sys/geom/geom_disk.c
+++ b/sys/geom/geom_disk.c
@@ -721,6 +721,11 @@
sc = g_malloc(sizeof(*sc), M_WAITOK | M_ZERO);
mtx_init(&sc->done_mtx, "g_disk_done", NULL, MTX_DEF);
sc->dp = dp;
+ if (dp->d_devstat == NULL) {
+ dp->d_devstat = devstat_new_entry(dp->d_name, dp->d_unit,
+ dp->d_sectorsize, DEVSTAT_ALL_SUPPORTED,
+ DEVSTAT_TYPE_DIRECT, DEVSTAT_PRIORITY_MAX);
+ }
sc->d_devstat = dp->d_devstat;
gp = g_new_geomf(&g_disk_class, "%s%d", dp->d_name, dp->d_unit);
gp->softc = sc;
@@ -862,6 +867,9 @@
dp = g_malloc(sizeof(struct disk), M_WAITOK | M_ZERO);
LIST_INIT(&dp->d_aliases);
+ dp->d_init_level = DISK_INIT_NONE;
+ dp->d_cevent = g_alloc_event(M_WAITOK);
+ dp->d_devent = g_alloc_event(M_WAITOK);
return (dp);
}
@@ -888,31 +896,40 @@
KASSERT(dp->d_name != NULL, ("disk_create need d_name"));
KASSERT(*dp->d_name != 0, ("disk_create need d_name"));
KASSERT(strlen(dp->d_name) < SPECNAMELEN - 4, ("disk name too long"));
- if (dp->d_devstat == NULL)
- dp->d_devstat = devstat_new_entry(dp->d_name, dp->d_unit,
- dp->d_sectorsize, DEVSTAT_ALL_SUPPORTED,
- DEVSTAT_TYPE_DIRECT, DEVSTAT_PRIORITY_MAX);
- dp->d_geom = NULL;
- dp->d_event = g_alloc_event(M_WAITOK);
+ g_disk_ident_adjust(dp->d_ident, sizeof(dp->d_ident));
- dp->d_init_level = DISK_INIT_NONE;
+ dp->d_init_level = DISK_INIT_CREATE;
- g_disk_ident_adjust(dp->d_ident, sizeof(dp->d_ident));
- g_post_event(g_disk_create, dp, M_WAITOK, dp, NULL);
+ KASSERT(dp->d_cevent != NULL,
+ ("Disk create for %p with event NULL", dp));
+ g_post_event_ep(g_disk_create, dp, dp->d_cevent, dp, NULL);
}
void
disk_destroy(struct disk *dp)
{
+ struct disk_alias *dap, *daptmp;
- KASSERT(dp->d_event != NULL,
+ /* If disk_create() was never called, just free the resources. */
+ if (dp->d_init_level < DISK_INIT_CREATE) {
+ if (dp->d_devstat != NULL)
+ devstat_remove_entry(dp->d_devstat);
+ LIST_FOREACH_SAFE(dap, &dp->d_aliases, da_next, daptmp)
+ g_free(dap);
+ g_free(dp->d_cevent);
+ g_free(dp->d_devent);
+ g_free(dp);
+ return;
+ }
+
+ KASSERT(dp->d_devent != NULL,
("Disk destroy for %p with event NULL", dp));
disk_gone(dp);
dp->d_destroyed = 1;
g_cancel_event(dp);
if (dp->d_devstat != NULL)
devstat_remove_entry(dp->d_devstat);
- g_post_event_ep(g_disk_destroy, dp, dp->d_event, NULL);
+ g_post_event_ep(g_disk_destroy, dp, dp->d_devent, NULL);
}
void
@@ -979,14 +996,14 @@
void
disk_attr_changed(struct disk *dp, const char *attr, int flag)
{
- struct g_geom *gp;
+ struct g_geom *gp = dp->d_geom;
struct g_provider *pp;
char devnamebuf[128];
- gp = dp->d_geom;
- if (gp != NULL)
- LIST_FOREACH(pp, &gp->provider, provider)
- (void)g_attr_changed(pp, attr, flag);
+ if (gp == NULL)
+ return;
+ LIST_FOREACH(pp, &gp->provider, provider)
+ (void)g_attr_changed(pp, attr, flag);
snprintf(devnamebuf, sizeof(devnamebuf), "devname=%s%d", dp->d_name,
dp->d_unit);
devctl_notify("GEOM", "disk", attr, devnamebuf);
@@ -995,34 +1012,32 @@
void
disk_media_changed(struct disk *dp, int flag)
{
- struct g_geom *gp;
+ struct g_geom *gp = dp->d_geom;
struct g_provider *pp;
- gp = dp->d_geom;
- if (gp != NULL) {
- pp = LIST_FIRST(&gp->provider);
- if (pp != NULL) {
- KASSERT(LIST_NEXT(pp, provider) == NULL,
- ("geom %p has more than one provider", gp));
- g_media_changed(pp, flag);
- }
+ if (gp == NULL)
+ return;
+ pp = LIST_FIRST(&gp->provider);
+ if (pp != NULL) {
+ KASSERT(LIST_NEXT(pp, provider) == NULL,
+ ("geom %p has more than one provider", gp));
+ g_media_changed(pp, flag);
}
}
void
disk_media_gone(struct disk *dp, int flag)
{
- struct g_geom *gp;
+ struct g_geom *gp = dp->d_geom;
struct g_provider *pp;
- gp = dp->d_geom;
- if (gp != NULL) {
- pp = LIST_FIRST(&gp->provider);
- if (pp != NULL) {
- KASSERT(LIST_NEXT(pp, provider) == NULL,
- ("geom %p has more than one provider", gp));
- g_media_gone(pp, flag);
- }
+ if (gp == NULL)
+ return;
+ pp = LIST_FIRST(&gp->provider);
+ if (pp != NULL) {
+ KASSERT(LIST_NEXT(pp, provider) == NULL,
+ ("geom %p has more than one provider", gp));
+ g_media_gone(pp, flag);
}
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Jan 11, 8:50 PM (20 h, 55 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15757677
Default Alt Text
D35784.diff (15 KB)
Attached To
Mode
D35784: Delay GEOM disk_create() until CAM periph probe complete
Attached
Detach File
Event Timeline
Log In to Comment