/*1* net/9p/util.c2*3* This file contains some helper functions4*5* Copyright (C) 2007 by Latchesar Ionkov <[email protected]>6* Copyright (C) 2004 by Eric Van Hensbergen <[email protected]>7* Copyright (C) 2002 by Ron Minnich <[email protected]>8*9* This program is free software; you can redistribute it and/or modify10* it under the terms of the GNU General Public License version 211* as published by the Free Software Foundation.12*13* This program is distributed in the hope that it will be useful,14* but WITHOUT ANY WARRANTY; without even the implied warranty of15* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the16* GNU General Public License for more details.17*18* You should have received a copy of the GNU General Public License19* along with this program; if not, write to:20* Free Software Foundation21* 51 Franklin Street, Fifth Floor22* Boston, MA 02111-1301 USA23*24*/2526#include <linux/module.h>27#include <linux/errno.h>28#include <linux/fs.h>29#include <linux/sched.h>30#include <linux/parser.h>31#include <linux/idr.h>32#include <linux/slab.h>33#include <net/9p/9p.h>3435/**36* struct p9_idpool - per-connection accounting for tag idpool37* @lock: protects the pool38* @pool: idr to allocate tag id from39*40*/4142struct p9_idpool {43spinlock_t lock;44struct idr pool;45};4647/**48* p9_idpool_create - create a new per-connection id pool49*50*/5152struct p9_idpool *p9_idpool_create(void)53{54struct p9_idpool *p;5556p = kmalloc(sizeof(struct p9_idpool), GFP_KERNEL);57if (!p)58return ERR_PTR(-ENOMEM);5960spin_lock_init(&p->lock);61idr_init(&p->pool);6263return p;64}65EXPORT_SYMBOL(p9_idpool_create);6667/**68* p9_idpool_destroy - create a new per-connection id pool69* @p: idpool to destroy70*/7172void p9_idpool_destroy(struct p9_idpool *p)73{74idr_destroy(&p->pool);75kfree(p);76}77EXPORT_SYMBOL(p9_idpool_destroy);7879/**80* p9_idpool_get - allocate numeric id from pool81* @p: pool to allocate from82*83* Bugs: This seems to be an awful generic function, should it be in idr.c with84* the lock included in struct idr?85*/8687int p9_idpool_get(struct p9_idpool *p)88{89int i = 0;90int error;91unsigned long flags;9293retry:94if (idr_pre_get(&p->pool, GFP_NOFS) == 0)95return -1;9697spin_lock_irqsave(&p->lock, flags);9899/* no need to store exactly p, we just need something non-null */100error = idr_get_new(&p->pool, p, &i);101spin_unlock_irqrestore(&p->lock, flags);102103if (error == -EAGAIN)104goto retry;105else if (error)106return -1;107108P9_DPRINTK(P9_DEBUG_MUX, " id %d pool %p\n", i, p);109return i;110}111EXPORT_SYMBOL(p9_idpool_get);112113/**114* p9_idpool_put - release numeric id from pool115* @id: numeric id which is being released116* @p: pool to release id into117*118* Bugs: This seems to be an awful generic function, should it be in idr.c with119* the lock included in struct idr?120*/121122void p9_idpool_put(int id, struct p9_idpool *p)123{124unsigned long flags;125126P9_DPRINTK(P9_DEBUG_MUX, " id %d pool %p\n", id, p);127128spin_lock_irqsave(&p->lock, flags);129idr_remove(&p->pool, id);130spin_unlock_irqrestore(&p->lock, flags);131}132EXPORT_SYMBOL(p9_idpool_put);133134/**135* p9_idpool_check - check if the specified id is available136* @id: id to check137* @p: pool to check138*/139140int p9_idpool_check(int id, struct p9_idpool *p)141{142return idr_find(&p->pool, id) != NULL;143}144EXPORT_SYMBOL(p9_idpool_check);145146147148