diff options
-rw-r--r-- | sys/fs/nwfs/nwfs_node.c | 130 | ||||
-rw-r--r-- | sys/fs/nwfs/nwfs_node.h | 4 | ||||
-rw-r--r-- | sys/fs/nwfs/nwfs_vfsops.c | 3 | ||||
-rw-r--r-- | sys/fs/nwfs/nwfs_vnops.c | 39 | ||||
-rw-r--r-- | sys/nwfs/nwfs_node.c | 130 | ||||
-rw-r--r-- | sys/nwfs/nwfs_node.h | 4 | ||||
-rw-r--r-- | sys/nwfs/nwfs_vfsops.c | 3 | ||||
-rw-r--r-- | sys/nwfs/nwfs_vnops.c | 39 |
8 files changed, 210 insertions, 142 deletions
diff --git a/sys/fs/nwfs/nwfs_node.c b/sys/fs/nwfs/nwfs_node.c index 4232e9b..2d34600 100644 --- a/sys/fs/nwfs/nwfs_node.c +++ b/sys/fs/nwfs/nwfs_node.c @@ -61,7 +61,7 @@ extern vop_t **nwfs_vnodeop_p; static LIST_HEAD(nwnode_hash_head,nwnode) *nwhashtbl; static u_long nwnodehash; -static int nwhashlock = 0; +static struct lock nwhashlock; MALLOC_DEFINE(M_NWNODE, "NWFS node", "NWFS vnode private part"); MALLOC_DEFINE(M_NWFSHASH, "NWFS hash", "NWFS has table"); @@ -76,20 +76,18 @@ SYSCTL_PROC(_vfs_nwfs, OID_AUTO, vnprint, CTLFLAG_WR|CTLTYPE_OPAQUE, NULL, 0, nwfs_sysctl_vnprint, "S,vnlist", "vnode hash"); void -nwfs_hash_init(void) -{ +nwfs_hash_init(void) { nwhashtbl = hashinit(desiredvnodes, M_NWFSHASH, &nwnodehash); + lockinit(&nwhashlock, PVFS, "nwfshl", 0, 0); } void -nwfs_hash_free(void) -{ +nwfs_hash_free(void) { free(nwhashtbl, M_NWFSHASH); } int -nwfs_sysctl_vnprint(SYSCTL_HANDLER_ARGS) -{ +nwfs_sysctl_vnprint(SYSCTL_HANDLER_ARGS) { struct nwnode *np; struct nwnode_hash_head *nhpp; struct vnode *vp; @@ -102,6 +100,7 @@ nwfs_sysctl_vnprint(SYSCTL_HANDLER_ARGS) nhpp = &nwhashtbl[i]; for (np = nhpp->lh_first; np != 0; np = np->n_hash.le_next) { vp = NWTOV(np); + vprint(NULL, vp); printf("%s:%d:%d:%d:%d\n",np->n_name,vp->v_usecount,vp->v_holdcnt, np->n_fid.f_id, np->n_fid.f_parent); } @@ -110,6 +109,27 @@ nwfs_sysctl_vnprint(SYSCTL_HANDLER_ARGS) } /* + * Search nwnode with given fid. + * Hash list should be locked by caller. + */ +static int +nwfs_hashlookup(struct nwmount *nmp, ncpfid fid, struct nwnode **npp) +{ + struct nwnode *np; + struct nwnode_hash_head *nhpp; + + nhpp = NWNOHASH(fid); + LIST_FOREACH(np, nhpp, n_hash) { + if (nmp != np->n_mount || !NWCMPF(&fid, &np->n_fid)) + continue; + if (npp) + *npp = np; + return 0; + } + return ENOENT; +} + +/* * Allocate new nwfsnode/vnode from given nwnode. * Vnode referenced and not locked. */ @@ -117,33 +137,26 @@ int nwfs_allocvp(struct mount *mp, ncpfid fid, struct vnode **vpp) { struct proc *p = curproc; /* XXX */ - struct nwnode *np, *np2; + struct nwnode *np; struct nwnode_hash_head *nhpp; + struct nwmount *nmp = VFSTONWFS(mp); struct vnode *vp; int error; -retry: - nhpp = NWNOHASH(fid); loop: - for (np = nhpp->lh_first; np != 0; np = np->n_hash.le_next) { + lockmgr(&nwhashlock, LK_EXCLUSIVE, NULL, p); +rescan: + if (nwfs_hashlookup(nmp, fid, &np) == 0) { vp = NWTOV(np); - if (mp != vp->v_mount || !NWCMPF(&fid, &np->n_fid)) - continue; - if (vget(vp, LK_EXCLUSIVE, p)) + simple_lock(&vp->v_interlock); + lockmgr(&nwhashlock, LK_RELEASE, NULL, p); + if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p)) goto loop; *vpp = vp; return(0); } + lockmgr(&nwhashlock, LK_RELEASE, NULL, p); - /* lock list, or waiting in malloc can cause problems */ - if (nwhashlock) { - while(nwhashlock) { - nwhashlock = -1; - tsleep((caddr_t) &nwhashlock, PVM, "nwfsvp", 0); - } - goto loop; - } - nwhashlock = 1; /* * Do the MALLOC before the getnewvnode since doing so afterward * might cause a bogus v_data pointer to get dereferenced @@ -152,52 +165,47 @@ loop: MALLOC(np, struct nwnode *, sizeof *np, M_NWNODE, M_WAITOK); error = getnewvnode(VT_NWFS, mp, nwfs_vnodeop_p, &vp); if (error) { - if (nwhashlock < 0) - wakeup(&nwhashlock); - nwhashlock = 0; - *vpp = 0; + *vpp = NULL; FREE(np, M_NWNODE); return (error); } - *vpp = vp; - bzero(np,sizeof(*np)); + bzero(np, sizeof(*np)); vp->v_data = np; np->n_vnode = vp; - np->n_mount = VFSTONWFS(mp); - np->n_fid = fid; - for (np2 = nhpp->lh_first; np2 != 0; np2 = np->n_hash.le_next) { - if (mp != NWTOV(np2)->v_mount || !NWCMPF(&fid, &np2->n_fid)) - continue; + np->n_mount = nmp; + lockmgr(&nwhashlock, LK_EXCLUSIVE, NULL, p); + /* + * Another process can create vnode while we blocked in malloc() or + * getnewvnode(). Rescan list again. + */ + if (nwfs_hashlookup(nmp, fid, NULL) == 0) { + vp->v_data = NULL; + np->n_vnode = NULL; vrele(vp); FREE(np, M_NWNODE); - if (nwhashlock < 0) - wakeup(&nwhashlock); - nwhashlock = 0; - goto retry; + goto rescan; } + *vpp = vp; + np->n_fid = fid; + np->n_flag |= NNEW; + lockinit(&vp->v_lock, PINOD, "nwnode", 0, LK_CANRECURSE); + nhpp = NWNOHASH(fid); LIST_INSERT_HEAD(nhpp, np, n_hash); - if (nwhashlock < 0) - wakeup(&nwhashlock); - nwhashlock = 0; vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); - np->n_flag |= NNEW; - return (error); + lockmgr(&nwhashlock, LK_RELEASE, NULL, p); + return 0; } int -nwfs_lookupnp(struct nwmount *nmp, ncpfid fid, struct nwnode **npp) +nwfs_lookupnp(struct nwmount *nmp, ncpfid fid, struct proc *p, + struct nwnode **npp) { - struct nwnode *np; - struct nwnode_hash_head *nhpp; + int error; - nhpp = NWNOHASH(fid); - for (np = nhpp->lh_first; np != 0; np = np->n_hash.le_next) { - if (nmp != np->n_mount || !NWCMPF(&fid, &np->n_fid)) - continue; - *npp = np; - return(0); - } - return ENOENT; + lockmgr(&nwhashlock, LK_EXCLUSIVE, NULL, p); + error = nwfs_hashlookup(nmp, fid, npp); + lockmgr(&nwhashlock, LK_RELEASE, NULL, p); + return error; } /* @@ -206,23 +214,27 @@ nwfs_lookupnp(struct nwmount *nmp, ncpfid fid, struct nwnode **npp) int nwfs_reclaim(ap) struct vop_reclaim_args /* { - struct vnode *a_vp; + struct vnode *a_vp; + struct proc *a_p; } */ *ap; { struct vnode *dvp = NULL, *vp = ap->a_vp; struct nwnode *dnp, *np = VTONW(vp); - struct nwmount *nmp=VTONWFS(vp); + struct nwmount *nmp = VTONWFS(vp); + struct proc *p = ap->a_p; NCPVNDEBUG("%s,%d\n", np->n_name, vp->v_usecount); if (np->n_refparent) { np->n_refparent = 0; - if (nwfs_lookupnp(nmp, np->n_parent, &dnp) == 0) { + if (nwfs_lookupnp(nmp, np->n_parent, p, &dnp) == 0) { dvp = dnp->n_vnode; } else { NCPVNDEBUG("%s: has no parent ?\n",np->n_name); } } + lockmgr(&nwhashlock, LK_EXCLUSIVE, NULL, p); LIST_REMOVE(np, n_hash); + lockmgr(&nwhashlock, LK_RELEASE, NULL, p); cache_purge(vp); if (nmp->n_root == np) { nmp->n_root = NULL; @@ -255,6 +267,10 @@ nwfs_inactive(ap) np->opened = 0; } VOP_UNLOCK(vp, 0, p); + if (np->n_flag & NSHOULDFREE) { + cache_purge(vp); + vgone(vp); + } return (0); } /* diff --git a/sys/fs/nwfs/nwfs_node.h b/sys/fs/nwfs/nwfs_node.h index 4f705b4..1bcaee7 100644 --- a/sys/fs/nwfs/nwfs_node.h +++ b/sys/fs/nwfs/nwfs_node.h @@ -43,6 +43,7 @@ #define NMODIFIED 0x0004 /* bogus, until async IO implemented */ #define NNEW 0x0008 /* vnode has been allocated */ #define NVOLUME 0x0010 /* vnode references a volume */ +#define NSHOULDFREE 0x0020 /* vnode should be removed from hash */ struct nwnode { LIST_ENTRY(nwnode) n_hash; @@ -85,7 +86,8 @@ struct uio; void nwfs_hash_init(void); void nwfs_hash_free(void); int nwfs_allocvp(struct mount *mp, ncpfid fid, struct vnode **vpp); -int nwfs_lookupnp(struct nwmount *nmp, ncpfid fid, struct nwnode **npp); +int nwfs_lookupnp(struct nwmount *nmp, ncpfid fid, struct proc *p, + struct nwnode **npp); int nwfs_inactive(struct vop_inactive_args *); int nwfs_reclaim(struct vop_reclaim_args *); int nwfs_nget(struct mount *mp, ncpfid fid, struct nw_entry_info *fap, diff --git a/sys/fs/nwfs/nwfs_vfsops.c b/sys/fs/nwfs/nwfs_vfsops.c index 563911b..34a88c6 100644 --- a/sys/fs/nwfs/nwfs_vfsops.c +++ b/sys/fs/nwfs/nwfs_vfsops.c @@ -301,7 +301,8 @@ nwfs_root(struct mount *mp, struct vnode **vpp) { conn = NWFSTOCONN(nmp); if (nmp->n_root) { *vpp = NWTOV(nmp->n_root); - vget(*vpp, LK_EXCLUSIVE, curproc); + while (vget(*vpp, LK_EXCLUSIVE, curproc) != 0) + ; return 0; } error = ncp_lookup_volume(conn, nmp->m.mounted_vol, &vol, diff --git a/sys/fs/nwfs/nwfs_vnops.c b/sys/fs/nwfs/nwfs_vnops.c index 488840e..e309785 100644 --- a/sys/fs/nwfs/nwfs_vnops.c +++ b/sys/fs/nwfs/nwfs_vnops.c @@ -97,9 +97,9 @@ static struct vnodeopv_entry_desc nwfs_vnodeop_entries[] = { { &vop_putpages_desc, (vop_t *) nwfs_putpages }, { &vop_ioctl_desc, (vop_t *) nwfs_ioctl }, { &vop_inactive_desc, (vop_t *) nwfs_inactive }, - { &vop_islocked_desc, (vop_t *) vop_noislocked }, + { &vop_islocked_desc, (vop_t *) vop_stdislocked }, { &vop_link_desc, (vop_t *) nwfs_link }, - { &vop_lock_desc, (vop_t *) vop_sharedlock }, + { &vop_lock_desc, (vop_t *) vop_stdlock }, { &vop_lookup_desc, (vop_t *) nwfs_lookup }, { &vop_mkdir_desc, (vop_t *) nwfs_mkdir }, { &vop_mknod_desc, (vop_t *) nwfs_mknod }, @@ -114,7 +114,7 @@ static struct vnodeopv_entry_desc nwfs_vnodeop_entries[] = { { &vop_setattr_desc, (vop_t *) nwfs_setattr }, { &vop_strategy_desc, (vop_t *) nwfs_strategy }, { &vop_symlink_desc, (vop_t *) nwfs_symlink }, - { &vop_unlock_desc, (vop_t *) vop_nounlock }, + { &vop_unlock_desc, (vop_t *) vop_stdunlock }, { &vop_write_desc, (vop_t *) nwfs_write }, { NULL, NULL } }; @@ -192,7 +192,7 @@ nwfs_open(ap) NCPVNDEBUG("%s,%d\n",np->n_name, np->opened); if (vp->v_type != VREG && vp->v_type != VDIR) { - NCPFATAL("open eacces vtype=%d\n", vp->v_type); + NCPFATAL("open vtype = %d\n", vp->v_type); return (EACCES); } if (vp->v_type == VDIR) return 0; /* nothing to do now */ @@ -267,10 +267,12 @@ nwfs_close(ap) simple_unlock(&vp->v_interlock); return 0; } - if (--np->opened == 0) + if (--np->opened == 0) { + simple_unlock(&vp->v_interlock); error = ncp_close_file(NWFSTOCONN(VTONWFS(vp)), &np->n_fh, ap->a_p, ap->a_cred); - simple_unlock(&vp->v_interlock); + } else + simple_unlock(&vp->v_interlock); np->n_atime = 0; return (error); } @@ -504,7 +506,10 @@ nwfs_remove(ap) cache_purge(vp); error = ncp_DeleteNSEntry(nmp, VTONW(dvp)->n_fid.f_id, cnp->cn_namelen,cnp->cn_nameptr,cnp->cn_proc,cnp->cn_cred); - if (error == 0x899c) error = EACCES; + if (error == 0) + np->n_flag |= NSHOULDFREE; + else if (error == 0x899c) + error = EACCES; } return (error); } @@ -700,16 +705,20 @@ nwfs_rmdir(ap) struct vnode *vp = ap->a_vp; struct vnode *dvp = ap->a_dvp; struct componentname *cnp = ap->a_cnp; + struct nwnode *np = VTONW(vp); struct nwmount *nmp = VTONWFS(vp); struct nwnode *dnp = VTONW(dvp); int error = EIO; - if (dvp == vp) return EINVAL; - if (!ncp_conn_valid(NWFSTOCONN(nmp))) return(error); + if (dvp == vp) + return EINVAL; error = ncp_DeleteNSEntry(nmp, dnp->n_fid.f_id, cnp->cn_namelen, cnp->cn_nameptr,cnp->cn_proc,cnp->cn_cred); - if (error == NWE_DIR_NOT_EMPTY) error = ENOTEMPTY; + if (error == 0) + np->n_flag |= NSHOULDFREE; + else if (error == NWE_DIR_NOT_EMPTY) + error = ENOTEMPTY; dnp->n_flag |= NMODIFIED; nwfs_attr_cacheremove(dvp); cache_purge(dvp); @@ -759,13 +768,19 @@ nwfs_fsync(ap) /* return (nfs_flush(ap->a_vp, ap->a_cred, ap->a_waitfor, ap->a_p, 1));*/ return (0); } + /* ARGSUSED */ static int nwfs_print (ap) struct vop_print_args /* { - struct vnode *a_vp; + struct vnode *a_vp; } */ *ap; { + struct vnode *vp = ap->a_vp; + struct nwnode *np = VTONW(vp); + + printf("nwfs node: name = '%s', fid = %d, pfid = %d\n", + np->n_name, np->n_fid.f_id, np->n_fid.f_parent); return (0); } @@ -1003,7 +1018,7 @@ printf("dvp %d:%d:%d\n", (int)mp, (int)dvp->v_flag & VROOT, (int)flags & ISDOTDO fap = NULL; notfound = 0; } else { - error = nwfs_lookupnp(nmp, dnp->n_parent, &npp); + error = nwfs_lookupnp(nmp, dnp->n_parent, p, &npp); if (error) { return error; } diff --git a/sys/nwfs/nwfs_node.c b/sys/nwfs/nwfs_node.c index 4232e9b..2d34600 100644 --- a/sys/nwfs/nwfs_node.c +++ b/sys/nwfs/nwfs_node.c @@ -61,7 +61,7 @@ extern vop_t **nwfs_vnodeop_p; static LIST_HEAD(nwnode_hash_head,nwnode) *nwhashtbl; static u_long nwnodehash; -static int nwhashlock = 0; +static struct lock nwhashlock; MALLOC_DEFINE(M_NWNODE, "NWFS node", "NWFS vnode private part"); MALLOC_DEFINE(M_NWFSHASH, "NWFS hash", "NWFS has table"); @@ -76,20 +76,18 @@ SYSCTL_PROC(_vfs_nwfs, OID_AUTO, vnprint, CTLFLAG_WR|CTLTYPE_OPAQUE, NULL, 0, nwfs_sysctl_vnprint, "S,vnlist", "vnode hash"); void -nwfs_hash_init(void) -{ +nwfs_hash_init(void) { nwhashtbl = hashinit(desiredvnodes, M_NWFSHASH, &nwnodehash); + lockinit(&nwhashlock, PVFS, "nwfshl", 0, 0); } void -nwfs_hash_free(void) -{ +nwfs_hash_free(void) { free(nwhashtbl, M_NWFSHASH); } int -nwfs_sysctl_vnprint(SYSCTL_HANDLER_ARGS) -{ +nwfs_sysctl_vnprint(SYSCTL_HANDLER_ARGS) { struct nwnode *np; struct nwnode_hash_head *nhpp; struct vnode *vp; @@ -102,6 +100,7 @@ nwfs_sysctl_vnprint(SYSCTL_HANDLER_ARGS) nhpp = &nwhashtbl[i]; for (np = nhpp->lh_first; np != 0; np = np->n_hash.le_next) { vp = NWTOV(np); + vprint(NULL, vp); printf("%s:%d:%d:%d:%d\n",np->n_name,vp->v_usecount,vp->v_holdcnt, np->n_fid.f_id, np->n_fid.f_parent); } @@ -110,6 +109,27 @@ nwfs_sysctl_vnprint(SYSCTL_HANDLER_ARGS) } /* + * Search nwnode with given fid. + * Hash list should be locked by caller. + */ +static int +nwfs_hashlookup(struct nwmount *nmp, ncpfid fid, struct nwnode **npp) +{ + struct nwnode *np; + struct nwnode_hash_head *nhpp; + + nhpp = NWNOHASH(fid); + LIST_FOREACH(np, nhpp, n_hash) { + if (nmp != np->n_mount || !NWCMPF(&fid, &np->n_fid)) + continue; + if (npp) + *npp = np; + return 0; + } + return ENOENT; +} + +/* * Allocate new nwfsnode/vnode from given nwnode. * Vnode referenced and not locked. */ @@ -117,33 +137,26 @@ int nwfs_allocvp(struct mount *mp, ncpfid fid, struct vnode **vpp) { struct proc *p = curproc; /* XXX */ - struct nwnode *np, *np2; + struct nwnode *np; struct nwnode_hash_head *nhpp; + struct nwmount *nmp = VFSTONWFS(mp); struct vnode *vp; int error; -retry: - nhpp = NWNOHASH(fid); loop: - for (np = nhpp->lh_first; np != 0; np = np->n_hash.le_next) { + lockmgr(&nwhashlock, LK_EXCLUSIVE, NULL, p); +rescan: + if (nwfs_hashlookup(nmp, fid, &np) == 0) { vp = NWTOV(np); - if (mp != vp->v_mount || !NWCMPF(&fid, &np->n_fid)) - continue; - if (vget(vp, LK_EXCLUSIVE, p)) + simple_lock(&vp->v_interlock); + lockmgr(&nwhashlock, LK_RELEASE, NULL, p); + if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p)) goto loop; *vpp = vp; return(0); } + lockmgr(&nwhashlock, LK_RELEASE, NULL, p); - /* lock list, or waiting in malloc can cause problems */ - if (nwhashlock) { - while(nwhashlock) { - nwhashlock = -1; - tsleep((caddr_t) &nwhashlock, PVM, "nwfsvp", 0); - } - goto loop; - } - nwhashlock = 1; /* * Do the MALLOC before the getnewvnode since doing so afterward * might cause a bogus v_data pointer to get dereferenced @@ -152,52 +165,47 @@ loop: MALLOC(np, struct nwnode *, sizeof *np, M_NWNODE, M_WAITOK); error = getnewvnode(VT_NWFS, mp, nwfs_vnodeop_p, &vp); if (error) { - if (nwhashlock < 0) - wakeup(&nwhashlock); - nwhashlock = 0; - *vpp = 0; + *vpp = NULL; FREE(np, M_NWNODE); return (error); } - *vpp = vp; - bzero(np,sizeof(*np)); + bzero(np, sizeof(*np)); vp->v_data = np; np->n_vnode = vp; - np->n_mount = VFSTONWFS(mp); - np->n_fid = fid; - for (np2 = nhpp->lh_first; np2 != 0; np2 = np->n_hash.le_next) { - if (mp != NWTOV(np2)->v_mount || !NWCMPF(&fid, &np2->n_fid)) - continue; + np->n_mount = nmp; + lockmgr(&nwhashlock, LK_EXCLUSIVE, NULL, p); + /* + * Another process can create vnode while we blocked in malloc() or + * getnewvnode(). Rescan list again. + */ + if (nwfs_hashlookup(nmp, fid, NULL) == 0) { + vp->v_data = NULL; + np->n_vnode = NULL; vrele(vp); FREE(np, M_NWNODE); - if (nwhashlock < 0) - wakeup(&nwhashlock); - nwhashlock = 0; - goto retry; + goto rescan; } + *vpp = vp; + np->n_fid = fid; + np->n_flag |= NNEW; + lockinit(&vp->v_lock, PINOD, "nwnode", 0, LK_CANRECURSE); + nhpp = NWNOHASH(fid); LIST_INSERT_HEAD(nhpp, np, n_hash); - if (nwhashlock < 0) - wakeup(&nwhashlock); - nwhashlock = 0; vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); - np->n_flag |= NNEW; - return (error); + lockmgr(&nwhashlock, LK_RELEASE, NULL, p); + return 0; } int -nwfs_lookupnp(struct nwmount *nmp, ncpfid fid, struct nwnode **npp) +nwfs_lookupnp(struct nwmount *nmp, ncpfid fid, struct proc *p, + struct nwnode **npp) { - struct nwnode *np; - struct nwnode_hash_head *nhpp; + int error; - nhpp = NWNOHASH(fid); - for (np = nhpp->lh_first; np != 0; np = np->n_hash.le_next) { - if (nmp != np->n_mount || !NWCMPF(&fid, &np->n_fid)) - continue; - *npp = np; - return(0); - } - return ENOENT; + lockmgr(&nwhashlock, LK_EXCLUSIVE, NULL, p); + error = nwfs_hashlookup(nmp, fid, npp); + lockmgr(&nwhashlock, LK_RELEASE, NULL, p); + return error; } /* @@ -206,23 +214,27 @@ nwfs_lookupnp(struct nwmount *nmp, ncpfid fid, struct nwnode **npp) int nwfs_reclaim(ap) struct vop_reclaim_args /* { - struct vnode *a_vp; + struct vnode *a_vp; + struct proc *a_p; } */ *ap; { struct vnode *dvp = NULL, *vp = ap->a_vp; struct nwnode *dnp, *np = VTONW(vp); - struct nwmount *nmp=VTONWFS(vp); + struct nwmount *nmp = VTONWFS(vp); + struct proc *p = ap->a_p; NCPVNDEBUG("%s,%d\n", np->n_name, vp->v_usecount); if (np->n_refparent) { np->n_refparent = 0; - if (nwfs_lookupnp(nmp, np->n_parent, &dnp) == 0) { + if (nwfs_lookupnp(nmp, np->n_parent, p, &dnp) == 0) { dvp = dnp->n_vnode; } else { NCPVNDEBUG("%s: has no parent ?\n",np->n_name); } } + lockmgr(&nwhashlock, LK_EXCLUSIVE, NULL, p); LIST_REMOVE(np, n_hash); + lockmgr(&nwhashlock, LK_RELEASE, NULL, p); cache_purge(vp); if (nmp->n_root == np) { nmp->n_root = NULL; @@ -255,6 +267,10 @@ nwfs_inactive(ap) np->opened = 0; } VOP_UNLOCK(vp, 0, p); + if (np->n_flag & NSHOULDFREE) { + cache_purge(vp); + vgone(vp); + } return (0); } /* diff --git a/sys/nwfs/nwfs_node.h b/sys/nwfs/nwfs_node.h index 4f705b4..1bcaee7 100644 --- a/sys/nwfs/nwfs_node.h +++ b/sys/nwfs/nwfs_node.h @@ -43,6 +43,7 @@ #define NMODIFIED 0x0004 /* bogus, until async IO implemented */ #define NNEW 0x0008 /* vnode has been allocated */ #define NVOLUME 0x0010 /* vnode references a volume */ +#define NSHOULDFREE 0x0020 /* vnode should be removed from hash */ struct nwnode { LIST_ENTRY(nwnode) n_hash; @@ -85,7 +86,8 @@ struct uio; void nwfs_hash_init(void); void nwfs_hash_free(void); int nwfs_allocvp(struct mount *mp, ncpfid fid, struct vnode **vpp); -int nwfs_lookupnp(struct nwmount *nmp, ncpfid fid, struct nwnode **npp); +int nwfs_lookupnp(struct nwmount *nmp, ncpfid fid, struct proc *p, + struct nwnode **npp); int nwfs_inactive(struct vop_inactive_args *); int nwfs_reclaim(struct vop_reclaim_args *); int nwfs_nget(struct mount *mp, ncpfid fid, struct nw_entry_info *fap, diff --git a/sys/nwfs/nwfs_vfsops.c b/sys/nwfs/nwfs_vfsops.c index 563911b..34a88c6 100644 --- a/sys/nwfs/nwfs_vfsops.c +++ b/sys/nwfs/nwfs_vfsops.c @@ -301,7 +301,8 @@ nwfs_root(struct mount *mp, struct vnode **vpp) { conn = NWFSTOCONN(nmp); if (nmp->n_root) { *vpp = NWTOV(nmp->n_root); - vget(*vpp, LK_EXCLUSIVE, curproc); + while (vget(*vpp, LK_EXCLUSIVE, curproc) != 0) + ; return 0; } error = ncp_lookup_volume(conn, nmp->m.mounted_vol, &vol, diff --git a/sys/nwfs/nwfs_vnops.c b/sys/nwfs/nwfs_vnops.c index 488840e..e309785 100644 --- a/sys/nwfs/nwfs_vnops.c +++ b/sys/nwfs/nwfs_vnops.c @@ -97,9 +97,9 @@ static struct vnodeopv_entry_desc nwfs_vnodeop_entries[] = { { &vop_putpages_desc, (vop_t *) nwfs_putpages }, { &vop_ioctl_desc, (vop_t *) nwfs_ioctl }, { &vop_inactive_desc, (vop_t *) nwfs_inactive }, - { &vop_islocked_desc, (vop_t *) vop_noislocked }, + { &vop_islocked_desc, (vop_t *) vop_stdislocked }, { &vop_link_desc, (vop_t *) nwfs_link }, - { &vop_lock_desc, (vop_t *) vop_sharedlock }, + { &vop_lock_desc, (vop_t *) vop_stdlock }, { &vop_lookup_desc, (vop_t *) nwfs_lookup }, { &vop_mkdir_desc, (vop_t *) nwfs_mkdir }, { &vop_mknod_desc, (vop_t *) nwfs_mknod }, @@ -114,7 +114,7 @@ static struct vnodeopv_entry_desc nwfs_vnodeop_entries[] = { { &vop_setattr_desc, (vop_t *) nwfs_setattr }, { &vop_strategy_desc, (vop_t *) nwfs_strategy }, { &vop_symlink_desc, (vop_t *) nwfs_symlink }, - { &vop_unlock_desc, (vop_t *) vop_nounlock }, + { &vop_unlock_desc, (vop_t *) vop_stdunlock }, { &vop_write_desc, (vop_t *) nwfs_write }, { NULL, NULL } }; @@ -192,7 +192,7 @@ nwfs_open(ap) NCPVNDEBUG("%s,%d\n",np->n_name, np->opened); if (vp->v_type != VREG && vp->v_type != VDIR) { - NCPFATAL("open eacces vtype=%d\n", vp->v_type); + NCPFATAL("open vtype = %d\n", vp->v_type); return (EACCES); } if (vp->v_type == VDIR) return 0; /* nothing to do now */ @@ -267,10 +267,12 @@ nwfs_close(ap) simple_unlock(&vp->v_interlock); return 0; } - if (--np->opened == 0) + if (--np->opened == 0) { + simple_unlock(&vp->v_interlock); error = ncp_close_file(NWFSTOCONN(VTONWFS(vp)), &np->n_fh, ap->a_p, ap->a_cred); - simple_unlock(&vp->v_interlock); + } else + simple_unlock(&vp->v_interlock); np->n_atime = 0; return (error); } @@ -504,7 +506,10 @@ nwfs_remove(ap) cache_purge(vp); error = ncp_DeleteNSEntry(nmp, VTONW(dvp)->n_fid.f_id, cnp->cn_namelen,cnp->cn_nameptr,cnp->cn_proc,cnp->cn_cred); - if (error == 0x899c) error = EACCES; + if (error == 0) + np->n_flag |= NSHOULDFREE; + else if (error == 0x899c) + error = EACCES; } return (error); } @@ -700,16 +705,20 @@ nwfs_rmdir(ap) struct vnode *vp = ap->a_vp; struct vnode *dvp = ap->a_dvp; struct componentname *cnp = ap->a_cnp; + struct nwnode *np = VTONW(vp); struct nwmount *nmp = VTONWFS(vp); struct nwnode *dnp = VTONW(dvp); int error = EIO; - if (dvp == vp) return EINVAL; - if (!ncp_conn_valid(NWFSTOCONN(nmp))) return(error); + if (dvp == vp) + return EINVAL; error = ncp_DeleteNSEntry(nmp, dnp->n_fid.f_id, cnp->cn_namelen, cnp->cn_nameptr,cnp->cn_proc,cnp->cn_cred); - if (error == NWE_DIR_NOT_EMPTY) error = ENOTEMPTY; + if (error == 0) + np->n_flag |= NSHOULDFREE; + else if (error == NWE_DIR_NOT_EMPTY) + error = ENOTEMPTY; dnp->n_flag |= NMODIFIED; nwfs_attr_cacheremove(dvp); cache_purge(dvp); @@ -759,13 +768,19 @@ nwfs_fsync(ap) /* return (nfs_flush(ap->a_vp, ap->a_cred, ap->a_waitfor, ap->a_p, 1));*/ return (0); } + /* ARGSUSED */ static int nwfs_print (ap) struct vop_print_args /* { - struct vnode *a_vp; + struct vnode *a_vp; } */ *ap; { + struct vnode *vp = ap->a_vp; + struct nwnode *np = VTONW(vp); + + printf("nwfs node: name = '%s', fid = %d, pfid = %d\n", + np->n_name, np->n_fid.f_id, np->n_fid.f_parent); return (0); } @@ -1003,7 +1018,7 @@ printf("dvp %d:%d:%d\n", (int)mp, (int)dvp->v_flag & VROOT, (int)flags & ISDOTDO fap = NULL; notfound = 0; } else { - error = nwfs_lookupnp(nmp, dnp->n_parent, &npp); + error = nwfs_lookupnp(nmp, dnp->n_parent, p, &npp); if (error) { return error; } |