diff options
author | cth <none@none> | 2007-01-25 18:03:45 -0800 |
---|---|---|
committer | cth <none@none> | 2007-01-25 18:03:45 -0800 |
commit | ff2aee480f8fc985fe6a84c8d593c7a13c7a0481 (patch) | |
tree | 0d5ff4483df33f777f33382ef13fe769fddcfe09 /usr/src/cmd/devfsadm/devfsadm.c | |
parent | e687df1a9fd8f5934440cce2177392751cffb904 (diff) | |
download | illumos-joyent-ff2aee480f8fc985fe6a84c8d593c7a13c7a0481.tar.gz |
6452574 we should improve management of the /dev/.devlink_db file
Diffstat (limited to 'usr/src/cmd/devfsadm/devfsadm.c')
-rw-r--r-- | usr/src/cmd/devfsadm/devfsadm.c | 192 |
1 files changed, 86 insertions, 106 deletions
diff --git a/usr/src/cmd/devfsadm/devfsadm.c b/usr/src/cmd/devfsadm/devfsadm.c index 1053dd8776..0cb644663b 100644 --- a/usr/src/cmd/devfsadm/devfsadm.c +++ b/usr/src/cmd/devfsadm/devfsadm.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -44,7 +44,6 @@ #include "devfsadm_impl.h" /* externs from devalloc.c */ - extern void _reset_devalloc(int); extern void _update_devalloc_db(devlist_t *, int, int, char *, char *); extern int _da_check_for_usb(char *, char *); @@ -106,11 +105,12 @@ static int inst_count = 0; static mutex_t count_lock; static cond_t cv; -/* variables for minor_fini calling system */ -static int minor_fini_timeout = MINOR_FINI_TIMEOUT_DEFAULT; +/* variables for minor_fini thread */ static mutex_t minor_fini_mutex; -static int minor_fini_thread_created = FALSE; -static int minor_fini_delay_restart = FALSE; +static int minor_fini_canceled = TRUE; +static int minor_fini_delayed = FALSE; +static cond_t minor_fini_cv; +static int minor_fini_timeout = MINOR_FINI_TIMEOUT_DEFAULT; /* single-threads /dev modification */ static sema_t dev_sema; @@ -345,20 +345,29 @@ main(int argc, char *argv[]) /* only one daemon can run at a time */ if ((pid = enter_daemon_lock()) == getpid()) { - thread_t thread; detachfromtty(); (void) cond_init(&cv, USYNC_THREAD, 0); (void) mutex_init(&count_lock, USYNC_THREAD, 0); if (thr_create(NULL, NULL, - (void *(*)(void *))instance_flush_thread, - NULL, - THR_DETACHED, - &thread) != 0) { + (void *(*)(void *))instance_flush_thread, + NULL, THR_DETACHED, NULL) != 0) { err_print(CANT_CREATE_THREAD, "daemon", strerror(errno)); devfsadm_exit(1); } + /* start the minor_fini_thread */ + (void) mutex_init(&minor_fini_mutex, USYNC_THREAD, 0); + (void) cond_init(&minor_fini_cv, USYNC_THREAD, 0); + if (thr_create(NULL, NULL, + (void *(*)(void *))minor_fini_thread, + NULL, THR_DETACHED, NULL)) { + err_print(CANT_CREATE_THREAD, "minor_fini", + strerror(errno)); + devfsadm_exit(1); + } + + /* * No need for rcm notifications when running * with an alternate root. So initialize rcm only @@ -1284,17 +1293,15 @@ sync_handler(void *cookie, char *ap, size_t asize, dci.dci_arg = NULL; lock_dev(); - devi_tree_walk(&dci, DINFOCPYALL, NULL); - - unlock_dev(CACHE_STATE); - dcp->dca_error = dci.dci_error; - startup_cache_sync_thread(); + if (dcp->dca_flags & DCA_DEVLINK_SYNC) + unlock_dev(SYNC_STATE); + else + unlock_dev(CACHE_STATE); -out: - (void) door_return((char *)dcp, sizeof (*dcp), NULL, 0); +out: (void) door_return((char *)dcp, sizeof (*dcp), NULL, 0); } static void @@ -1317,7 +1324,6 @@ lock_dev(void) invalidate_enumerate_cache(); rm_all_links_from_cache(); (void) di_devlink_close(&devlink_cache, DI_LINK_ERROR); - devlink_cache = NULL; } /* @@ -1358,28 +1364,54 @@ lock_dev(void) } } +/* + * Unlock the device. If we are processing a CACHE_STATE call, we signal a + * minor_fini_thread delayed SYNC_STATE at the end of the call. If we are + * processing a SYNC_STATE call, we cancel any minor_fini_thread SYNC_STATE + * at both the start and end of the call since we will be doing the SYNC_STATE. + */ static void unlock_dev(int flag) { + assert(flag == SYNC_STATE || flag == CACHE_STATE); + vprint(CHATTY_MID, "unlock_dev(): entered\n"); + /* If we are starting a SYNC_STATE, cancel minor_fini_thread SYNC */ + if (flag == SYNC_STATE) { + (void) mutex_lock(&minor_fini_mutex); + minor_fini_canceled = TRUE; + minor_fini_delayed = FALSE; + (void) mutex_unlock(&minor_fini_mutex); + } + if (build_dev == FALSE) return; assert(devlink_cache); - assert(flag == SYNC_STATE || flag == CACHE_STATE); - if (flag == SYNC_STATE) { unload_modules(); if (update_database) (void) di_devlink_update(devlink_cache); (void) di_devlink_close(&devlink_cache, 0); - devlink_cache = NULL; } exit_dev_lock(); + (void) mutex_lock(&minor_fini_mutex); + if (flag == SYNC_STATE) { + /* We did a SYNC_STATE, cancel minor_fini_thread SYNC */ + minor_fini_canceled = TRUE; + minor_fini_delayed = FALSE; + } else { + /* We did a CACHE_STATE, start delayed minor_fini_thread SYNC */ + minor_fini_canceled = FALSE; + minor_fini_delayed = TRUE; + (void) cond_signal(&minor_fini_cv); + } + (void) mutex_unlock(&minor_fini_mutex); + (void) sema_post(&dev_sema); } @@ -1566,7 +1598,6 @@ event_handler(sysevent_t *ev) } unlock_dev(CACHE_STATE); - startup_cache_sync_thread(); } else if (strcmp(subclass, ESC_DEVFS_BRANCH_ADD) == 0 || strcmp(subclass, ESC_DEVFS_BRANCH_REMOVE) == 0) { @@ -1584,7 +1615,6 @@ event_handler(sysevent_t *ev) build_and_log_event(EC_DEV_BRANCH, dev_ev_subclass, path, DI_NODE_NIL); unlock_dev(CACHE_STATE); - startup_cache_sync_thread(); } else err_print(UNKNOWN_EVENT, subclass); @@ -2255,100 +2285,50 @@ load_module(char *mname, char *cdir) } /* - * Create a thread to call minor_fini after some delay - */ -static void -startup_cache_sync_thread() -{ - vprint(INITFINI_MID, "startup_cache_sync_thread\n"); - - (void) mutex_lock(&minor_fini_mutex); - - minor_fini_delay_restart = TRUE; - - if (minor_fini_thread_created == FALSE) { - - if (thr_create(NULL, NULL, - (void *(*)(void *))call_minor_fini_thread, NULL, - THR_DETACHED, NULL)) { - err_print(CANT_CREATE_THREAD, "minor_fini", - strerror(errno)); - - (void) mutex_unlock(&minor_fini_mutex); - - /* - * just sync state here instead of - * giving up - */ - lock_dev(); - unlock_dev(SYNC_STATE); - - return; - } - minor_fini_thread_created = TRUE; - } else { - vprint(INITFINI_MID, "restarting delay\n"); - } - - (void) mutex_unlock(&minor_fini_mutex); -} - -/* - * after not receiving an event for minor_fini_timeout secs, we need - * to call the minor_fini routines + * After we have completed a CACHE_STATE, if a SYNC_STATE does not occur + * within 'timeout' secs the minor_fini_thread needs to do a SYNC_STATE + * so that we still call the minor_fini routines. */ /*ARGSUSED*/ static void -call_minor_fini_thread(void *arg) +minor_fini_thread(void *arg) { - int count = 0; + timestruc_t abstime; - (void) mutex_lock(&minor_fini_mutex); + vprint(INITFINI_MID, "minor_fini_thread starting\n"); - vprint(INITFINI_MID, "call_minor_fini_thread starting\n"); + (void) mutex_lock(&minor_fini_mutex); + for (;;) { + /* wait the gather period, or until signaled */ + abstime.tv_sec = time(NULL) + minor_fini_timeout; + abstime.tv_nsec = 0; + (void) cond_timedwait(&minor_fini_cv, + &minor_fini_mutex, &abstime); + + /* if minor_fini was canceled, go wait again */ + if (minor_fini_canceled == TRUE) + continue; - do { - minor_fini_delay_restart = FALSE; + /* if minor_fini was delayed, go wait again */ + if (minor_fini_delayed == TRUE) { + minor_fini_delayed = FALSE; + continue; + } + /* done with cancellations and delays, do the SYNC_STATE */ (void) mutex_unlock(&minor_fini_mutex); - (void) sleep(minor_fini_timeout); - (void) mutex_lock(&minor_fini_mutex); - - /* - * if minor_fini_delay_restart is still false then - * we can call minor fini routines. - * ensure that at least periodically minor_fini gets - * called satisfying link generators depending on fini - * being eventually called - */ - if ((count++ >= FORCE_CALL_MINOR_FINI) || - (minor_fini_delay_restart == FALSE)) { - vprint(INITFINI_MID, - "call_minor_fini starting (%d)\n", count); - (void) mutex_unlock(&minor_fini_mutex); - - lock_dev(); - unlock_dev(SYNC_STATE); - - vprint(INITFINI_MID, "call_minor_fini done\n"); - - /* - * hang around before exiting just in case - * minor_fini_delay_restart is set again - */ - (void) sleep(1); - count = 0; - - (void) mutex_lock(&minor_fini_mutex); - } - } while (minor_fini_delay_restart); + lock_dev(); + unlock_dev(SYNC_STATE); + vprint(INITFINI_MID, "minor_fini sync done\n"); - minor_fini_thread_created = FALSE; - (void) mutex_unlock(&minor_fini_mutex); - vprint(INITFINI_MID, "call_minor_fini_thread exiting\n"); + (void) mutex_lock(&minor_fini_mutex); + minor_fini_canceled = TRUE; + minor_fini_delayed = FALSE; + } } + /* * Attempt to initialize module, if a minor_init routine exists. Set * the active flag if the routine exists and succeeds. If it doesn't @@ -2940,7 +2920,7 @@ reset_node_permissions(di_node_t node, di_minor_t minor) * reset ownership and permissions to those specified in * minor_perm * else - * preserve exsisting/user-modified ownership and + * preserve existing/user-modified ownership and * permissions * * devfs indicates a new device by faking access time to be zero. |