[SSI] openssi/kernel/cluster/ssi/ipc unixnm.c,1.16,1.17
Roger Tsang <[email protected]> Sun, 08 Aug 2010 02:27:12 +0000
| Newsgroups | gmane.linux.cluster.ssic.cvs |
|---|---|
| Message-ID | <[email protected]> |
Update of /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/ipc
In directory sfp-cvsdas-3.v30.ch3.sourceforge.com:/tmp/cvs-serv3340/cluster/ssi/ipc
Modified Files:
Tag: OPENSSI-FC
unixnm.c
Log Message:
IPC (UNIX domain sockets):
- Implement lockless unixnm_svr_table list traversal. Reduce connect(), sendmsg() contention with bind(), connect(), sendmsg().
- ssi_unix_deregister() do O(1) lookup. Remove release() contention with bind() and various paths with unix_table_lock.
- unixnm_put() do O(1) lookup. Reduce release() contention with bind(), connect(), sendmsg().
- Allocate unixnm_svr_entry and unixnm_cache_entry structures from the Linux slab cache.
cluster/ssi/ipc/unixnm.c | 350 ++++++++++++++++++-------------
include/cluster/ssi/unix.h | 27 --
include/net/af_unix.h | 5
net/unix/af_unix.c | 1
Index: unixnm.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/ipc/unixnm.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -d -r1.16 -r1.17
--- unixnm.c 27 Oct 2009 03:18:29 -0000 1.16
+++ unixnm.c 8 Aug 2010 02:27:10 -0000 1.17
@@ -63,9 +63,12 @@
clusternode_t socknode;
unsigned long sockino;
+ atomic_t refcnt;
+ struct rcu_head rhead;
};
static struct list_head unixnm_svr_table[UNIX_HASH_SIZE];
-static __cacheline_aligned_in_smp DEFINE_RWLOCK(unixnm_svr_lock);
+static __cacheline_aligned_in_smp DEFINE_SPINLOCK(unixnm_svr_table_lock);
+static kmem_cache_t *unixnm_svr_entry_cachep;
/* rebuild cache */
struct unixnm_cache_entry {
@@ -74,9 +77,10 @@
struct inode *name_inode;
struct unix_address *name_addr;
};
-static struct list_head unixnm_cache_list = LIST_HEAD_INIT(unixnm_cache_list);
-static int unixnm_cache_size = 0;
+static LIST_HEAD(unixnm_cache_list);
static __cacheline_aligned_in_smp DEFINE_SPINLOCK(unixnm_cache_listlock);
+static int unixnm_cache_size = 0;
+static kmem_cache_t *unixnm_cli_entry_cachep;
struct unixnm_rebuild_entry {
int hash;
@@ -103,6 +107,7 @@
cluster_svc_t cluster_unixnm_svc;
clms_key_svc_t unixnm_key_service;
+void __unixnmsvr_put(struct unixnm_svr_entry *);
/*
* Initialization
@@ -121,11 +126,21 @@
int ctr;
for (ctr = 0; ctr < UNIX_HASH_SIZE; ++ctr)
INIT_LIST_HEAD(&unixnm_svr_table[ctr]);
+
+ unixnm_svr_entry_cachep = kmem_cache_create("unixnm_svr_entry",
+ sizeof(struct unixnm_svr_entry), 0,
+ SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|SLAB_PANIC,
+ NULL, NULL);
}
void
unixnm_init(void)
{
+ unixnm_cli_entry_cachep = kmem_cache_create("unixnm_cli_entry",
+ sizeof(struct unixnm_cache_entry), 0,
+ SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|SLAB_PANIC,
+ NULL, NULL);
+
unixnm_svr = clms_get_key_server_node(unixnm_key_service, 1);
if (this_node == unixnm_svr) {
@@ -168,30 +183,46 @@
int data_len)
{
struct unixnm_rebuild_entry *rbldent;
+ struct unixnm_svr_entry *svrent;
int ctr;
rbldent = (struct unixnm_rebuild_entry *) buffer;
- for (ctr = 0; ctr < data_len / sizeof(*rbldent); ++ctr) {
- struct unixnm_svr_entry *svrent =
- kzmalloc_nofail(sizeof(*svrent));
+#ifdef SSI_SKIP
+ /* No need to hold these mutexes because
+ * unixnmsvr_server_ready() is not yet called.
+ * See unixnmsvr_failover().
+ */
+ down(&unixnm_svr_name_lock);
+ down(&unixnm_svr_ino_lock);
+#endif
+
+ for (ctr = 0; ctr < data_len / sizeof(*rbldent); ++ctr) {
+ svrent = kmem_cache_alloc(unixnm_svr_entry_cachep,
+ GFP_KERNEL|__GFP_NOFAIL);
INIT_LIST_HEAD(&svrent->list);
if (rbldent->namelen) {
- svrent->name = kmalloc_nofail(
- sizeof(rbldent->name));
+ svrent->name_ssidev = 0;
+ svrent->name_ino = 0;
+ svrent->type = 0;
+ svrent->name = kmalloc_nofail(sizeof(rbldent->name));
memcpy(svrent->name, &rbldent->name, rbldent->namelen);
svrent->namelen = rbldent->namelen;
} else {
svrent->name_ssidev = rbldent->name_ssidev;
svrent->name_ino = rbldent->name_ino;
svrent->type = rbldent->type;
+ svrent->name = NULL;
+ svrent->namelen = 0;
}
- svrent->sockino = rbldent->sockino;
svrent->socknode = node;
+ svrent->sockino = rbldent->sockino;
+ atomic_set(&svrent->refcnt, 1);
+ INIT_RCU_HEAD(&svrent->rhead);
- write_lock(&unixnm_svr_lock);
- list_add(&svrent->list, &unixnm_svr_table[rbldent->hash]);
- write_unlock(&unixnm_svr_lock);
+ spin_lock(&unixnm_svr_table_lock);
+ list_add_rcu(&svrent->list, &unixnm_svr_table[rbldent->hash]);
+ spin_unlock(&unixnm_svr_table_lock);
++rbldent;
}
}
@@ -207,12 +238,14 @@
struct unixnm_cache_entry *cchent;
down_write(&unixnm_cache_rebuildlock);
+
*data_len = unixnm_cache_size * sizeof(*entry);
- error = -E2BIG;
- if (*data_len > buffer_len)
+ if (*data_len > buffer_len) {
+ error = -E2BIG;
goto out;
-
+ }
entry = (struct unixnm_rebuild_entry *) buffer;
+
list_for_each_entry(cchent, &unixnm_cache_list, list) {
struct inode *inode = cchent->inode;
struct sock *sk = SOCKET_I(inode)->sk;
@@ -221,10 +254,10 @@
struct unix_address *name_addr = cchent->name_addr;
memset(entry, 0, sizeof(*entry));
+
if (name_inode) {
struct dentry *dentry = unix_sk(sk)->dentry;
- if (dentry && dentry->d_inode != name_inode)
- BUG();
+ BUG_ON(dentry && dentry->d_inode != name_inode);
entry->hash = unixnmsvr_hashino(name_inode->i_ino);
entry->name_ssidev = ssidev_get_i_ssidev(name_inode);
@@ -232,8 +265,7 @@
entry->type = sk->sk_type;
} else {
struct unix_address *addr = unix_sk(sk)->addr;
- if (addr && addr != name_addr)
- BUG();
+ BUG_ON(addr && addr != name_addr);
entry->hash = name_addr->hash;
memcpy(&entry->name, name_addr->name, name_addr->len);
@@ -258,20 +290,20 @@
static inline void
unixnmsvr_nodedown(clusternode_t node)
{
+ struct unixnm_svr_entry *entry;
int hash;
- write_lock(&unixnm_svr_lock);
for (hash = 0; hash < UNIX_HASH_SIZE; ++hash) {
- struct unixnm_svr_entry *entry, *next;
- list_for_each_entry_safe(entry, next, &unixnm_svr_table[hash], list) {
- if (entry->socknode == node) {
- list_del(&entry->list);
- kfree(entry->name);
- kfree(entry);
+ rcu_read_lock();
+ list_for_each_entry_rcu(entry, &unixnm_svr_table[hash], list) {
+ if (entry->socknode == node &&
+ atomic_test_and_add(1, &entry->refcnt)) {
+ __unixnmsvr_put(entry);
+ __unixnmsvr_put(entry); /* final */
}
}
+ rcu_read_unlock();
}
- write_unlock(&unixnm_svr_lock);
}
int
@@ -295,22 +327,47 @@
* Server routines
*/
-static inline struct unixnm_svr_entry *
+void
+unixnm_svr_dealloc(struct rcu_head *rhead)
+{
+ struct unixnm_svr_entry *entry =
+ container_of(rhead, struct unixnm_svr_entry, rhead);
+ kfree(entry->name);
+ kmem_cache_free(unixnm_svr_entry_cachep, entry);
+}
+
+void
+__unixnmsvr_put(struct unixnm_svr_entry *entry)
+{
+ if (!atomic_dec_and_lock(&entry->refcnt, &unixnm_svr_table_lock))
+ return;
+ list_del_rcu(&entry->list);
+ spin_unlock(&unixnm_svr_table_lock);
+ call_rcu(&entry->rhead, unixnm_svr_dealloc);
+}
+
+
+static struct unixnm_svr_entry *
unixnmsvr_getent_byinode(
dev_t name_ssidev,
unsigned long name_ino)
{
struct unixnm_svr_entry *entry;
- list_for_each_entry(entry,
+ rcu_read_lock();
+ list_for_each_entry_rcu(entry,
&unixnm_svr_table[unixnmsvr_hashino(name_ino)], list) {
if (entry->name)
continue;
if (entry->name_ino == name_ino &&
- entry->name_ssidev == name_ssidev)
- return entry;
+ entry->name_ssidev == name_ssidev &&
+ atomic_test_and_add(1, &entry->refcnt))
+ goto found;
}
- return NULL;
+ entry = NULL;
+found:
+ rcu_read_unlock();
+ return entry;
}
int
@@ -324,72 +381,80 @@
u_long sockino)
{
struct unixnm_svr_entry *entry, *newentry;
+static DECLARE_MUTEX(unixnm_svr_ino_lock);
- *rval = -EREMOTE;
- if (this_node != unixnm_svr)
+ if (this_node != unixnm_svr) {
+ *rval = -EREMOTE;
return 0;
+ }
- *rval = -EUNM_BUG;
- if (socknode > NSC_MAX_NODE_VALUE || socknode <= 0) {
+ if (unlikely(socknode > NSC_MAX_NODE_VALUE || socknode <= 0)) {
printk(KERN_ERR "unixnmsvr_get_byinode: "
"bogus node number: %u\n", socknode);
+ *rval = -EUNM_BUG;
return 0;
}
- read_lock(&unixnm_svr_lock);
- entry = unixnmsvr_getent_byinode(name_ssidev, name_ino);
- read_unlock(&unixnm_svr_lock);
- if (entry)
- goto entry_exists_out;
-
- *rval = -ENOMEM;
- newentry = kzmalloc(sizeof(*newentry), GFP_USER);
- if (!newentry)
+ newentry = kmem_cache_alloc(unixnm_svr_entry_cachep, GFP_KERNEL);
+ if (!newentry) {
+ *rval = -ENOMEM;
return 0;
+ }
INIT_LIST_HEAD(&newentry->list);
newentry->name_ssidev = name_ssidev;
newentry->name_ino = name_ino;
newentry->type = type;
+ newentry->name = NULL;
+ newentry->namelen = 0;
newentry->socknode = socknode;
newentry->sockino = sockino;
+ atomic_set(&newentry->refcnt, 1);
+ INIT_RCU_HEAD(&newentry->rhead);
- write_lock(&unixnm_svr_lock);
+ down(&unixnm_svr_ino_lock);
entry = unixnmsvr_getent_byinode(name_ssidev, name_ino);
- if (!entry)
- list_add(&newentry->list,
+ if (!entry) {
+ spin_lock(&unixnm_svr_table_lock);
+ list_add_rcu(&newentry->list,
&unixnm_svr_table[unixnmsvr_hashino(name_ino)]);
- write_unlock(&unixnm_svr_lock);
- if (entry) {
- kfree(newentry);
- goto entry_exists_out;
+ spin_unlock(&unixnm_svr_table_lock);
+ up(&unixnm_svr_ino_lock);
+ *rval = 0;
+ return 0;
}
+ up(&unixnm_svr_ino_lock);
- *rval = 0;
- return 0;
+ __unixnmsvr_put(entry);
+ kmem_cache_free(unixnm_svr_entry_cachep, newentry);
-entry_exists_out:
*rval = -EADDRINUSE;
printk(KERN_WARNING "unixnmsvr_get_byinode: filesystem for ssidev %d "
"doesn't correctly support exclusive create\n", name_ssidev);
return 0;
}
-static inline struct unixnm_svr_entry *
+static struct unixnm_svr_entry *
unixnmsvr_getent_byname(
struct sockaddr_un *sunaddr,
int namelen,
int hash)
{
struct unixnm_svr_entry *entry;
- list_for_each_entry(entry, &unixnm_svr_table[hash], list) {
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(entry, &unixnm_svr_table[hash], list) {
if (!entry->name)
continue;
if (entry->namelen == namelen &&
- memcmp(entry->name, sunaddr, namelen) == 0)
- return entry;
+ memcmp(entry->name, sunaddr, namelen) == 0 &&
+ atomic_test_and_add(1, &entry->refcnt))
+ goto found;
}
- return NULL;
+ entry = NULL;
+found:
+ rcu_read_unlock();
+ return entry;
}
int
@@ -402,77 +467,80 @@
{
struct sockaddr_un *sunaddr = (struct sockaddr_un *) name;
struct unixnm_svr_entry *entry, *newentry;
+static DECLARE_MUTEX(unixnm_svr_name_lock);
*rval = -EREMOTE;
if (this_node != unixnm_svr)
return 0;
*rval = -EUNM_BUG;
- if (!name) {
+ if (unlikely(!name)) {
printk(KERN_ERR "unixnmsvr_get_byname: "
"NULL name pointer\n");
return 0;
}
- if (namelen < sizeof(sunaddr->sun_family)) {
+ if (unlikely(namelen < sizeof(sunaddr->sun_family))) {
printk(KERN_ERR "unixnmsvr_get_byname: "
"namelen too small: %d\n", namelen);
return 0;
}
- if (namelen > sizeof(*sunaddr)) {
+ if (unlikely(namelen > sizeof(*sunaddr))) {
printk(KERN_ERR "unixnmsvr_get_byname: "
"namelen too big: %d\n", namelen);
return 0;
}
- if (hash > UNIX_HASH_SIZE - 1) {
+ if (unlikely(hash > UNIX_HASH_SIZE - 1)) {
printk(KERN_ERR "unixnmsvr_get_byname: "
"hash too big: %d\n", hash);
return 0;
}
- if (socknode > NSC_MAX_NODE_VALUE || socknode <= 0) {
+ if (unlikely(socknode > NSC_MAX_NODE_VALUE || socknode <= 0)) {
printk(KERN_ERR "unixnmsvr_get_byname: "
"bogus node number: %u\n", socknode);
return 0;
}
- read_lock(&unixnm_svr_lock);
- entry = unixnmsvr_getent_byname(sunaddr, namelen, hash);
- read_unlock(&unixnm_svr_lock);
- if (entry)
- goto entry_exists_out;
-
*rval = -ENOMEM;
- newentry = kzmalloc(sizeof(*newentry), GFP_USER);
+
+ newentry = kmem_cache_alloc(unixnm_svr_entry_cachep, GFP_KERNEL);
if (!newentry)
return 0;
INIT_LIST_HEAD(&newentry->list);
- newentry->name = kmalloc(namelen, GFP_USER);
+ newentry->name_ssidev = 0;
+ newentry->name_ino = 0;
+ newentry->type = 0;
+
+ newentry->name = kmalloc(namelen, GFP_KERNEL);
if (!newentry->name) {
- kfree(newentry);
+ kmem_cache_free(unixnm_svr_entry_cachep, newentry);
return 0;
}
-
memcpy(newentry->name, sunaddr, namelen);
+
newentry->namelen = namelen;
newentry->socknode = socknode;
newentry->sockino = sockino;
+ atomic_set(&newentry->refcnt, 1);
+ INIT_RCU_HEAD(&newentry->rhead);
- write_lock(&unixnm_svr_lock);
+ down(&unixnm_svr_name_lock);
entry = unixnmsvr_getent_byname(sunaddr, namelen, hash);
- if (!entry)
- list_add(&newentry->list,
+ if (!entry) {
+ spin_lock(&unixnm_svr_table_lock);
+ list_add_rcu(&newentry->list,
&unixnm_svr_table[hash]);
- write_unlock(&unixnm_svr_lock);
- if (entry) {
- kfree(newentry->name);
- kfree(newentry);
- goto entry_exists_out;
+ spin_unlock(&unixnm_svr_table_lock);
+ up(&unixnm_svr_name_lock);
+ *rval = 0;
+ return 0;
}
+ up(&unixnm_svr_name_lock);
- *rval = 0;
- return 0;
+ __unixnmsvr_put(entry);
+ kfree(newentry->name);
+ kmem_cache_free(unixnm_svr_entry_cachep, newentry);
-entry_exists_out:
*rval = -EADDRINUSE;
return 0;
}
@@ -494,34 +562,34 @@
return 0;
*rval = -EUNM_BUG;
- if (!socknode) {
+ if (unlikely(!socknode)) {
printk(KERN_ERR "unixnmsvr_find_byinode: "
"NULL socknode pointer\n");
return 0;
}
- if (!sockino) {
+ if (unlikely(!sockino)) {
printk(KERN_ERR "unixnmsvr_find_byinode: "
"NULL sockino pointer\n");
return 0;
}
- read_lock(&unixnm_svr_lock);
entry = unixnmsvr_getent_byinode(name_ssidev, name_ino);
-
- *rval = -ECONNREFUSED;
- if (!entry)
+ if (!entry) {
+ *rval = -ECONNREFUSED;
goto out;
-
- *rval = -EPROTOTYPE;
- if (entry->type != type)
+ }
+ if (entry->type != type) {
+ *rval = -EPROTOTYPE;
goto out;
+ }
*rval = 0;
*socknode = entry->socknode;
*sockino = entry->sockino;
out:
- read_unlock(&unixnm_svr_lock);
+ if (entry)
+ __unixnmsvr_put(entry);
return 0;
}
@@ -541,41 +609,40 @@
return 0;
*rval = -EUNM_BUG;
- if (!socknode) {
+ if (unlikely(!socknode)) {
printk(KERN_ERR "unixnmsvr_find_byname: "
"NULL socknode pointer\n");
return 0;
}
- if (!sockino) {
+ if (unlikely(!sockino)) {
printk(KERN_ERR "unixnmsvr_find_byname: "
"NULL sockino pointer\n");
return 0;
}
- if (!name) {
+ if (unlikely(!name)) {
printk(KERN_ERR "unixnmsvr_find_byname: "
"NULL name pointer\n");
return 0;
}
- if (namelen > sizeof(*sunaddr)) {
+ if (unlikely(namelen > sizeof(*sunaddr))) {
printk(KERN_ERR "unixnmsvr_find_byname: "
"namelen too big: %d\n", hash);
return 0;
}
- if (hash > UNIX_HASH_SIZE - 1) {
+ if (unlikely(hash > UNIX_HASH_SIZE - 1)) {
printk(KERN_ERR "unixnmsvr_find_byname: "
"hash too big: %d\n", hash);
return 0;
}
- *rval = -ECONNREFUSED;
- read_lock(&unixnm_svr_lock);
entry = unixnmsvr_getent_byname(sunaddr, namelen, hash);
if (entry) {
- *rval = 0;
*socknode = entry->socknode;
*sockino = entry->sockino;
- }
- read_unlock(&unixnm_svr_lock);
+ __unixnmsvr_put(entry);
+ *rval = 0;
+ } else
+ *rval = -ECONNREFUSED;
return 0;
}
@@ -588,46 +655,43 @@
clusternode_t socknode,
u_long sockino)
{
- struct unixnm_svr_entry *tmp, *entry = NULL;
+ struct unixnm_svr_entry *entry;
*rval = -EREMOTE;
if (this_node != unixnm_svr)
return 0;
*rval = -EUNM_BUG;
- if (hash < 0 || hash > (UNIX_HASH_SIZE-1)) {
+ if (unlikely(hash < 0 || hash > (UNIX_HASH_SIZE-1))) {
printk(KERN_ERR "unixnmsvr_put: "
"bogus hash value: %d\n", hash);
return 0;
}
- if (socknode > NSC_MAX_NODE_VALUE || socknode <= 0) {
+ if (unlikely(socknode > NSC_MAX_NODE_VALUE || socknode <= 0)) {
printk(KERN_ERR "unixnmsvr_put: "
"bogus node number: %u\n", socknode);
return 0;
}
- write_lock(&unixnm_svr_lock);
- list_for_each_entry(tmp, &unixnm_svr_table[hash], list) {
- if (tmp->socknode == socknode &&
- tmp->sockino == sockino) {
- entry = tmp;
- list_del(&entry->list);
- break;
- }
+ rcu_read_lock();
+ list_for_each_entry_rcu(entry, &unixnm_svr_table[hash], list) {
+ if (entry->socknode == socknode &&
+ entry->sockino == sockino &&
+ atomic_test_and_add(1, &entry->refcnt))
+ goto found;
}
- write_unlock(&unixnm_svr_lock);
-
- *rval = -EUNM_BUG;
- if (!entry) {
+ entry = NULL;
+found:
+ rcu_read_unlock();
+ if (entry) {
+ __unixnmsvr_put(entry);
+ __unixnmsvr_put(entry); /* final */
+ *rval = 0;
+ } else {
printk(KERN_ERR "unixnmsvr_put: "
"entry not found for node %u and ino %ld\n",
socknode, sockino);
- return 0;
}
-
- *rval = 0;
- kfree(entry->name);
- kfree(entry);
return 0;
}
@@ -715,7 +779,7 @@
struct unixnm_cache_entry *entry;
int error, ret;
- entry = kmalloc(sizeof(*entry), GFP_USER);
+ entry = kmem_cache_alloc(unixnm_cli_entry_cachep, GFP_KERNEL);
if (!entry)
return -ENOMEM;
@@ -738,16 +802,20 @@
entry->inode = inode;
entry->name_inode = name_inode;
entry->name_addr = NULL;
+
spin_lock(&unixnm_cache_listlock);
++unixnm_cache_size;
list_add(&entry->list, &unixnm_cache_list);
spin_unlock(&unixnm_cache_listlock);
+
+ unix_sk(sock->sk)->ssi_unixnm_entry = (void *)entry;
entry = NULL;
unlock_out:
up_read(&unixnm_cache_rebuildlock);
rpc_out:
- kfree(entry);
+ if (entry)
+ kmem_cache_free(unixnm_cli_entry_cachep, entry);
return error;
}
@@ -764,7 +832,7 @@
struct unixnm_cache_entry *entry;
int error, ret;
- entry = kmalloc(sizeof(*entry), GFP_USER);
+ entry = kmem_cache_alloc(unixnm_cli_entry_cachep, GFP_KERNEL);
if (!entry)
return -ENOMEM;
@@ -791,12 +859,15 @@
++unixnm_cache_size;
list_add(&entry->list, &unixnm_cache_list);
spin_unlock(&unixnm_cache_listlock);
+
+ unix_sk(sock->sk)->ssi_unixnm_entry = (void *)entry;
entry = NULL;
unlock_out:
up_read(&unixnm_cache_rebuildlock);
rpc_out:
- kfree(entry);
+ if (entry)
+ kmem_cache_free(unixnm_cli_entry_cachep, entry);
return error;
}
@@ -874,7 +945,7 @@
struct unix_sock *options = unix_sk(sock->sk);
int hash;
- struct unixnm_cache_entry *tmp, *entry = NULL;
+ struct unixnm_cache_entry *entry;
int error, ret;
hash = options->dentry ?
@@ -882,6 +953,10 @@
options->addr->hash;
SSI_ASSERT(hash >= 0 && hash < UNIX_HASH_SIZE);
+ entry = (struct unixnm_cache_entry *) options->ssi_unixnm_entry;
+ options->ssi_unixnm_entry = NULL;
+ SSI_ASSERT(entry);
+
rpc_repeat:
down_read(&unixnm_cache_rebuildlock);
if (this_node == unixnm_svr)
@@ -899,26 +974,17 @@
}
spin_lock(&unixnm_cache_listlock);
- list_for_each_entry(tmp, &unixnm_cache_list, list) {
- if (tmp->inode == inode) {
- entry = tmp;
- break;
- }
- }
- if (!entry) {
- printk(KERN_EMERG "unixnm_put: entry missing from cache\n");
- BUG();
- }
--unixnm_cache_size;
list_del(&entry->list);
spin_unlock(&unixnm_cache_listlock);
up_read(&unixnm_cache_rebuildlock);
- kfree(entry);
+ kmem_cache_free(unixnm_cli_entry_cachep, entry);
return;
rpc_out:
BUG();
+ for (;;) ; /* no return */
}
------------------------------------------------------------------------------
This SF.net email is sponsored by
Make an app they can't live without
Enter the BlackBerry Developer Challenge
http://p.sf.net/sfu/RIM-dev2dev