summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/fs/nwfs/nwfs_node.c130
-rw-r--r--sys/fs/nwfs/nwfs_node.h4
-rw-r--r--sys/fs/nwfs/nwfs_vfsops.c3
-rw-r--r--sys/fs/nwfs/nwfs_vnops.c39
-rw-r--r--sys/nwfs/nwfs_node.c130
-rw-r--r--sys/nwfs/nwfs_node.h4
-rw-r--r--sys/nwfs/nwfs_vfsops.c3
-rw-r--r--sys/nwfs/nwfs_vnops.c39
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;
}
OpenPOWER on IntegriCloud