summaryrefslogtreecommitdiffstats
path: root/sys/geom/geom_dev.c
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2012-07-29 11:51:48 +0000
committermav <mav@FreeBSD.org>2012-07-29 11:51:48 +0000
commit24017b5387054ebed0abcea2a144f0db7f108d51 (patch)
tree07c23269365b3097a0872aa1a4fe569caf1995e1 /sys/geom/geom_dev.c
parent6009a2eb434a1c413557b4d2bc90c32da1b6e1d4 (diff)
downloadFreeBSD-src-24017b5387054ebed0abcea2a144f0db7f108d51.zip
FreeBSD-src-24017b5387054ebed0abcea2a144f0db7f108d51.tar.gz
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; VFS -- to handle spoiling same as orphan to prevent accessing replaced media. PART class already handles spoiling alike to orphan. Reviewed by: silence on geom@ and scsi@ Tested by: avg Sponsored by: iXsystems, Inc. / PC-BSD MFC after: 2 months
Diffstat (limited to 'sys/geom/geom_dev.c')
-rw-r--r--sys/geom/geom_dev.c20
1 files changed, 16 insertions, 4 deletions
diff --git a/sys/geom/geom_dev.c b/sys/geom/geom_dev.c
index f3165a0..7936740 100644
--- a/sys/geom/geom_dev.c
+++ b/sys/geom/geom_dev.c
@@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$");
#include <sys/conf.h>
#include <sys/ctype.h>
#include <sys/bio.h>
+#include <sys/bus.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/proc.h>
@@ -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, const char *attr)
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_provider *pp, int insist __unused)
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, pp->name);
cp = g_new_consumer(gp);
error = g_attach(cp, pp);
OpenPOWER on IntegriCloud