summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbp <bp@FreeBSD.org>2000-10-02 09:49:04 +0000
committerbp <bp@FreeBSD.org>2000-10-02 09:49:04 +0000
commitaf5c59dc4ff3f56184587c5798871262a8a7a217 (patch)
treef561b87c9c02b46312db8fbd1949d05303c8e94d
parent72e68d3b765994ed27cdd33c3f725fcc3328cac3 (diff)
downloadFreeBSD-src-af5c59dc4ff3f56184587c5798871262a8a7a217.zip
FreeBSD-src-af5c59dc4ff3f56184587c5798871262a8a7a217.tar.gz
Protect hash data with lock manager instead of home grown one.
Replace shared lock on vnode with exclusive one. It shouldn't impact perfomance as NCP protocol doesn't support outstanding requests. Do not hold simple lock on vnode for long period of time. Add functionality to the nwfs_print() routine.
-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