9p: 9P server fid management
Subsystems (2)
Latchesar Ionkov
maintainerRFC PATCH 4/6 9p: 9P server fid management
This patchset provides support for in-kernel 9P2000 servers.
This patch adds the 9P server fid management.
Signed-off-by Latchesar Ionkov <[email protected]>
--- net/9p/srv/fid.c | 178 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 178 insertions(+), 0 deletions(-) create mode 100644 net/9p/srv/fid.c
net/9p/srv/fid.c new file +178 -0
@@ -0,0 +1,178 @@ +/* +* net/9p/srv/fid.c +* +* Fid Management +* +* Copyright (C) 2007 by Latchesar Ionkov <[email protected]> +* +* 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/poll.h> +#include <linux/list.h> +#include <linux/hash.h> +#include <linux/parser.h> +#include <net/9p/9p.h> +#include <net/9p/transport.h> +#include <net/9p/srv.h> +#include "srvimpl.h" + +struct p9srv_fidpool *p9srv_fidpool_create (void ) +{ +int i; +struct p9srv_fidpool *fp; + + fp =kmalloc (sizeof (struct p9srv_fidpool ),GFP_KERNEL ); +if (!fp) +return ERR_PTR (-ENOMEM ); + +spin_lock_init (&fp->lock); +for (i =0 ; i <FID_HTABLE_SIZE ; i++) +INIT_HLIST_HEAD (&fp->hash[i]); + +P9_DPRINTK (P9SRV_DEBUG_FID ,"fidpool %p\n" , fp); +return fp; +} + +void p9srv_fidpool_destroy (struct p9srv_fidpool *fp) +{ +int i; + +P9_DPRINTK (P9SRV_DEBUG_FID ,"fidpool %p\n" , fp); +for (i =0 ; i <FID_HTABLE_SIZE ; i++) +BUG_ON (!hlist_empty (&fp->hash[i])); + +kfree (fp); +} + +void p9srv_fidpool_reset (struct p9srv_fidpool *fp) +{ +int i; +struct p9srv_fid *cfid; +struct hlist_node *hn, *htmp; +HLIST_HEAD (hh); + +P9_DPRINTK (P9SRV_DEBUG_FID ,"fidpool %p\n" , fp); +spin_lock (&fp->lock); +for (i =0 ; i <FID_HTABLE_SIZE ; i++) { +hlist_for_each_entry_safe (cfid, hn, htmp, &fp->hash[i], + fid_list) { +hlist_del (hn); +hlist_add_head (hn, &hh); + } + } +spin_unlock (&fp->lock); + +hlist_for_each_entry_safe (cfid, hn, htmp, &hh, fid_list) { +atomic_set (&cfid->refcount,1 ); +p9srv_fid_decref (cfid); + } +} + +struct p9srv_fid *p9srv_fid_create (struct p9srv_fidpool *fp,u32 fid) +{ +unsigned long hash; +struct p9srv_fid *cfid, *nfid; +struct hlist_node *hn; + +P9_DPRINTK (P9SRV_DEBUG_FID ,"fidpool %p fid %d\n" , fp, fid); + hash =hash_long (fid,FID_HTABLE_BITS ); + nfid =kmalloc (sizeof (struct p9srv_fid ),GFP_KERNEL ); +if (!nfid) +return ERR_PTR (-ENOMEM ); + + nfid->fid = fid; +atomic_set (&nfid->refcount,0 ); + nfid->conn =NULL ; + nfid->aux =NULL ; + nfid->omode = ~0 ; + nfid->type =0 ; + nfid->diroffset =0 ; + nfid->uid = ~0 ; + nfid->fidpool = fp; +INIT_HLIST_NODE (&nfid->fid_list); +spin_lock (&fp->lock); +hlist_for_each_entry (cfid, hn, &fp->hash[hash], fid_list) { +if (cfid->fid == fid) { +spin_unlock (&fp->lock); +kfree (nfid); +return ERR_PTR (-EEXIST ); + } + } + +hlist_add_head (&nfid->fid_list, &fp->hash[hash]); +spin_unlock (&fp->lock); +p9srv_fid_incref (nfid); +return nfid; +} + +struct p9srv_fid *p9srv_fid_find (struct p9srv_fidpool *fp,u32 fid) +{ +unsigned long hash; +struct p9srv_fid *cfid; +struct hlist_node *hn; + + hash =hash_long (fid,FID_HTABLE_BITS ); +spin_lock (&fp->lock); +hlist_for_each_entry (cfid, hn, &fp->hash[hash], fid_list) { +if (cfid->fid == fid) { +spin_unlock (&fp->lock); +p9srv_fid_incref (cfid); +return cfid; + } + } +spin_unlock (&fp->lock); + +return NULL ; +} +EXPORT_SYMBOL (p9srv_fid_find); + +void p9srv_fid_incref (struct p9srv_fid *fid) +{ +if (fid) +atomic_inc (&fid->refcount); + +P9_DPRINTK (P9SRV_DEBUG_FID ,"fidpool %p fid %d count %d\n" , + fid->fidpool, fid->fid,atomic_read (&fid->refcount)); +} +EXPORT_SYMBOL (p9srv_fid_incref); + +void p9srv_fid_decref (struct p9srv_fid *fid) +{ +int n; + +if (!fid) +return ; + + n =atomic_dec_and_test (&fid->refcount); +P9_DPRINTK (P9SRV_DEBUG_FID ,"fidpool %p fid %d count %d \n" , + fid->fidpool, fid->fid,atomic_read (&fid->refcount)); +if (n) { +P9_DPRINTK (P9SRV_DEBUG_FID ,"destroy fidpool %p fid %d\n" , + fid->fidpool, fid->fid); +spin_lock (&fid->fidpool->lock); +hlist_del (&fid->fid_list); +spin_unlock (&fid->fidpool->lock); +if (fid->conn && fid->conn->srv && fid->conn->srv->fiddestroy) + (*fid->conn->srv->fiddestroy)(fid); +kfree (fid); + } +} +EXPORT_SYMBOL (p9srv_fid_decref);
Signature · 1 line
1.5.2.4