Blame | Last modification | View Log | RSS feed
#include <sys/param.h>
#include <sys/sockio.h>
#include <sys/proc.h>
#include <sys/vnode.h>
#include <sys/kernel.h>
#include <sys/sysctl.h>
#include <sys/malloc.h>
#include <sys/mount.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/systm.h>
#include <sys/protosw.h>
#include <sys/syslog.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <vm/vm.h>
#include <vm/vm_extern.h>
#include <vm/vm_zone.h>
#include <net/if.h>
#include <net/route.h>
#include <netinet/in.h>
#include <9fs/bitstring.h>
#include <9fs/9p.h>
#include <9fs/9auth.h>
#include <9fs/9fs.h>
vm_zone_t u9fsnode_zone;
static LIST_HEAD(u9fsnodehashhead, u9fsnode) *u9fsnodehashtbl;
static u_long u9fsnodehash;
MALLOC_DEFINE(M_U9FSHASH, "U9FS hash", "U9FS hash tables");
/*
* Initialize hash links for u9fsnodes
* and build u9fsnode free list.
*/
void
u9fs_nhinit()
{
u9fsnode_zone = zinit("U9FSNODE", sizeof(struct u9fsnode), 0, 0, 1);
u9fsnodehashtbl = phashinit(desiredvnodes, M_U9FSHASH, &u9fsnodehash);
}
/*
* Look up a vnode/u9fsnode by file handle.
* Callers must check for mount points!!
* In all cases, a pointer to a
* u9fsnode structure is returned.
*/
static int u9fs_node_hash_lock;
int
u9fs_nget(mntp, fh, npp, p)
struct mount *mntp;
register u9fsfh_t fh;
struct u9fsnode **npp;
struct proc * p;
{
struct u9fsnode *np;
struct u9fsnodehashhead *nhpp;
register struct vnode *vp;
struct vnode *nvp;
int error;
nhpp = U9FSNOHASH(fh);
loop:
for (np = nhpp->lh_first; np != 0; np = np->n_hash.le_next) {
if (mntp != U9FSTOV(np)->v_mount || fh != np->n_qid.path )
continue;
vp = U9FSTOV(np);
if (vget(vp, LK_EXCLUSIVE, p))
goto loop;
*npp = np;
return(0);
}
/*
* Obtain a lock to prevent a race condition if the getnewvnode()
* or MALLOC() below happens to block.
*/
if (u9fs_node_hash_lock) {
while (u9fs_node_hash_lock) {
u9fs_node_hash_lock = -1;
tsleep(&u9fs_node_hash_lock, PVM, "u9fsngt", 0);
}
goto loop;
}
u9fs_node_hash_lock = 1;
/*
* allocate before getnewvnode since doing so afterward
* might cause a bogus v_data pointer to get dereferenced
* elsewhere if zalloc should block.
*/
np = zalloc(u9fsnode_zone);
error = getnewvnode(VT_U9FS, mntp, u9fs_vnodeop_p, &nvp);
if (error) {
if (u9fs_node_hash_lock < 0)
wakeup(&u9fs_node_hash_lock);
u9fs_node_hash_lock = 0;
*npp = 0;
zfree(u9fsnode_zone, np);
return (error);
}
vp = nvp;
bzero((caddr_t)np, sizeof *np);
vp->v_data = np;
np->n_vnode = vp;
/*
* Insert the u9fsnode in the hash queue for its new file handle
*/
LIST_INSERT_HEAD(nhpp, np, n_hash);
np->n_qid.path = fh;
np->n_qid.vers = 0; /* not in cache yet */
np->n_fid = 0; /* should be set by the caller */
*npp = np;
if (u9fs_node_hash_lock < 0)
wakeup(&u9fs_node_hash_lock);
u9fs_node_hash_lock = 0;
/*
* Lock the new u9fsnode.
*/
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
return (0);
}