--- orig/dazuko_core.c +++ mod/dazuko_core.c @@ -112,6 +112,7 @@ int event; int filenamelength; /* not including terminator */ char *filename; + struct xp_timestamp should_be_ready_by; struct event_properties event_p; struct file_properties file_p; struct xp_mutex mutex; @@ -141,7 +142,6 @@ struct slot_list_container { struct slot_list *slot_list; - struct xp_mutex mutex; }; struct one_slot_state_not_condition_param @@ -171,7 +171,9 @@ static struct xp_mutex mutex_unique_count; static unsigned char access_mask_cache[NUM_EVENTS][NUM_SLOT_LISTS]; static struct xp_mutex mutex_amc; +static struct xp_rwlock lock_slot_lists; +typedef enum { DAZUKO_NO_SLOT_LOCK = 0, DAZUKO_HAVE_SLOT_LOCK } have_slot_lock_type; int dazuko_vsnprintf(char *str, size_t size, const char *format, va_list ap) { @@ -359,7 +361,7 @@ return 0; } -static void dazuko_setup_amc_cache(void) +static void dazuko_setup_amc_cache(have_slot_lock_type had_slot_lock) { int i; int j; @@ -367,6 +369,10 @@ unsigned long event; int index; + if (!had_slot_lock) +/* LOCK? */ + call_xp_read_lock(&lock_slot_lists); + /* DOWN */ call_xp_down(&mutex_amc); @@ -382,14 +388,8 @@ for (j=0 ; jstate == DAZUKO_WORKING || s->state == DAZUKO_WAITING) && xp_timestamp_in_past(&s->should_be_ready_by)) { + /* this has taken faaaaar too long so let's terminate */ + s->state = DAZUKO_FREE; + printk(KERN_ERR "dazuko: timeout for a slot\n"); + call_xp_notify(&(s->wait_daemon_waiting_until_this_slot_not_DONE)); + return 0; + } + /* make sure this is a predicted transition and there * is a daemon on this slot (unique != 0)*/ if (s->state != from_state || s->did.unique == 0) @@ -514,7 +527,7 @@ return success; } -static struct slot * _dazuko_find_slot(struct daemon_id *did, int release, struct slot_list *sl) +static struct slot * _dazuko_find_slot(struct daemon_id *did, int release, struct slot_list *sl, have_slot_lock_type had_slot_lock) { /* Find the first slot with the same given * pid number. SMP safe. Use this function @@ -531,23 +544,22 @@ return NULL; } + if (!had_slot_lock) +/* LOCK? */ + call_xp_read_lock(&lock_slot_lists); + for (i=0 ; islots[i]); -/* DOWN */ - call_xp_down(&(s->mutex)); if (did == NULL) { /* we are looking for an empty slot */ if (s->did.unique == 0 && s->did.xp_id == NULL) { - /* we release the mutex only if the - * called wanted us to */ - if (release) - call_xp_up(&(s->mutex)); - -/* UP? */ + if (!had_slot_lock) + call_xp_read_unlock(&lock_slot_lists); +/* UNLOCK? */ return s; } @@ -565,67 +577,72 @@ * in which case we will trust xp_id) */ if (did->unique < 0 || (s->did.unique == did->unique)) { - /* we release the mutex only if the - * called wanted us to */ - if (release) - call_xp_up(&(s->mutex)); - -/* UP? */ + if (!had_slot_lock) + call_xp_read_unlock(&lock_slot_lists); +/* UNLOCK? */ return s; } } - - call_xp_up(&(s->mutex)); -/* UP */ } + if (!had_slot_lock) + call_xp_read_unlock(&lock_slot_lists); +/* UNLOCK? */ + return NULL; } -static struct slot * dazuko_find_slot_and_slotlist(struct daemon_id *did, int release, struct slot_list *slist, struct slot_list **sl_result) +static struct slot * dazuko_find_slot_and_slotlist(struct daemon_id *did, int release, struct slot_list *slist, struct slot_list **sl_result, have_slot_lock_type had_slot_lock) { struct slot *s; int i; struct slot_list *sl; + if (slist == NULL) { + if (!had_slot_lock) + call_xp_read_lock(&lock_slot_lists); +/* LOCK? */ + for (i=0 ; ipid as the the @@ -773,18 +790,24 @@ /* find our slot and hold the mutex * if we find it */ -/* DOWN? */ - s = dazuko_find_slot_and_slotlist(did, 0, NULL, &sl); + if (!had_slot_lock) + call_xp_write_lock(&lock_slot_lists); + s = dazuko_find_slot_and_slotlist(did, 0, NULL, &sl, + DAZUKO_HAVE_SLOT_LOCK); if (s == NULL) { DPRINT(("dazuko: this daemon not registered [%d]\n", did->unique)); + if (!had_slot_lock) + call_xp_write_unlock(&lock_slot_lists); /* this daemon was not registered */ return 0; } /* DOWN */ + call_xp_down(&(s->mutex)); + DPRINT(("dazuko: unregister (found match [%d -> %d])\n", did->unique, s->did.unique)); @@ -807,7 +830,7 @@ if (call_xp_atomic_read(&(sl->use_count)) == 0) { sl->access_mask = 0; - dazuko_setup_amc_cache(); + dazuko_setup_amc_cache(DAZUKO_HAVE_SLOT_LOCK); dazuko_remove_all_paths(sl); /* this was the last daemon in the group */ @@ -829,6 +852,10 @@ call_xp_print("dazuko: active count error (possible bug)\n"); } + if (!had_slot_lock) + call_xp_write_unlock(&lock_slot_lists); +/* UNLOCK */ + /* slot->state has changed to FREE, notifiy appropriate queues */ /* we need to notify all slot queues because unique could be -1, * which means that it is possible that this process does not @@ -854,30 +881,29 @@ did.unique = -1; did.xp_id = call_xp_id_copy(xp_id); - ret = _dazuko_unregister_daemon(&did); + ret = _dazuko_unregister_daemon(&did, DAZUKO_NO_SLOT_LOCK); call_xp_id_free(did.xp_id); return ret; } -static inline struct slot_list* find_slot_list_from_groupname(const char *group_name) +static inline struct slot_list* find_slot_list_from_groupname(const char *group_name, have_slot_lock_type had_slot_lock) { int i; - struct slot_list *sl; + struct slot_list *sl = NULL; const char *p1; const char *p2; + if (!had_slot_lock) +/* LOCK? */ + call_xp_read_lock(&lock_slot_lists); + + for (i=0 ; iunique)); if (did == NULL || reg_name == NULL) return XP_ERROR_PERMISSION; - s = dazuko_find_slot(did, 1, NULL); +/* LOCK */ + call_xp_write_lock(&lock_slot_lists); + + s = dazuko_find_slot(did, 1, NULL, DAZUKO_HAVE_SLOT_LOCK); if (s != NULL) { /* We are already registered! */ call_xp_print("dazuko: daemon %d already assigned to slot[%d]\n", did->unique, s->id); - + call_xp_write_unlock(&lock_slot_lists); +/* UNLOCK */ return XP_ERROR_PERMISSION; } /* Find the slot_list with the matching name. */ - sl = find_slot_list_from_groupname(reg_name); + sl = find_slot_list_from_groupname(reg_name, DAZUKO_HAVE_SLOT_LOCK); - if (sl == NULL) - { + if (sl == NULL) do { /* There is no slot_list with this name. We * need to make one. */ sl = (struct slot_list *)call_xp_malloc(sizeof(struct slot_list)); - if (sl == NULL) - return XP_ERROR_FAULT; + if (sl == NULL) { + err = XP_ERROR_FAULT; + break; + } dazuko_bzero(sl, sizeof(struct slot_list)); sl->reg_name = call_xp_malloc(string_length + 1); if (sl->reg_name == NULL) { - call_xp_free(sl); - return XP_ERROR_FAULT; + err = XP_ERROR_FAULT; + break; } dazuko_bzero(sl->reg_name, string_length + 1); @@ -980,43 +1022,48 @@ /* we need to find an empty slot */ for (i=0 ; ireg_name); - call_xp_free(sl); + err = XP_ERROR_BUSY; + break; + } + } while (0); - return XP_ERROR_BUSY; + if (err) { + if (sl) { + if (sl->reg_name) + call_xp_free(sl->reg_name); + call_xp_free(sl); } + call_xp_write_unlock(&lock_slot_lists); +/* UNLOCK */ + return err; } /* find an available slot and hold the mutex * if we find one */ /* DOWN? */ - s = dazuko_find_slot(NULL, 0, sl); + s = dazuko_find_slot(NULL, 0, sl, DAZUKO_HAVE_SLOT_LOCK); - if (s == NULL) + if (s == NULL) { + call_xp_write_unlock(&lock_slot_lists); +/* UNLOCK */ return XP_ERROR_BUSY; + } + call_xp_down(&(s->mutex)); /* DOWN */ + /* We have found a slot, so increment the active * variable and the kernel module use counter. * The module counter will always reflect the @@ -1048,6 +1095,10 @@ call_xp_up(&(s->mutex)); /* UP */ + call_xp_write_unlock(&lock_slot_lists); +/* UNLOCK */ + + /* although there was a state change, we don't need to notify any queues * because a new slot is first interesting when it hits the READY state */ @@ -1064,31 +1115,17 @@ /* If a slot is returned, it will be already locked! */ - int i; struct slot *s; struct one_slot_state_not_condition_param cond_p; tryagain: /* find our slot */ - s = dazuko_find_slot(did, 1, NULL); + s = dazuko_find_slot(did, 1, NULL, DAZUKO_NO_SLOT_LOCK); if (s == NULL) { - i = dazuko_register_daemon(did, "_COMPAT", 7, 1); - if (i != 0) - { - call_xp_print("dazuko: unregistered daemon %d attempted to get access\n", did->unique); - return NULL; - } - - s = dazuko_find_slot(did, 1, NULL); - if (s == NULL) - { - call_xp_print("dazuko: unregistered daemon %d attempted to get access\n", did->unique); - return NULL; - } - - call_xp_print("dazuko: warning: daemon %d is using a deprecated protocol\n", did->unique); + call_xp_print("dazuko: unregistered daemon %d attempted to get access\n", did->unique); + return NULL; } /* the daemon is now ready to receive a file */ @@ -1154,7 +1191,7 @@ static int dazuko_initialize_cache(struct daemon_id *did, unsigned long ttl) { /* find our slot */ - if (dazuko_find_slot(did, 1, NULL) == NULL) + if (dazuko_find_slot(did, 1, NULL, DAZUKO_NO_SLOT_LOCK) == NULL) { /* this daemon is not registered! */ @@ -1547,12 +1584,15 @@ * (or that we don't register twice) */ /* find our slot */ - s = dazuko_find_slot_and_slotlist(did, 1, NULL, &sl); + call_xp_write_lock(&lock_slot_lists); + + s = dazuko_find_slot_and_slotlist(did, 1, NULL, &sl, DAZUKO_HAVE_SLOT_LOCK); switch (opt) { case REGISTER: call_xp_print("dazuko: dazuko_set_option does not support REGISTER (bug!)\n"); + call_xp_write_unlock(&lock_slot_lists); return XP_ERROR_PERMISSION; case UNREGISTER: @@ -1560,6 +1600,7 @@ { /* We are not registered! */ + call_xp_write_unlock(&lock_slot_lists); return 0; } break; @@ -1567,21 +1608,9 @@ default: if (s == NULL) { - error = dazuko_register_daemon(did, "_COMPAT", 7, 1); - if (error) - { - call_xp_print("dazuko: unregistered daemon %d attempted access\n", did->unique); - return XP_ERROR_PERMISSION; - } - - s = dazuko_find_slot_and_slotlist(did, 1, NULL, &sl); - if (s == NULL) - { - call_xp_print("dazuko: unregistered daemon %d attempted access\n", did->unique); - return XP_ERROR_PERMISSION; - } - - call_xp_print("dazuko: warning: daemon %d is using a deprecated protocol (opt=%d)\n", did->unique, opt); + call_xp_print("dazuko: unregistered daemon %d attempted access\n", did->unique); + call_xp_write_unlock(&lock_slot_lists); + return XP_ERROR_PERMISSION; } break; } @@ -1590,14 +1619,14 @@ switch (opt) { case UNREGISTER: - error = _dazuko_unregister_daemon(did); + error = _dazuko_unregister_daemon(did, DAZUKO_HAVE_SLOT_LOCK); break; case SET_ACCESS_MASK: sl->access_mask = (char)dazuko_strtoul((char *)param); /* rebuild access_mask_cache */ - dazuko_setup_amc_cache(); + dazuko_setup_amc_cache(DAZUKO_HAVE_SLOT_LOCK); break; case ADD_INCLUDE_PATH: @@ -1627,6 +1656,7 @@ break; } + call_xp_write_unlock(&lock_slot_lists); return error; } @@ -1676,6 +1706,7 @@ struct get_ready_slot_condition_param cond_p1; struct two_slot_state_not_condition_param cond_p2; + begin: /* we initialize the slot value because * we cannot guarentee that it will be @@ -1686,6 +1717,7 @@ /* wait for a slot to become ready */ cond_p1.slotlist = sl; cond_p1.slot = s; + if (call_xp_wait_until_condition(&(sl->wait_kernel_waiting_for_any_READY_slot_or_zero_use_count), get_ready_slot_condition, &cond_p1, 0) != 0) { /* The kernel process was killed while @@ -1714,6 +1746,7 @@ /* DOWN */ + /* the slot is already locked at this point */ /* grab the daemon's unique */ @@ -1728,6 +1761,7 @@ s->event = event; s->response = prev_response; s->filenamelength = filenamelength; + xp_timestamp_seconds_from_now(60, &s->should_be_ready_by); /* An arbitrary minute */ if (event_p == NULL) dazuko_bzero(&(s->event_p), sizeof(struct event_properties)); @@ -1766,7 +1800,6 @@ /* slot->state has changed to FREE, notifiy appropriate queue */ call_xp_notify(&(s->wait_daemon_waiting_until_this_slot_not_DONE)); - return -1; /* user interrupted */ } @@ -1837,6 +1870,8 @@ kfs->aliases = (struct dazuko_file_listnode *)xp_malloc(sizeof(struct dazuko_file_listnode)); if (kfs->aliases == NULL) { + call_xp_read_unlock(&(slist->lock_lists)); +/* UNLOCK */ call_xp_print("dazuko: warning: access not controlled (%s)\n", kfs->filename); return 0; } @@ -1913,24 +1948,6 @@ return selected; } -static inline int dazuko_should_scan(struct dazuko_file_struct *kfs, struct slot_list *slist) -{ - /* Check if we are supposed to scan this file. - * This checks for all the correct file types, - * permissions, and if it is within the desired - * paths to scan. */ - - int result = 0; - - /* make necessary platform-dependent checks */ - if (call_xp_fill_file_struct(kfs) == 0) - { - if (dazuko_is_selected(kfs, slist)) - result = 1; - } - - return result; -} static inline int dazuko_run_daemon(unsigned long event, struct dazuko_file_struct *dfs, struct event_properties *event_p, struct slot_list *skip_slotlist) { @@ -2045,18 +2062,12 @@ for (i=0 ; ilock_trusted_list)); @@ -2234,7 +2247,7 @@ if (xp_id == NULL || group_name == NULL || token == NULL) return -1; - sl = find_slot_list_from_groupname(group_name); + sl = find_slot_list_from_groupname(group_name, DAZUKO_NO_SLOT_LOCK); if (sl == NULL) return -1; @@ -2280,16 +2293,13 @@ int i; struct slot_list *sl; +/* LOCK */ + call_xp_write_lock(&lock_slot_lists); + for (i=0 ; iaccess_mask = k_param[0]; /* rebuild access_mask_cache */ - dazuko_setup_amc_cache(); + dazuko_setup_amc_cache(DAZUKO_NO_SLOT_LOCK); } break; @@ -3444,19 +3458,16 @@ int dazuko_init(void) { - int i; int error; call_xp_init_mutex(&mutex_unique_count); call_xp_init_mutex(&mutex_amc); + call_xp_init_rwlock(&lock_slot_lists); dazuko_bzero(&slot_lists, sizeof(slot_lists)); memset(&access_mask_cache, AMC_UNSET, sizeof(access_mask_cache)); - for (i=0 ; i #endif +#include + #else #ifdef DEVFS_SUPPORT @@ -253,21 +255,17 @@ inline void xp_init_mutex(struct xp_mutex *mutex) { - #ifdef init_MUTEX - init_MUTEX(&(mutex->mutex)); - #else - sema_init(&(mutex->mutex), 1); - #endif + mutex->spinlock = SPIN_LOCK_UNLOCKED; } inline void xp_down(struct xp_mutex *mutex) { - down(&(mutex->mutex)); + spin_lock_irqsave(&mutex->spinlock, mutex->flags); } inline void xp_up(struct xp_mutex *mutex) { - up(&(mutex->mutex)); + spin_unlock_irqrestore(&mutex->spinlock, mutex->flags); } inline void xp_destroy_mutex(struct xp_mutex *mutex) @@ -1924,7 +1922,7 @@ } #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,20) { - #ifdef __SMP__ + #if defined(__SMP__) || defined(CONFIG_SMP) lock_kernel(); #endif filename = getname((char *) regs.ebx); @@ -1939,14 +1937,14 @@ current->ptrace &= ~PT_DTRACE; putname(filename); out: - #ifdef __SMP__ + #if defined(__SMP__) || defined(CONFIG_SMP) unlock_kernel(); #endif return error; } #else { - #ifdef __SMP__ + #if defined(__SMP__) || defined(CONFIG_SMP) lock_kernel(); #endif filename = getname((char *) regs.ebx); @@ -1961,7 +1959,7 @@ current->flags &= ~PF_DTRACE; putname(filename); out: - #ifdef __SMP__ + #if defined(__SMP__) || defined(CONFIG_SMP) unlock_kernel(); #endif return error; @@ -2270,7 +2268,7 @@ dazuko_unlock_current(); /* do a file syncronization on all devices (IMPORTANT!) and replace system calls */ - #ifdef __SMP__ + #if defined(__SMP__) || defined(CONFIG_SMP) lock_kernel(); #endif @@ -2333,7 +2331,7 @@ } #endif - #ifdef __SMP__ + #if defined(__SMP__) || defined(CONFIG_SMP) unlock_kernel(); #endif /* done syncing and replacing */ @@ -2363,7 +2361,7 @@ int error; /* do a file syncronization on all devices (IMPORTANT!) and replace system calls */ - #ifdef __SMP__ + #if defined(__SMP__) || defined(CONFIG_SMP) lock_kernel(); #endif @@ -2415,7 +2413,7 @@ } #endif - #ifdef __SMP__ + #if defined(__SMP__) || defined(CONFIG_SMP) unlock_kernel(); #endif /* done syncing and replacing */ @@ -2669,6 +2667,18 @@ dazuko_exit(); } +int xp_timestamp_in_past(struct xp_timestamp *time) +{ + return time ? time_after(jiffies, time->timestamp) : 0; +} + +void xp_timestamp_seconds_from_now(int seconds, struct xp_timestamp *time) +{ + if (time) + time->timestamp = jiffies + seconds * HZ; +} + + #ifdef MODULE --- orig/dazuko_linux.h +++ mod/dazuko_linux.h @@ -92,7 +92,8 @@ struct xp_mutex { - struct semaphore mutex; + spinlock_t spinlock; + unsigned long flags; }; struct xp_atomic @@ -133,4 +134,9 @@ rwlock_t rwlock; }; +struct xp_timestamp +{ + unsigned long timestamp; +}; + #endif