diff options
Diffstat (limited to 'usr/src/cmd/devfsadm/devalloc.c')
-rw-r--r-- | usr/src/cmd/devfsadm/devalloc.c | 133 |
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); } |