summaryrefslogtreecommitdiffstats
path: root/sys/fs
diff options
context:
space:
mode:
authortegge <tegge@FreeBSD.org>2007-03-13 01:50:27 +0000
committertegge <tegge@FreeBSD.org>2007-03-13 01:50:27 +0000
commit214bc5723c38739a6060170f2c421e59d87b2c82 (patch)
tree6dca3f2c99e6dcb6402e1486118e56eb8d5e871b /sys/fs
parent76cbc46fe707603a2b4dde9cc8398128868b56ee (diff)
downloadFreeBSD-src-214bc5723c38739a6060170f2c421e59d87b2c82.zip
FreeBSD-src-214bc5723c38739a6060170f2c421e59d87b2c82.tar.gz
Make insmntque() externally visibile and allow it to fail (e.g. during
late stages of unmount). On failure, the vnode is recycled. Add insmntque1(), to allow for file system specific cleanup when recycling vnode on failure. Change getnewvnode() to no longer call insmntque(). Previously, embryonic vnodes were put onto the list of vnode belonging to a file system, which is unsafe for a file system marked MPSAFE. Change vfs_hash_insert() to no longer lock the vnode. The caller now has that responsibility. Change most file systems to lock the vnode and call insmntque() or insmntque1() after a new vnode has been sufficiently setup. Handle failed insmntque*() calls by propagating errors to callers, possibly after some file system specific cleanup. Approved by: re (kensmith) Reviewed by: kib In collaboration with: kib
Diffstat (limited to 'sys/fs')
-rw-r--r--sys/fs/cd9660/cd9660_vfsops.c13
-rw-r--r--sys/fs/coda/coda_vnops.c3
-rw-r--r--sys/fs/devfs/devfs_vnops.c23
-rw-r--r--sys/fs/fdescfs/fdesc_vnops.c7
-rw-r--r--sys/fs/hpfs/hpfs_vfsops.c12
-rw-r--r--sys/fs/msdosfs/msdosfs_denode.c11
-rw-r--r--sys/fs/ntfs/ntfs_vfsops.c7
-rw-r--r--sys/fs/nullfs/null_subr.c15
-rw-r--r--sys/fs/nwfs/nwfs_node.c6
-rw-r--r--sys/fs/portalfs/portal_vfsops.c7
-rw-r--r--sys/fs/portalfs/portal_vnops.c5
-rw-r--r--sys/fs/pseudofs/pseudofs_vncache.c10
-rw-r--r--sys/fs/smbfs/smbfs_node.c5
-rw-r--r--sys/fs/udf/udf_vfsops.c8
-rw-r--r--sys/fs/umapfs/umap_subr.c6
-rw-r--r--sys/fs/unionfs/union_subr.c5
16 files changed, 132 insertions, 11 deletions
diff --git a/sys/fs/cd9660/cd9660_vfsops.c b/sys/fs/cd9660/cd9660_vfsops.c
index 319b192..2b557a0 100644
--- a/sys/fs/cd9660/cd9660_vfsops.c
+++ b/sys/fs/cd9660/cd9660_vfsops.c
@@ -663,8 +663,10 @@ cd9660_vget_internal(mp, ino, flags, vpp, relocated, isodir)
struct vnode *vp;
struct cdev *dev;
int error;
+ struct thread *td;
- error = vfs_hash_get(mp, ino, flags, curthread, vpp, NULL, NULL);
+ td = curthread;
+ error = vfs_hash_get(mp, ino, flags, td, vpp, NULL, NULL);
if (error || *vpp != NULL)
return (error);
@@ -682,7 +684,14 @@ cd9660_vget_internal(mp, ino, flags, vpp, relocated, isodir)
ip->i_vnode = vp;
ip->i_number = ino;
- error = vfs_hash_insert(vp, ino, flags, curthread, vpp, NULL, NULL);
+ lockmgr(vp->v_vnlock, LK_EXCLUSIVE, NULL, td);
+ error = insmntque(vp, mp);
+ if (error != 0) {
+ free(ip, M_ISOFSNODE);
+ *vpp = NULLVP;
+ return (error);
+ }
+ error = vfs_hash_insert(vp, ino, flags, td, vpp, NULL, NULL);
if (error || *vpp != NULL)
return (error);
diff --git a/sys/fs/coda/coda_vnops.c b/sys/fs/coda/coda_vnops.c
index c35dda8..f5b246b 100644
--- a/sys/fs/coda/coda_vnops.c
+++ b/sys/fs/coda/coda_vnops.c
@@ -1797,6 +1797,9 @@ make_coda_node(CodaFid *fid, struct mount *vfsp, short type)
if (err) {
panic("coda: getnewvnode returned error %d\n", err);
}
+ err = insmntque1(vp, vfsp, NULL, NULL); /* XXX: Too early for mpsafe fs */
+ if (err != 0)
+ panic("coda: insmntque failed: error %d", err);
vp->v_data = cp;
vp->v_type = type;
cp->c_vnode = vp;
diff --git a/sys/fs/devfs/devfs_vnops.c b/sys/fs/devfs/devfs_vnops.c
index 47cc01c..dc39e67 100644
--- a/sys/fs/devfs/devfs_vnops.c
+++ b/sys/fs/devfs/devfs_vnops.c
@@ -154,6 +154,20 @@ devfs_allocv_drop_refs(int drop_dm_lock, struct devfs_mount *dmp,
return (not_found);
}
+static void
+devfs_insmntque_dtr(struct vnode *vp, void *arg)
+{
+ struct devfs_dirent *de;
+
+ de = (struct devfs_dirent *)arg;
+ mtx_lock(&devfs_de_interlock);
+ vp->v_data = NULL;
+ de->de_vnode = NULL;
+ mtx_unlock(&devfs_de_interlock);
+ vgone(vp);
+ vput(vp);
+}
+
/*
* devfs_allocv shall be entered with dmp->dm_lock held, and it drops
* it on return.
@@ -230,13 +244,16 @@ devfs_allocv(struct devfs_dirent *de, struct mount *mp, struct vnode **vpp, stru
} else {
vp->v_type = VBAD;
}
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
mtx_lock(&devfs_de_interlock);
vp->v_data = de;
de->de_vnode = vp;
mtx_unlock(&devfs_de_interlock);
- sx_xunlock(&dmp->dm_lock);
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
- sx_xlock(&dmp->dm_lock);
+ error = insmntque1(vp, mp, devfs_insmntque_dtr, de);
+ if (error != 0) {
+ (void) devfs_allocv_drop_refs(1, dmp, de);
+ return (error);
+ }
if (devfs_allocv_drop_refs(0, dmp, de)) {
vput(vp);
return (ENOENT);
diff --git a/sys/fs/fdescfs/fdesc_vnops.c b/sys/fs/fdescfs/fdesc_vnops.c
index 90c4be0..c16c0a2 100644
--- a/sys/fs/fdescfs/fdesc_vnops.c
+++ b/sys/fs/fdescfs/fdesc_vnops.c
@@ -151,6 +151,13 @@ loop:
fd->fd_type = ftype;
fd->fd_fd = -1;
fd->fd_ix = ix;
+ /* XXX: vnode should be locked here */
+ error = insmntque(*vpp, mp); /* XXX: Too early for mpsafe fs */
+ if (error != 0) {
+ free(fd, M_TEMP);
+ *vpp = NULLVP;
+ goto out;
+ }
LIST_INSERT_HEAD(fc, fd, fd_hash);
out:
diff --git a/sys/fs/hpfs/hpfs_vfsops.c b/sys/fs/hpfs/hpfs_vfsops.c
index b0a303a..bb29a83 100644
--- a/sys/fs/hpfs/hpfs_vfsops.c
+++ b/sys/fs/hpfs/hpfs_vfsops.c
@@ -445,6 +445,7 @@ hpfs_vget(
struct hpfsnode *hp;
struct buf *bp;
int error;
+ struct thread *td;
dprintf(("hpfs_vget(0x%x): ",ino));
@@ -471,7 +472,7 @@ hpfs_vget(
MALLOC(hp, struct hpfsnode *, sizeof(struct hpfsnode),
M_HPFSNO, M_WAITOK);
- error = getnewvnode("hpfs", hpmp->hpm_mp, &hpfs_vnodeops, &vp);
+ error = getnewvnode("hpfs", mp, &hpfs_vnodeops, &vp);
if (error) {
printf("hpfs_vget: can't get new vnode\n");
FREE(hp, M_HPFSNO);
@@ -498,7 +499,14 @@ hpfs_vget(
hp->h_mode = hpmp->hpm_mode;
hp->h_devvp = hpmp->hpm_devvp;
- error = vfs_hash_insert(vp, ino, flags, curthread, vpp, NULL, NULL);
+ td = curthread;
+ lockmgr(vp->v_vnlock, LK_EXCLUSIVE, NULL, td);
+ error = insmntque(vp, mp);
+ if (error != 0) {
+ free(hp, M_HPFSNO);
+ return (error);
+ }
+ error = vfs_hash_insert(vp, ino, flags, td, vpp, NULL, NULL);
if (error || *vpp != NULL)
return (error);
diff --git a/sys/fs/msdosfs/msdosfs_denode.c b/sys/fs/msdosfs/msdosfs_denode.c
index 726f7a0..3c8970d 100644
--- a/sys/fs/msdosfs/msdosfs_denode.c
+++ b/sys/fs/msdosfs/msdosfs_denode.c
@@ -107,6 +107,7 @@ deget(pmp, dirclust, diroffset, depp)
struct denode *ldep;
struct vnode *nvp, *xvp;
struct buf *bp;
+ struct thread *td;
#ifdef MSDOSFS_DEBUG
printf("deget(pmp %p, dirclust %lu, diroffset %lx, depp %p)\n",
@@ -172,7 +173,15 @@ deget(pmp, dirclust, diroffset, depp)
ldep->de_inode = inode;
fc_purge(ldep, 0); /* init the fat cache for this denode */
- error = vfs_hash_insert(nvp, inode, LK_EXCLUSIVE, curthread, &xvp,
+ td = curthread;
+ lockmgr(nvp->v_vnlock, LK_EXCLUSIVE, NULL, td);
+ error = insmntque(nvp, mntp);
+ if (error != 0) {
+ FREE(ldep, M_MSDOSFSNODE);
+ *depp = NULL;
+ return (error);
+ }
+ error = vfs_hash_insert(nvp, inode, LK_EXCLUSIVE, td, &xvp,
de_vncmpf, &inode);
if (error) {
*depp = NULL;
diff --git a/sys/fs/ntfs/ntfs_vfsops.c b/sys/fs/ntfs/ntfs_vfsops.c
index e63fc8a..26ab396 100644
--- a/sys/fs/ntfs/ntfs_vfsops.c
+++ b/sys/fs/ntfs/ntfs_vfsops.c
@@ -706,6 +706,13 @@ ntfs_vgetex(
ntfs_ntput(ip);
return (error);
}
+ /* XXX: Too early for mpsafe fs, lacks vnode lock */
+ error = insmntque(vp, ntmp->ntm_mountp);
+ if (error) {
+ ntfs_frele(fp);
+ ntfs_ntput(ip);
+ return (error);
+ }
dprintf(("ntfs_vget: vnode: %p for ntnode: %d\n", vp,ino));
fp->f_vp = vp;
diff --git a/sys/fs/nullfs/null_subr.c b/sys/fs/nullfs/null_subr.c
index 5dc7c63..66144c0 100644
--- a/sys/fs/nullfs/null_subr.c
+++ b/sys/fs/nullfs/null_subr.c
@@ -185,6 +185,18 @@ null_hashins(mp, xp)
return (NULLVP);
}
+static void
+null_insmntque_dtr(struct vnode *vp, void *xp)
+{
+ vp->v_data = NULL;
+ vp->v_vnlock = &vp->v_lock;
+ FREE(xp, M_NULLFSNODE);
+ vp->v_op = &dead_vnodeops;
+ (void) vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, curthread);
+ vgone(vp);
+ vput(vp);
+}
+
/*
* Make a new or get existing nullfs node.
* Vp is the alias vnode, lowervp is the lower vnode.
@@ -239,6 +251,9 @@ null_nodeget(mp, lowervp, vpp)
vp->v_vnlock = lowervp->v_vnlock;
if (vp->v_vnlock == NULL)
panic("null_nodeget: Passed a NULL vnlock.\n");
+ error = insmntque1(vp, mp, null_insmntque_dtr, xp);
+ if (error != 0)
+ return (error);
/*
* Atomically insert our new node into the hash or vget existing
* if someone else has beaten us to it.
diff --git a/sys/fs/nwfs/nwfs_node.c b/sys/fs/nwfs/nwfs_node.c
index dc906ef..92b7f86 100644
--- a/sys/fs/nwfs/nwfs_node.c
+++ b/sys/fs/nwfs/nwfs_node.c
@@ -174,6 +174,12 @@ rescan:
FREE(np, M_NWNODE);
return (error);
}
+ error = insmntque(vp, mp); /* XXX: Too early for mpsafe fs */
+ if (error != 0) {
+ FREE(np, M_NWNODE);
+ *vpp = NULL;
+ return (error);
+ }
vp->v_data = np;
np->n_vnode = vp;
np->n_mount = nmp;
diff --git a/sys/fs/portalfs/portal_vfsops.c b/sys/fs/portalfs/portal_vfsops.c
index db73ef0..412e81a 100644
--- a/sys/fs/portalfs/portal_vfsops.c
+++ b/sys/fs/portalfs/portal_vfsops.c
@@ -136,6 +136,13 @@ portal_mount(struct mount *mp, struct thread *td)
return (error);
}
+ error = insmntque(rvp, mp); /* XXX: Too early for mpsafe fs */
+ if (error != 0) {
+ FREE(fmp, M_PORTALFSMNT);
+ FREE(pn, M_TEMP);
+ fdrop(fp, td);
+ return (error);
+ }
rvp->v_data = pn;
rvp->v_type = VDIR;
rvp->v_vflag |= VV_ROOT;
diff --git a/sys/fs/portalfs/portal_vnops.c b/sys/fs/portalfs/portal_vnops.c
index 143d634..d6c4bc5 100644
--- a/sys/fs/portalfs/portal_vnops.c
+++ b/sys/fs/portalfs/portal_vnops.c
@@ -154,6 +154,11 @@ portal_lookup(ap)
*vpp = fvp;
vn_lock(fvp, LK_EXCLUSIVE | LK_RETRY, td);
+ error = insmntque(fvp, dvp->v_mount);
+ if (error != 0) {
+ *vpp = NULLVP;
+ return (error);
+ }
return (0);
bad:;
diff --git a/sys/fs/pseudofs/pseudofs_vncache.c b/sys/fs/pseudofs/pseudofs_vncache.c
index e6961bd..2412e32 100644
--- a/sys/fs/pseudofs/pseudofs_vncache.c
+++ b/sys/fs/pseudofs/pseudofs_vncache.c
@@ -180,6 +180,14 @@ retry:
if ((pn->pn_flags & PFS_PROCDEP) != 0)
(*vpp)->v_vflag |= VV_PROCDEP;
pvd->pvd_vnode = *vpp;
+ (*vpp)->v_vnlock->lk_flags |= LK_CANRECURSE;
+ vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY, curthread);
+ error = insmntque(*vpp, mp);
+ if (error != 0) {
+ FREE(pvd, M_PFSVNCACHE);
+ *vpp = NULLVP;
+ return (error);
+ }
mtx_lock(&pfs_vncache_mutex);
pvd->pvd_prev = NULL;
pvd->pvd_next = pfs_vncache;
@@ -187,8 +195,6 @@ retry:
pvd->pvd_next->pvd_prev = pvd;
pfs_vncache = pvd;
mtx_unlock(&pfs_vncache_mutex);
- (*vpp)->v_vnlock->lk_flags |= LK_CANRECURSE;
- vn_lock(*vpp, LK_RETRY | LK_EXCLUSIVE, curthread);
return (0);
}
diff --git a/sys/fs/smbfs/smbfs_node.c b/sys/fs/smbfs/smbfs_node.c
index 52e3565..bd3af4a 100644
--- a/sys/fs/smbfs/smbfs_node.c
+++ b/sys/fs/smbfs/smbfs_node.c
@@ -242,6 +242,11 @@ loop:
FREE(np, M_SMBNODE);
return error;
}
+ error = insmntque(vp, mp); /* XXX: Too early for mpsafe fs */
+ if (error != 0) {
+ FREE(np, M_SMBNODE);
+ return (error);
+ }
vp->v_type = fap->fa_attr & SMB_FA_DIR ? VDIR : VREG;
bzero(np, sizeof(*np));
vp->v_data = np;
diff --git a/sys/fs/udf/udf_vfsops.c b/sys/fs/udf/udf_vfsops.c
index ee58725..262e605 100644
--- a/sys/fs/udf/udf_vfsops.c
+++ b/sys/fs/udf/udf_vfsops.c
@@ -613,7 +613,13 @@ udf_vget(struct mount *mp, ino_t ino, int flags, struct vnode **vpp)
unode->udfmp = udfmp;
vp->v_data = unode;
- error = vfs_hash_insert(vp, ino, flags, curthread, vpp, NULL, NULL);
+ lockmgr(vp->v_vnlock, LK_EXCLUSIVE, NULL, td);
+ error = insmntque(vp, mp);
+ if (error != 0) {
+ uma_zfree(udf_zone_node, unode);
+ return (error);
+ }
+ error = vfs_hash_insert(vp, ino, flags, td, vpp, NULL, NULL);
if (error || *vpp != NULL)
return (error);
diff --git a/sys/fs/umapfs/umap_subr.c b/sys/fs/umapfs/umap_subr.c
index 90f19d9..40756c3 100644
--- a/sys/fs/umapfs/umap_subr.c
+++ b/sys/fs/umapfs/umap_subr.c
@@ -214,6 +214,12 @@ umap_node_alloc(mp, lowervp, vpp)
return (error);
}
vp = *vpp;
+ error = insmntque(vp, mp); /* XXX: Too early for mpsafe fs */
+ if (error != 0) {
+ FREE(xp, M_TEMP);
+ *vpp = NULLVP;
+ return (error);
+ }
vp->v_type = lowervp->v_type;
xp->umap_vnode = vp;
diff --git a/sys/fs/unionfs/union_subr.c b/sys/fs/unionfs/union_subr.c
index 09e2f6d..9af9939 100644
--- a/sys/fs/unionfs/union_subr.c
+++ b/sys/fs/unionfs/union_subr.c
@@ -243,6 +243,11 @@ unionfs_nodeget(struct mount *mp, struct vnode *uppervp,
FREE(unp, M_UNIONFSNODE);
return (error);
}
+ error = insmntque(vp, mp); /* XXX: Too early for mpsafe fs */
+ if (error != 0) {
+ FREE(unp, M_UNIONFSNODE);
+ return (error);
+ }
if (dvp != NULLVP)
vref(dvp);
if (uppervp != NULLVP)
OpenPOWER on IntegriCloud