summaryrefslogtreecommitdiff
path: root/usr/src/cmd/devfsadm/devalloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/devfsadm/devalloc.c')
-rw-r--r--usr/src/cmd/devfsadm/devalloc.c133
1 files changed, 112 insertions, 21 deletions
diff --git a/usr/src/cmd/devfsadm/devalloc.c b/usr/src/cmd/devfsadm/devalloc.c
index 1f0f6a8e77..11147269cb 100644
--- a/usr/src/cmd/devfsadm/devalloc.c
+++ b/usr/src/cmd/devfsadm/devalloc.c
@@ -20,12 +20,10 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* Device allocation related work.
*/
@@ -46,8 +44,9 @@
#define DEALLOCATE "/usr/sbin/deallocate"
#define MKDEVALLOC "/usr/sbin/mkdevalloc"
-static void _update_dev(deventry_t *, int, char *);
+static char *_update_dev(deventry_t *, int, const char *, char *, char *);
static int _make_db();
+extern int event_driven;
/*
@@ -167,6 +166,10 @@ _make_db()
* _update_devalloc_db
* Forms allocatable device entries to be written to device_allocate and
* device_maps.
+ *
+ * Or finds the correct entry to remove, and removes it.
+ *
+ * Note: devname is a /devices link in the REMOVE case.
*/
/* ARGSUSED */
void
@@ -175,6 +178,8 @@ _update_devalloc_db(devlist_t *devlist, int devflag, int action, char *devname,
{
int i;
deventry_t *entry = NULL, *dentry = NULL;
+ char *typestring;
+ char *nickname; /* typestring + instance */
if (action == DA_ADD) {
for (i = 0; i < DA_COUNT; i++) {
@@ -198,61 +203,147 @@ _update_devalloc_db(devlist_t *devlist, int devflag, int action, char *devname,
return;
}
if (dentry)
- _update_dev(dentry, action, NULL);
+ (void) _update_dev(dentry, action, NULL, NULL,
+ NULL);
}
} else if (action == DA_REMOVE) {
- if (devflag & DA_AUDIO)
+ if (devflag & DA_AUDIO) {
dentry = devlist->audio;
- else if (devflag & DA_CD)
+ typestring = DA_AUDIO_TYPE;
+ } else if (devflag & DA_CD) {
dentry = devlist->cd;
- else if (devflag & DA_FLOPPY)
+ typestring = DA_CD_TYPE;
+ } else if (devflag & DA_FLOPPY) {
dentry = devlist->floppy;
- else if (devflag & DA_TAPE)
+ typestring = DA_FLOPPY_TYPE;
+ } else if (devflag & DA_TAPE) {
dentry = devlist->tape;
- else if (devflag & DA_RMDISK)
+ typestring = DA_TAPE_TYPE;
+ } else if (devflag & DA_RMDISK) {
dentry = devlist->rmdisk;
- else
+ typestring = DA_RMDISK_TYPE;
+ } else
return;
+ if (event_driven) {
+ nickname = _update_dev(NULL, action, typestring, NULL,
+ devname);
+
+ if (nickname != NULL) {
+ (void) da_rm_list_entry(devlist, devname,
+ devflag, nickname);
+ free(nickname);
+ }
+ return;
+ }
+ /*
+ * Not reached as of now, could be reached if devfsadm is
+ * enhanced to clean up devalloc database more thoroughly.
+ * Will not reliably match for event-driven removes
+ */
for (entry = dentry; entry != NULL; entry = entry->next) {
if (strcmp(entry->devinfo.devname, devname) == 0)
break;
}
- _update_dev(entry, action, devname);
+ (void) _update_dev(entry, action, NULL, devname, NULL);
}
}
-static void
-_update_dev(deventry_t *dentry, int action, char *devname)
+/*
+ * _update_dev: Update device_allocate and/or device_maps files
+ *
+ * If adding a device:
+ * dentry: A linked list of allocatable devices
+ * action: DA_ADD or DA_REMOVE
+ * devtype: type of device linked list to update on removal
+ * devname: short name (i.e. rmdisk5, cdrom0) of device if known
+ * rm_link: name of real /device from hot_cleanup
+ *
+ * If the action is ADD or if the action is triggered by an event
+ * from syseventd, read the files FIRST and treat their data as
+ * more-accurate than the dentry list, adjusting dentry contents if needed.
+ *
+ * For DA_ADD, try to add each device in the list to the files.
+ *
+ * If the action is DA_REMOVE and not a hotplug remove, adjust the files
+ * as indicated by the linked list.
+ *
+ * RETURNS:
+ * If we successfully remove a device from the files, returns
+ * a char * to strdup'd devname of the device removed.
+ *
+ * The caller is responsible for freeing the return value.
+ *
+ * NULL for all other cases, both success and failure.
+ *
+ */
+static char *
+_update_dev(deventry_t *dentry, int action, const char *devtype, char *devname,
+ char *rm_link)
{
da_args dargs;
deventry_t newentry, *entry;
+ int status;
dargs.rootdir = NULL;
dargs.devnames = NULL;
+ if (event_driven)
+ dargs.optflag = DA_EVENT;
+ else
+ dargs.optflag = 0;
+
if (action == DA_ADD) {
- dargs.optflag = DA_ADD | DA_FORCE;
+ dargs.optflag |= DA_ADD;
+ /*
+ * Add Events do not have enough information to overrride the
+ * existing file contents.
+ */
+
for (entry = dentry; entry != NULL; entry = entry->next) {
dargs.devinfo = &(entry->devinfo);
(void) da_update_device(&dargs);
}
} else if (action == DA_REMOVE) {
- dargs.optflag = DA_REMOVE;
+ dargs.optflag |= DA_REMOVE;
if (dentry) {
entry = dentry;
+ } else if (dargs.optflag & DA_EVENT) {
+ if (devname == NULL)
+ newentry.devinfo.devname = NULL;
+ else
+ newentry.devinfo.devname = strdup(devname);
+ newentry.devinfo.devtype = (char *)devtype;
+ newentry.devinfo.devauths =
+ newentry.devinfo.devopts =
+ newentry.devinfo.devexec = NULL;
+ newentry.devinfo.devlist = strdup(rm_link);
+ newentry.devinfo.instance = 0;
+ newentry.next = NULL;
+ entry = &newentry;
} else {
newentry.devinfo.devname = strdup(devname);
- newentry.devinfo.devtype =
+ newentry.devinfo.devtype = (char *)devtype;
newentry.devinfo.devauths =
- newentry.devinfo.devexec =
- newentry.devinfo.devopts =
- newentry.devinfo.devlist = NULL;
+ newentry.devinfo.devexec =
+ newentry.devinfo.devopts =
+ newentry.devinfo.devlist = NULL;
newentry.devinfo.instance = 0;
newentry.next = NULL;
entry = &newentry;
}
dargs.devinfo = &(entry->devinfo);
- (void) da_update_device(&dargs);
+ /*
+ * da_update_device will fill in entry devname if
+ * event_driven is true and device is in the file
+ */
+ status = da_update_device(&dargs);
+ if (event_driven)
+ if (newentry.devinfo.devlist != NULL)
+ free(newentry.devinfo.devlist);
+ if (status == 0)
+ return (dargs.devinfo->devname);
+ else free(dargs.devinfo->devname);
}
+ return (NULL);
}