diff options
Diffstat (limited to 'net/9p/util.c')
-rw-r--r-- | net/9p/util.c | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/net/9p/util.c b/net/9p/util.c new file mode 100644 index 00000000..6ceeeb38 --- /dev/null +++ b/net/9p/util.c @@ -0,0 +1,146 @@ +/* + * net/9p/util.c + * + * This file contains some helper functions + * + * Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net> + * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com> + * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to: + * Free Software Foundation + * 51 Franklin Street, Fifth Floor + * Boston, MA 02111-1301 USA + * + */ + +#include <linux/module.h> +#include <linux/errno.h> +#include <linux/fs.h> +#include <linux/sched.h> +#include <linux/parser.h> +#include <linux/idr.h> +#include <linux/slab.h> +#include <net/9p/9p.h> + +/** + * struct p9_idpool - per-connection accounting for tag idpool + * @lock: protects the pool + * @pool: idr to allocate tag id from + * + */ + +struct p9_idpool { + spinlock_t lock; + struct idr pool; +}; + +/** + * p9_idpool_create - create a new per-connection id pool + * + */ + +struct p9_idpool *p9_idpool_create(void) +{ + struct p9_idpool *p; + + p = kmalloc(sizeof(struct p9_idpool), GFP_KERNEL); + if (!p) + return ERR_PTR(-ENOMEM); + + spin_lock_init(&p->lock); + idr_init(&p->pool); + + return p; +} +EXPORT_SYMBOL(p9_idpool_create); + +/** + * p9_idpool_destroy - create a new per-connection id pool + * @p: idpool to destroy + */ + +void p9_idpool_destroy(struct p9_idpool *p) +{ + idr_destroy(&p->pool); + kfree(p); +} +EXPORT_SYMBOL(p9_idpool_destroy); + +/** + * p9_idpool_get - allocate numeric id from pool + * @p: pool to allocate from + * + * Bugs: This seems to be an awful generic function, should it be in idr.c with + * the lock included in struct idr? + */ + +int p9_idpool_get(struct p9_idpool *p) +{ + int i = 0; + int error; + unsigned long flags; + +retry: + if (idr_pre_get(&p->pool, GFP_NOFS) == 0) + return -1; + + spin_lock_irqsave(&p->lock, flags); + + /* no need to store exactly p, we just need something non-null */ + error = idr_get_new(&p->pool, p, &i); + spin_unlock_irqrestore(&p->lock, flags); + + if (error == -EAGAIN) + goto retry; + else if (error) + return -1; + + p9_debug(P9_DEBUG_MUX, " id %d pool %p\n", i, p); + return i; +} +EXPORT_SYMBOL(p9_idpool_get); + +/** + * p9_idpool_put - release numeric id from pool + * @id: numeric id which is being released + * @p: pool to release id into + * + * Bugs: This seems to be an awful generic function, should it be in idr.c with + * the lock included in struct idr? + */ + +void p9_idpool_put(int id, struct p9_idpool *p) +{ + unsigned long flags; + + p9_debug(P9_DEBUG_MUX, " id %d pool %p\n", id, p); + + spin_lock_irqsave(&p->lock, flags); + idr_remove(&p->pool, id); + spin_unlock_irqrestore(&p->lock, flags); +} +EXPORT_SYMBOL(p9_idpool_put); + +/** + * p9_idpool_check - check if the specified id is available + * @id: id to check + * @p: pool to check + */ + +int p9_idpool_check(int id, struct p9_idpool *p) +{ + return idr_find(&p->pool, id) != NULL; +} +EXPORT_SYMBOL(p9_idpool_check); + |