Page MenuHomeFreeBSD

D16735.id46920.diff
No OneTemporary

D16735.id46920.diff

Index: lib/libdevctl/devctl.h
===================================================================
--- lib/libdevctl/devctl.h
+++ lib/libdevctl/devctl.h
@@ -41,5 +41,7 @@
int devctl_clear_driver(const char *device, bool force);
int devctl_rescan(const char *device);
int devctl_delete(const char *device, bool force);
+int devctl_freeze(void);
+int devctl_thaw(void);
#endif /* !__DEVCTL_H__ */
Index: lib/libdevctl/devctl.3
===================================================================
--- lib/libdevctl/devctl.3
+++ lib/libdevctl/devctl.3
@@ -36,10 +36,12 @@
.Nm devctl_detach ,
.Nm devctl_disable ,
.Nm devctl_enable ,
+.Nm devctl_freeze ,
.Nm devctl_rescan ,
.Nm devctl_resume ,
.Nm devctl_set_driver ,
-.Nm devctl_suspend
+.Nm devctl_suspend ,
+.Nm devctl_thaw
.Nd device control library
.Sh LIBRARY
.Lb libdevctl
@@ -58,6 +60,8 @@
.Ft int
.Fn devctl_enable "const char *device"
.Ft int
+.Fn devctl_freeze "void"
+.Ft int
.Fn devctl_rescan "const char *device"
.Ft int
.Fn devctl_resume "const char *device"
@@ -65,6 +69,8 @@
.Fn devctl_set_driver "const char *device" "const char *driver" "bool force"
.Ft int
.Fn devctl_suspend "const char *device"
+.Ft int
+.Fn devctl_thaw "void"
.Sh DESCRIPTION
The
.Nm
@@ -189,6 +195,16 @@
.Fn devctl_rescan
function rescans a bus device checking for devices that have been added or
removed.
+.Pp
+The
+.Fn devctl_freeze
+function freezes probe and attach processing initiated in response to
+drivers being loaded.
+.Pp
+The
+.Fn devctl_thaw
+function resumes (thaws the freeze) probe and attach processing
+initiated in response to drivers being loaded.
.Sh RETURN VALUES
.Rv -std devctl_attach devctl_clear_driver devctl_delete devctl_detach \
devctl_disable devctl_enable devctl_suspend devctl_rescan devctl_resume \
Index: lib/libdevctl/devctl.c
===================================================================
--- lib/libdevctl/devctl.c
+++ lib/libdevctl/devctl.c
@@ -145,3 +145,17 @@
return (devctl_simple_request(DEV_DELETE, device, force ?
DEVF_FORCE_DELETE : 0));
}
+
+int
+devctl_freeze(void)
+{
+
+ return (devctl_simple_request(DEV_FREEZE, "", 0));
+}
+
+int
+devctl_thaw(void)
+{
+
+ return (devctl_simple_request(DEV_THAW, "", 0));
+}
Index: sbin/devmatch/devmatch.c
===================================================================
--- sbin/devmatch/devmatch.c
+++ sbin/devmatch/devmatch.c
@@ -56,12 +56,6 @@
#define DEVMATCH_MAX_HITS 256
-static struct match_data {
- char *descr;
- int priority;
-} match_data[DEVMATCH_MAX_HITS];
-
-static int hit_index;
static int all_flag;
static int dump_flag;
static char *linker_hints;
@@ -71,6 +65,7 @@
static void *hints;
static void *hints_end;
+static struct devinfo_dev *root;
static void *
read_hints(const char *fn, size_t *len)
@@ -240,35 +235,6 @@
return retval;
}
-static int
-match_data_compare(const void *_pa, const void *_pb)
-{
- const struct match_data *pa = _pa;
- const struct match_data *pb = _pb;
-
- /* biggest value first */
- if (pa->priority > pb->priority)
- return (-1);
- else if (pa->priority < pb->priority)
- return (1);
-
- /* then sort by string */
- return (strcmp(pa->descr, pb->descr));
-}
-
-static int
-bitrev16(int input)
-{
- int retval = 0;
- int x;
-
- for (x = 0; x != 16; x++) {
- if ((input >> x) & 1)
- retval |= (0x8000 >> x);
- }
- return (retval);
-}
-
static void
search_hints(const char *bus, const char *dev, const char *pnpinfo)
{
@@ -417,22 +383,12 @@
printf("\n");
else if (!notme) {
if (!unbound_flag) {
- char *descr = NULL;
-
if (all_flag)
- asprintf(&descr, "%s: %s", *dev ? dev : "unattached", lastmod);
+ printf("%s: %s", *dev ? dev : "unattached", lastmod);
else
- asprintf(&descr, "%s", lastmod);
+ printf("%s", lastmod);
if (verbose_flag)
printf("Matches --- %s ---\n", lastmod);
-
- if (descr != NULL && hit_index < DEVMATCH_MAX_HITS) {
- match_data[hit_index].descr = descr;
- match_data[hit_index].priority = bitrev16(mask);
- hit_index++;
- } else {
- free(descr);
- }
}
found++;
}
@@ -445,19 +401,6 @@
}
walker = (void *)(len - sizeof(int) + (intptr_t)walker);
}
- if (hit_index != 0) {
- /* sort hits by priority */
- mergesort(match_data, hit_index, sizeof(match_data[0]), &match_data_compare);
-
- /* printout */
- for (i = 0; i != hit_index; i++) {
- puts(match_data[i].descr);
- free(match_data[i].descr);
- }
-
- /* reset hit_index */
- hit_index = 0;
- }
if (unbound_flag && found == 0 && *pnpinfo) {
if (verbose_flag)
printf("------------------------- ");
@@ -480,6 +423,8 @@
break;
if (!(dev->dd_flags & DF_ENABLED))
break;
+ if (dev->dd_flags & DF_ATTACHED_ONCE)
+ break;
parent = devinfo_handle_to_device(dev->dd_parent);
bus = strdup(parent->dd_name);
p = bus + strlen(bus) - 1;
@@ -496,10 +441,50 @@
return (devinfo_foreach_device_child(dev, find_unmatched, arg));
}
+struct exact_info
+{
+ const char *bus;
+ const char *loc;
+ struct devinfo_dev *dev;
+};
+
+/*
+ * Look for the exact location specified by the nomatch event. The
+ * loc and pnpinfo run together to get the string we're looking for,
+ * so we have to synthesize the same thing that subr_bus.c is
+ * generating in devnomatch/devaddq to do the string comparison.
+ */
+static int
+find_exact_dev(struct devinfo_dev *dev, void *arg)
+{
+ struct devinfo_dev *parent;
+ char *loc;
+ struct exact_info *info;
+
+ info = arg;
+ do {
+ if (info->dev != NULL)
+ break;
+ if (!(dev->dd_flags & DF_ENABLED))
+ break;
+ parent = devinfo_handle_to_device(dev->dd_parent);
+ if (strcmp(info->bus, parent->dd_name) != 0)
+ break;
+ asprintf(&loc, "%s %s", parent->dd_pnpinfo,
+ parent->dd_location);
+ if (strcmp(loc, info->loc) == 0)
+ info->dev = dev;
+ free(loc);
+ } while (0);
+
+ return (devinfo_foreach_device_child(dev, find_exact_dev, arg));
+}
+
static void
find_nomatch(char *nomatch)
{
- char *bus, *pnpinfo, *tmp;
+ char *bus, *pnpinfo, *tmp, *busnameunit;
+ struct exact_info info;
/*
* Find our bus name. It will include the unit number. We have to search
@@ -515,6 +500,9 @@
errx(1, "No bus found in nomatch string: '%s'", nomatch);
bus = tmp + 4;
*tmp = '\0';
+ busnameunit = strdup(bus);
+ if (busnameunit == NULL)
+ errx(1, "Can't allocate memory for strings");
tmp = bus + strlen(bus) - 1;
while (tmp > bus && isdigit(*tmp))
tmp--;
@@ -531,6 +519,17 @@
errx(1, "Malformed NOMATCH string: '%s'", nomatch);
pnpinfo = nomatch + 4;
+ /*
+ * See if we can find the devinfo_dev for this device. If we
+ * can, and it's been attached before, we should filter it out
+ * so that a kldunload foo doesn't cause an immediate reload.
+ */
+ info.loc = pnpinfo;
+ info.bus = busnameunit;
+ info.dev = NULL;
+ devinfo_foreach_device_child(root, find_exact_dev, (void *)&info);
+ if (info.dev != NULL && info.dev->dd_flags & DF_ATTACHED_ONCE)
+ exit(0);
search_hints(bus, "", pnpinfo);
exit(0);
@@ -546,7 +545,6 @@
int
main(int argc, char **argv)
{
- struct devinfo_dev *root;
int ch;
while ((ch = getopt_long(argc, argv, "adh:p:uv",
@@ -586,12 +584,13 @@
exit(0);
}
- if (nomatch_str != NULL)
- find_nomatch(nomatch_str);
if (devinfo_init())
err(1, "devinfo_init");
if ((root = devinfo_handle_to_device(DEVINFO_ROOT_DEVICE)) == NULL)
errx(1, "can't find root device");
- devinfo_foreach_device_child(root, find_unmatched, (void *)0);
+ if (nomatch_str != NULL)
+ find_nomatch(nomatch_str);
+ else
+ devinfo_foreach_device_child(root, find_unmatched, (void *)0);
devinfo_free();
}
Index: sbin/init/rc.conf
===================================================================
--- sbin/init/rc.conf
+++ sbin/init/rc.conf
@@ -42,6 +42,7 @@
devd_enable="YES" # Run devd, to trigger programs on device tree changes.
devd_flags="" # Additional flags for devd(8).
devmatch_enable="YES" # Demand load kernel modules based on device ids.
+devmatch_blacklist="" # List of modules (w/o .ko) to exclude from devmatch.
#kld_list="" # Kernel modules to load after local disks are mounted
kldxref_enable="YES" # Build linker.hints files with kldxref(8).
kldxref_clobber="NO" # Overwrite old linker.hints at boot.
Index: sbin/init/rc.d/devmatch
===================================================================
--- sbin/init/rc.d/devmatch
+++ sbin/init/rc.d/devmatch
@@ -41,15 +41,15 @@
devmatch_start()
{
- local x
+ local x m list
if [ -n "$one_nomatch" ]; then
- x=$(devmatch -p "${one_nomatch}")
+ list=$(devmatch -p "${one_nomatch}" | sort -u)
else
- x=$(devmatch)
+ list=$(devmatch | sort -u)
fi
- [ -n "$x" ] || return
+ [ -n "$list" ] || return
# While kldload can accept multiple modules
# on the line at once, we loop here in case
@@ -57,10 +57,18 @@
# We also optimize against the false positives
# or drivers that have symbolic links that
# confuse devmatch by running it -n.
- for m in ${x}; do
+ # Finally, we filter out all items in the
+ # devmactch_blacklist.
+ devctl freeze
+ x=$(echo ${devmatch_blacklist} | tr ' ' '#')
+ for m in ${list}; do
+ case "#${x}#" in
+ *"#${m}#"*) continue ;;
+ esac
echo "Autoloading module: ${m}"
kldload -n ${m}
done
+ devctl thaw
}
load_rc_config $name
Index: sys/kern/subr_bus.c
===================================================================
--- sys/kern/subr_bus.c
+++ sys/kern/subr_bus.c
@@ -82,6 +82,8 @@
kobj_class_t driver;
TAILQ_ENTRY(driverlink) link; /* list of drivers in devclass */
int pass;
+ int flags;
+#define DL_DEFERRED_PROBE 1 /* Probe deferred on this */
TAILQ_ENTRY(driverlink) passlink;
};
@@ -101,6 +103,7 @@
int maxunit; /* size of devices array */
int flags;
#define DC_HAS_CHILDREN 1
+#define DC_DEFERRED_PROBE 2 /* Driver loaded during freeze */
struct sysctl_ctx_list sysctl_ctx;
struct sysctl_oid *sysctl_tree;
@@ -152,6 +155,7 @@
EVENTHANDLER_LIST_DEFINE(dev_lookup);
static void devctl2_init(void);
+static bool device_frozen;
#define DRIVERNAME(d) ((d)? d->name : "no driver")
#define DEVCLANAME(d) ((d)? d->name : "no devclass")
@@ -1168,7 +1172,12 @@
dl->pass = pass;
driver_register_pass(dl);
- devclass_driver_added(dc, driver);
+ if (device_frozen) {
+ dc->flags |= DC_DEFERRED_PROBE;
+ dl->flags |= DL_DEFERRED_PROBE;
+ } else {
+ devclass_driver_added(dc, driver);
+ }
bus_data_generation_update();
return (0);
}
@@ -1208,6 +1217,9 @@
* Note that since a driver can be in multiple devclasses, we
* should not detach devices which are not children of devices in
* the affected devclass.
+ *
+ * If we're frozen, we don't generate NOMATCH events. We assume
+ * something later will scan them.
*/
for (i = 0; i < dc->maxunit; i++) {
if (dc->devices[i]) {
@@ -1216,9 +1228,13 @@
dev->parent->devclass == busclass) {
if ((error = device_detach(dev)) != 0)
return (error);
- BUS_PROBE_NOMATCH(dev->parent, dev);
- devnomatch(dev);
- dev->flags |= DF_DONENOMATCH;
+ if (device_frozen) {
+ dev->flags &= ~DF_DONENOMATCH;
+ } else {
+ BUS_PROBE_NOMATCH(dev->parent, dev);
+ devnomatch(dev);
+ dev->flags |= DF_DONENOMATCH;
+ }
}
}
}
@@ -2935,6 +2951,7 @@
dev->state = DS_NOTPRESENT;
return (error);
}
+ dev->flags |= DF_ATTACHED_ONCE;
attachtime = get_cyclecount() - attachtime;
/*
* 4 bits per device is a reasonable value for desktop and server
@@ -5406,6 +5423,26 @@
return (false);
}
+static void
+device_do_deferred_probes(void)
+{
+ devclass_t dc;
+ driverlink_t dl;
+
+ TAILQ_FOREACH(dc, &devclasses, link) {
+ if ((dc->flags & DC_DEFERRED_PROBE) == 0)
+ continue;
+ TAILQ_FOREACH(dl, &dc->drivers, link) {
+ if ((dl->flags & DL_DEFERRED_PROBE) == 0)
+ continue;
+ devclass_driver_added(dc, dl->driver);
+ dl->flags &= ~DL_DEFERRED_PROBE;
+ }
+ dc->flags &= ~DC_DEFERRED_PROBE;
+ }
+ bus_data_generation_update();
+}
+
static int
devctl2_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag,
struct thread *td)
@@ -5432,6 +5469,10 @@
if (error == 0)
error = find_device(req, &dev);
break;
+ case DEV_FREEZE:
+ case DEV_THAW:
+ error = priv_check(td, PRIV_DRIVER);
+ break;
default:
error = ENOTTY;
break;
@@ -5635,6 +5676,24 @@
error = device_delete_child(parent, dev);
break;
}
+ case DEV_FREEZE:
+ printf("Freeze: %d -- ", device_frozen);
+ if (device_frozen)
+ error = EBUSY;
+ else
+ device_frozen = true;
+ printf("%d (%d)\n", device_frozen, error);
+ break;
+ case DEV_THAW:
+ printf("Thaw: %d -- ", device_frozen);
+ if (!device_frozen)
+ error = EBUSY;
+ else {
+ device_do_deferred_probes();
+ device_frozen = false;
+ }
+ printf("%d (%d)\n", device_frozen, error);
+ break;
}
mtx_unlock(&Giant);
return (error);
Index: sys/sys/bus.h
===================================================================
--- sys/sys/bus.h
+++ sys/sys/bus.h
@@ -92,7 +92,8 @@
#define DF_EXTERNALSOFTC 0x40 /* softc not allocated by us */
#define DF_REBID 0x80 /* Can rebid after attach */
#define DF_SUSPENDED 0x100 /* Device is suspended. */
-#define DF_QUIET_CHILDREN 0x200 /* Default to quiet for all my children */
+#define DF_QUIET_CHILDREN 0x200 /* Default to quiet for all my children */
+#define DF_ATTACHED_ONCE 0x400 /* Has been attached at least once */
/**
* @brief Device request structure used for ioctl's.
@@ -126,6 +127,8 @@
#define DEV_CLEAR_DRIVER _IOW('D', 8, struct devreq)
#define DEV_RESCAN _IOW('D', 9, struct devreq)
#define DEV_DELETE _IOW('D', 10, struct devreq)
+#define DEV_FREEZE _IOW('D', 11, struct devreq)
+#define DEV_THAW _IOW('D', 12, struct devreq)
/* Flags for DEV_DETACH and DEV_DISABLE. */
#define DEVF_FORCE_DETACH 0x0000001
Index: usr.sbin/devctl/devctl.c
===================================================================
--- usr.sbin/devctl/devctl.c
+++ usr.sbin/devctl/devctl.c
@@ -71,17 +71,19 @@
static void
usage(void)
{
- fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
- "usage: devctl attach device",
- " devctl detach [-f] device",
- " devctl disable [-f] device",
- " devctl enable device",
- " devctl suspend device",
- " devctl resume device",
- " devctl set driver [-f] device driver",
- " devctl clear driver [-f] device",
- " devctl rescan device",
- " devctl delete [-f] device");
+ fprintf(stderr,
+ "usage: devctl attach device\n"
+ " devctl detach [-f] device\n"
+ " devctl disable [-f] device\n"
+ " devctl enable device\n"
+ " devctl suspend device\n"
+ " devctl resume device\n"
+ " devctl set driver [-f] device driver\n"
+ " devctl clear driver [-f] device\n"
+ " devctl rescan device\n"
+ " devctl delete [-f] device\n"
+ " devctl freeze\n"
+ " devctl thaw\n");
exit(1);
}
@@ -343,6 +345,46 @@
}
DEVCTL_COMMAND(top, delete, delete);
+static void
+freeze_usage(void)
+{
+
+ fprintf(stderr, "usage: devctl freeze\n");
+ exit(1);
+}
+
+static int
+freeze(int ac, char **av __unused)
+{
+
+ if (ac != 1)
+ freeze_usage();
+ if (devctl_freeze() < 0)
+ err(1, "Failed to freeze probe/attach");
+ return (0);
+}
+DEVCTL_COMMAND(top, freeze, freeze);
+
+static void
+thaw_usage(void)
+{
+
+ fprintf(stderr, "usage: devctl thaw\n");
+ exit(1);
+}
+
+static int
+thaw(int ac, char **av __unused)
+{
+
+ if (ac != 1)
+ thaw_usage();
+ if (devctl_thaw() < 0)
+ err(1, "Failed to thaw probe/attach");
+ return (0);
+}
+DEVCTL_COMMAND(top, thaw, thaw);
+
int
main(int ac, char *av[])
{

File Metadata

Mime Type
text/plain
Expires
Tue, Oct 28, 6:15 AM (5 h, 44 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
24297168
Default Alt Text
D16735.id46920.diff (15 KB)

Event Timeline