Page MenuHomeFreeBSD

D26140.id76267.diff
No OneTemporary

D26140.id76267.diff

Index: sys/arm/ti/am335x/am335x_pmic.c
===================================================================
--- sys/arm/ti/am335x/am335x_pmic.c
+++ sys/arm/ti/am335x/am335x_pmic.c
@@ -113,7 +113,7 @@
if (int_reg.aci) {
snprintf(notify_buf, sizeof(notify_buf), "notify=0x%02x",
status_reg.acpwr);
- devctl_notify_f("ACPI", "ACAD", "power", notify_buf, M_NOWAIT);
+ devctl_notify("ACPI", "ACAD", "power", notify_buf);
}
}
Index: sys/geom/geom_dev.c
===================================================================
--- sys/geom/geom_dev.c
+++ sys/geom/geom_dev.c
@@ -213,7 +213,7 @@
sc = cp->private;
g_trace(G_T_TOPOLOGY, "g_dev_destroy(%p(%s))", cp, gp->name);
snprintf(buf, sizeof(buf), "cdev=%s", gp->name);
- devctl_notify_f("GEOM", "DEV", "DESTROY", buf, M_WAITOK);
+ devctl_notify("GEOM", "DEV", "DESTROY", buf);
if (cp->acr > 0 || cp->acw > 0 || cp->ace > 0)
g_access(cp, -cp->acr, -cp->acw, -cp->ace);
g_detach(cp);
@@ -277,13 +277,13 @@
sc = cp->private;
dev = sc->sc_dev;
snprintf(buf, sizeof(buf), "cdev=%s", dev->si_name);
- devctl_notify_f("DEVFS", "CDEV", "MEDIACHANGE", buf, M_WAITOK);
- devctl_notify_f("GEOM", "DEV", "MEDIACHANGE", buf, M_WAITOK);
+ devctl_notify("DEVFS", "CDEV", "MEDIACHANGE", buf);
+ devctl_notify("GEOM", "DEV", "MEDIACHANGE", buf);
dev = sc->sc_alias;
if (dev != NULL) {
snprintf(buf, sizeof(buf), "cdev=%s", dev->si_name);
- devctl_notify_f("DEVFS", "CDEV", "MEDIACHANGE", buf, M_WAITOK);
- devctl_notify_f("GEOM", "DEV", "MEDIACHANGE", buf, M_WAITOK);
+ devctl_notify("DEVFS", "CDEV", "MEDIACHANGE", buf);
+ devctl_notify("GEOM", "DEV", "MEDIACHANGE", buf);
}
}
@@ -308,7 +308,7 @@
char buf[SPECNAMELEN + 6];
snprintf(buf, sizeof(buf), "cdev=%s", cp->provider->name);
- devctl_notify_f("GEOM", "DEV", "SIZECHANGE", buf, M_WAITOK);
+ devctl_notify("GEOM", "DEV", "SIZECHANGE", buf);
}
struct g_provider *
@@ -379,7 +379,7 @@
g_dev_attrchanged(cp, "GEOM::physpath");
snprintf(buf, sizeof(buf), "cdev=%s", gp->name);
- devctl_notify_f("GEOM", "DEV", "CREATE", buf, M_WAITOK);
+ devctl_notify("GEOM", "DEV", "CREATE", buf);
/*
* Now add all the aliases for this drive
*/
@@ -392,7 +392,7 @@
continue;
}
snprintf(buf, sizeof(buf), "cdev=%s", gap->ga_alias);
- devctl_notify_f("GEOM", "DEV", "CREATE", buf, M_WAITOK);
+ devctl_notify("GEOM", "DEV", "CREATE", buf);
}
return (gp);
Index: sys/kern/kern_conf.c
===================================================================
--- sys/kern/kern_conf.c
+++ sys/kern/kern_conf.c
@@ -546,7 +546,7 @@
return;
memcpy(data, prefix, sizeof(prefix) - 1);
memcpy(data + sizeof(prefix) - 1, dev->si_name, namelen + 1);
- devctl_notify_f("DEVFS", "CDEV", ev, data, mflags);
+ devctl_notify("DEVFS", "CDEV", ev, data);
free(data, M_TEMP);
}
Index: sys/kern/kern_rctl.c
===================================================================
--- sys/kern/kern_rctl.c
+++ sys/kern/kern_rctl.c
@@ -591,8 +591,8 @@
p->p_pid, p->p_ucred->cr_ruid,
p->p_ucred->cr_prison->pr_prison_racct->prr_name);
sbuf_finish(&sb);
- devctl_notify_f("RCTL", "rule", "matched",
- sbuf_data(&sb), M_NOWAIT);
+ devctl_notify("RCTL", "rule", "matched",
+ sbuf_data(&sb));
sbuf_delete(&sb);
free(buf, M_RCTL);
link->rrl_exceeded = 1;
Index: sys/kern/subr_bus.c
===================================================================
--- sys/kern/subr_bus.c
+++ sys/kern/subr_bus.c
@@ -156,6 +156,8 @@
EVENTHANDLER_LIST_DEFINE(device_detach);
EVENTHANDLER_LIST_DEFINE(dev_lookup);
+static int bus_child_location_sb(device_t child, struct sbuf *sb);
+static int bus_child_pnpinfo_sb(device_t child, struct sbuf *sb);
static void devctl2_init(void);
static bool device_frozen;
@@ -392,9 +394,10 @@
.d_name = "devctl",
};
+#define DEVCTL_BUFFER (1024 - sizeof(void *))
struct dev_event_info {
- char *dei_data;
STAILQ_ENTRY(dev_event_info) dei_link;
+ char dei_data[DEVCTL_BUFFER];
};
STAILQ_HEAD(devq, dev_event_info);
@@ -409,6 +412,7 @@
struct selinfo sel;
struct devq devq;
struct sigio *sigio;
+ uma_zone_t zone;
} devsoftc;
static void filt_devctl_detach(struct knote *kn);
@@ -431,6 +435,11 @@
cv_init(&devsoftc.cv, "dev cv");
STAILQ_INIT(&devsoftc.devq);
knlist_init_mtx(&devsoftc.sel.si_note, &devsoftc.mtx);
+ if (devctl_queue_length > 0) {
+ devsoftc.zone = uma_zcreate("DEVCTL", sizeof(struct dev_event_info),
+ NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
+ uma_prealloc(devsoftc.zone, devctl_queue_length);
+ }
devctl2_init();
}
@@ -495,8 +504,7 @@
devsoftc.queued--;
mtx_unlock(&devsoftc.mtx);
rv = uiomove(n1->dei_data, strlen(n1->dei_data), uio);
- free(n1->dei_data, M_BUS);
- free(n1, M_BUS);
+ uma_zfree(devsoftc.zone, n1);
return (rv);
}
@@ -585,42 +593,51 @@
return (devsoftc.inuse == 1);
}
-/**
- * @brief Queue data to be read from the devctl device
- *
- * Generic interface to queue data to the devctl device. It is
- * assumed that @p data is properly formatted. It is further assumed
- * that @p data is allocated using the M_BUS malloc type.
- */
-static void
-devctl_queue_data_f(char *data, int flags)
+static struct dev_event_info *
+devctl_alloc_dei(void)
{
- struct dev_event_info *n1 = NULL, *n2 = NULL;
+ struct dev_event_info *dei = NULL;
- if (strlen(data) == 0)
- goto out;
+ mtx_lock(&devsoftc.mtx);
if (devctl_queue_length == 0)
goto out;
- n1 = malloc(sizeof(*n1), M_BUS, flags);
- if (n1 == NULL)
- goto out;
- n1->dei_data = data;
- mtx_lock(&devsoftc.mtx);
- if (devctl_queue_length == 0) {
- mtx_unlock(&devsoftc.mtx);
- free(n1->dei_data, M_BUS);
- free(n1, M_BUS);
- return;
- }
- /* Leave at least one spot in the queue... */
- while (devsoftc.queued > devctl_queue_length - 1) {
- n2 = STAILQ_FIRST(&devsoftc.devq);
+ if (devctl_queue_length == devsoftc.queued) {
+ dei = STAILQ_FIRST(&devsoftc.devq);
STAILQ_REMOVE_HEAD(&devsoftc.devq, dei_link);
- free(n2->dei_data, M_BUS);
- free(n2, M_BUS);
devsoftc.queued--;
+ } else {
+ /* dei can't be NULL -- we know we have at least one in the zone */
+ dei = uma_zalloc(devsoftc.zone, M_NOWAIT);
+ MPASS(dei != NULL);
}
- STAILQ_INSERT_TAIL(&devsoftc.devq, n1, dei_link);
+ *dei->dei_data = '\0';
+out:
+ mtx_unlock(&devsoftc.mtx);
+ return (dei);
+}
+
+static struct dev_event_info *
+devctl_alloc_dei_sb(struct sbuf *sb)
+{
+ struct dev_event_info *dei;
+
+ dei = devctl_alloc_dei();
+ if (dei != NULL)
+ sbuf_new(sb, dei->dei_data, sizeof(dei->dei_data), SBUF_FIXEDLEN);
+ return (dei);
+}
+
+static void
+devctl_free_dei(struct dev_event_info *dei)
+{
+ uma_zfree(devsoftc.zone, dei);
+}
+
+static void
+devctl_queue(struct dev_event_info *dei)
+{
+ mtx_lock(&devsoftc.mtx);
+ STAILQ_INSERT_TAIL(&devsoftc.devq, dei, dei_link);
devsoftc.queued++;
cv_broadcast(&devsoftc.cv);
KNOTE_LOCKED(&devsoftc.sel.si_note, 0);
@@ -628,62 +645,38 @@
selwakeup(&devsoftc.sel);
if (devsoftc.async && devsoftc.sigio != NULL)
pgsigio(&devsoftc.sigio, SIGIO, 0);
- return;
-out:
- /*
- * We have to free data on all error paths since the caller
- * assumes it will be free'd when this item is dequeued.
- */
- free(data, M_BUS);
- return;
-}
-
-static void
-devctl_queue_data(char *data)
-{
- devctl_queue_data_f(data, M_NOWAIT);
}
/**
* @brief Send a 'notification' to userland, using standard ways
*/
-void
-devctl_notify_f(const char *system, const char *subsystem, const char *type,
- const char *data, int flags)
-{
- int len = 0;
- char *msg;
-
- if (system == NULL)
- return; /* BOGUS! Must specify system. */
- if (subsystem == NULL)
- return; /* BOGUS! Must specify subsystem. */
- if (type == NULL)
- return; /* BOGUS! Must specify type. */
- len += strlen(" system=") + strlen(system);
- len += strlen(" subsystem=") + strlen(subsystem);
- len += strlen(" type=") + strlen(type);
- /* add in the data message plus newline. */
- if (data != NULL)
- len += strlen(data);
- len += 3; /* '!', '\n', and NUL */
- msg = malloc(len, M_BUS, flags);
- if (msg == NULL)
- return; /* Drop it on the floor */
- if (data != NULL)
- snprintf(msg, len, "!system=%s subsystem=%s type=%s %s\n",
- system, subsystem, type, data);
- else
- snprintf(msg, len, "!system=%s subsystem=%s type=%s\n",
- system, subsystem, type);
- devctl_queue_data_f(msg, flags);
-}
-
void
devctl_notify(const char *system, const char *subsystem, const char *type,
const char *data)
{
- devctl_notify_f(system, subsystem, type, data, M_NOWAIT);
+ struct dev_event_info *dei;
+ struct sbuf sb;
+
+ if (system == NULL || subsystem == NULL || type == NULL)
+ return;
+ dei = devctl_alloc_dei_sb(&sb);
+ if (dei == NULL)
+ return;
+ sbuf_cpy(&sb, "!system=");
+ sbuf_cat(&sb, system);
+ sbuf_cat(&sb, " subsystem=");
+ sbuf_cat(&sb, subsystem);
+ sbuf_cat(&sb, " type=");
+ sbuf_cat(&sb, type);
+ if (data != NULL) {
+ sbuf_putc(&sb, ' ');
+ sbuf_cat(&sb, data);
+ }
+ sbuf_putc(&sb, '\n');
+ if (sbuf_finish(&sb) != 0)
+ devctl_free_dei(dei); /* overflow -> drop it */
+ else
+ devctl_queue(dei);
}
/*
@@ -698,53 +691,46 @@
* object of that event, plus the plug and play info and location info
* for that event. This is likely most useful for devices, but less
* useful for other consumers of this interface. Those should use
- * the devctl_queue_data() interface instead.
+ * the devctl_notify() interface instead.
+ *
+ * Output:
+ * ${type}${what} at $(location dev) $(pnp-info dev) on $(parent dev)
*/
static void
devaddq(const char *type, const char *what, device_t dev)
{
- char *data = NULL;
- char *loc = NULL;
- char *pnp = NULL;
+ struct dev_event_info *dei;
const char *parstr;
+ struct sbuf sb;
- if (!devctl_queue_length)/* Rare race, but lost races safely discard */
+ dei = devctl_alloc_dei_sb(&sb);
+ if (dei == NULL)
return;
- data = malloc(1024, M_BUS, M_NOWAIT);
- if (data == NULL)
- goto bad;
+ sbuf_cpy(&sb, type);
+ sbuf_cat(&sb, what);
+ sbuf_cat(&sb, " at ");
- /* get the bus specific location of this device */
- loc = malloc(1024, M_BUS, M_NOWAIT);
- if (loc == NULL)
- goto bad;
- *loc = '\0';
- bus_child_location_str(dev, loc, 1024);
+ /* Add in the location */
+ bus_child_location_sb(dev, &sb);
+ sbuf_putc(&sb, ' ');
- /* Get the bus specific pnp info of this device */
- pnp = malloc(1024, M_BUS, M_NOWAIT);
- if (pnp == NULL)
- goto bad;
- *pnp = '\0';
- bus_child_pnpinfo_str(dev, pnp, 1024);
+ /* Add in pnpinfo */
+ bus_child_pnpinfo_sb(dev, &sb);
/* Get the parent of this device, or / if high enough in the tree. */
if (device_get_parent(dev) == NULL)
parstr = "."; /* Or '/' ? */
else
parstr = device_get_nameunit(device_get_parent(dev));
- /* String it all together. */
- snprintf(data, 1024, "%s%s at %s %s on %s\n", type, what, loc, pnp,
- parstr);
- free(loc, M_BUS);
- free(pnp, M_BUS);
- devctl_queue_data(data);
+ sbuf_cat(&sb, " on ");
+ sbuf_cat(&sb, parstr);
+ sbuf_putc(&sb, '\n');
+ if (sbuf_finish(&sb) != 0)
+ goto bad;
+ devctl_queue(dei);
return;
bad:
- free(pnp, M_BUS);
- free(loc, M_BUS);
- free(data, M_BUS);
- return;
+ devctl_free_dei(dei);
}
/*
@@ -786,7 +772,6 @@
static int
sysctl_devctl_queue(SYSCTL_HANDLER_ARGS)
{
- struct dev_event_info *n1;
int q, error;
q = devctl_queue_length;
@@ -795,18 +780,32 @@
return (error);
if (q < 0)
return (EINVAL);
- if (mtx_initialized(&devsoftc.mtx))
- mtx_lock(&devsoftc.mtx);
- devctl_queue_length = q;
- while (devsoftc.queued > devctl_queue_length) {
- n1 = STAILQ_FIRST(&devsoftc.devq);
- STAILQ_REMOVE_HEAD(&devsoftc.devq, dei_link);
- free(n1->dei_data, M_BUS);
- free(n1, M_BUS);
- devsoftc.queued--;
+
+ /*
+ * When set as a tunable, we've not yet initialized the mutex.
+ * It is safe to just assign to devctl_queue_length and return
+ * as we're racing no one. We'll use whatever value set in
+ * devinit.
+ */
+ if (!mtx_initialized(&devsoftc.mtx)) {
+ devctl_queue_length = q;
+ return (0);
}
- if (mtx_initialized(&devsoftc.mtx))
- mtx_unlock(&devsoftc.mtx);
+
+ /*
+ * XXX It's hard to grow or shrink the UMA zone. Only allow
+ * disabling the queue size for the moment until underlying
+ * UMA issues can be sorted out.
+ */
+ if (q != 0)
+ return (EINVAL);
+ if (q == devctl_queue_length)
+ return (0);
+ mtx_lock(&devsoftc.mtx);
+ devctl_queue_length = 0;
+ uma_zdestroy(devsoftc.zone);
+ devsoftc.zone = 0;
+ mtx_unlock(&devsoftc.mtx);
return (0);
}
@@ -4919,6 +4918,68 @@
return (BUS_CHILD_LOCATION_STR(parent, child, buf, buflen));
}
+/**
+ * @brief Wrapper function for bus_child_pnpinfo_str using sbuf
+ *
+ * A convenint wrapper frunction for bus_child_pnpinfo_str that allows
+ * us to splat that into an sbuf. It uses unholy knowledge of sbuf to
+ * accomplish this, however. It is an interim function until we can convert
+ * this interface more fully.
+ */
+/* Note: we reach inside of sbuf because it's API isn't rich enough to do this */
+#define SPACE(s) ((s)->s_size - (s)->s_len)
+#define EOB(s) ((s)->s_buf + (s)->s_len)
+
+static int
+bus_child_pnpinfo_sb(device_t dev, struct sbuf *sb)
+{
+ char *p;
+ size_t space;
+
+ if (sb->s_error != 0)
+ return (-1);
+ p = EOB(sb);
+ *p = '\0'; /* sbuf buffer isn't NUL terminated until sbuf_finish() */
+ space = SPACE(sb);
+ if (space <= 1) {
+ sb->s_error = ENOMEM;
+ return (-1);
+ }
+ bus_child_pnpinfo_str(dev, p, space);
+ sb->s_len += strlen(p);
+ return (0);
+}
+
+/**
+ * @brief Wrapper function for bus_child_pnpinfo_str using sbuf
+ *
+ * A convenint wrapper frunction for bus_child_pnpinfo_str that allows
+ * us to splat that into an sbuf. It uses unholy knowledge of sbuf to
+ * accomplish this, however. It is an interim function until we can convert
+ * this interface more fully.
+ */
+static int
+bus_child_location_sb(device_t dev, struct sbuf *sb)
+{
+ char *p;
+ size_t space;
+
+ if (sb->s_error != 0)
+ return (-1);
+ p = EOB(sb);
+ *p = '\0'; /* sbuf buffer isn't NUL terminated until sbuf_finish() */
+ space = SPACE(sb);
+ if (space <= 1) {
+ sb->s_error = ENOMEM;
+ return (-1);
+ }
+ bus_child_location_str(dev, p, space);
+ sb->s_len += strlen(p);
+ return (0);
+}
+#undef SPACE
+#undef EOB
+
/**
* @brief Wrapper function for BUS_GET_CPUS().
*
Index: sys/sys/devctl.h
===================================================================
--- sys/sys/devctl.h
+++ sys/sys/devctl.h
@@ -36,8 +36,6 @@
* hook to send the message.
*/
boolean_t devctl_process_running(void);
-void devctl_notify_f(const char *__system, const char *__subsystem,
- const char *__type, const char *__data, int __flags);
void devctl_notify(const char *__system, const char *__subsystem,
const char *__type, const char *__data);
struct sbuf;

File Metadata

Mime Type
text/plain
Expires
Sat, Nov 22, 4:54 PM (22 h, 20 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
25981453
Default Alt Text
D26140.id76267.diff (14 KB)

Event Timeline