//Called when module unloaded using 'rmmod' void cleanup_module() { print_all(); nf_unregister_hook(&nfho); //cleanup – unregister hook //TODO - cleanup hash table kfree(ts); int i; for(i = 0; i < GLOBAL_MAP_SIZE; i++){ if(global_map[i]){ struct hlist_node* n; struct hlist_node* old; hte_t* h; /* hlist_for_each(n, global_map[i]){ h = hlist_entry(h, hte_t, node); hlist_del(n); //if(h) kfree(h); //kfree(n); } */ n = global_map[i]->first; while(n){ h = hlist_entry(n,hte_t, node); old = n; n = n->next; hlist_del(old); //kfree(old); kfree(h); } kfree(global_map[i]); } } kfree(global_map); }
static unsigned uproc_dentry_equal(struct hlist_node* p, void *d1, void*d2, void*d3) { uproc_dentry_t *parent = (uproc_dentry_t*)d1; const char *name = (const char *)d2; size_t namelen = (size_t)d3; uproc_dentry_t *entry = hlist_entry(p, uproc_dentry_t, hlink); return entry->parent == parent && namelen == entry->namelen && !strncmp(name, entry->name, namelen); }
/* * search for the last part of the path which does not contain '/'. * @ret should store the parent of the path @name, otherwise * the search will start at the root. * After returned, *lp stores the start of the last part, * *ret stores the parent dir. * return -ENOENT if the path does not exist. */ static int __find_last_part(uproc_ctx_t *ctx, const char *name, uproc_dentry_t **ret, const char **lp) { const char *p, *pnext; const char *prev = name; uproc_dentry_t *parent = NULL, *entry = NULL; struct hlist_node *n; size_t namelen; parent = *ret; if (!parent || *prev == '/') parent = ctx->root; entry = parent; // skip over front '/'s while (*prev && *prev == '/') ++prev; if (prev > name) {// point @prev to the last '/' *lp = prev--; } else { *lp = prev; } for (;*prev;) { __range_strchr(prev, &p, &pnext, '/'); if (!p) { *lp = prev; break; } else if (!*pnext) { *lp = p + 1; break; } ++p; namelen = pnext - p; n = uproc_htable_find(&ctx->htable, __uproc_dentry_hash(parent, p, namelen), (void*)parent, (void*)p, (void*)namelen); if (!n) { _SET_UPROC_ERRNO(-ENOENT); return -ENOENT; } entry = hlist_entry(n, uproc_dentry_t, hlink); prev = p; parent = entry; } *ret = parent; _SET_UPROC_ERRNO(-0); return 0; }
static int __uproc_lookup(uproc_ctx_t *ctx, const char *name, uproc_dentry_t **pentry) { uproc_dentry_t *parent; struct hlist_node *n; size_t namelen; int ret = 0; const char *p; if (!name || !strlen(name)) { _SET_UPROC_ERRNO(-EINVAL); return -EINVAL; } if ((ret = __find_last_part(ctx, name, &parent, &p))) { return ret; } namelen = strlen(p); if (namelen == 0) { if (parent == ctx->root){ *pentry = ctx->root; return 0; } else { /* /xxx/yyy/ */ *pentry = parent; return 0; } } n = uproc_htable_find(&ctx->htable, __uproc_dentry_hash(parent, p, namelen), (void*)parent, (void*)p, (void*)namelen); if (!n) { _SET_UPROC_ERRNO(-ENOENT); return -ENOENT; } *pentry = hlist_entry(n, uproc_dentry_t, hlink); _SET_UPROC_ERRNO(-0); return ret; }
static unsigned uproc_dentry_hash(struct hlist_node* p) { uproc_dentry_t *entry = hlist_entry(p, uproc_dentry_t, hlink); return __uproc_dentry_hash(entry->parent, entry->name, entry->namelen); }