summaryrefslogtreecommitdiffstats
path: root/sys/fs/tmpfs/tmpfs_vnops.c
diff options
context:
space:
mode:
authordelphij <delphij@FreeBSD.org>2007-08-10 05:24:49 +0000
committerdelphij <delphij@FreeBSD.org>2007-08-10 05:24:49 +0000
commit1e2d5f7f4ae5c6c278371f5d357ee949df152bcc (patch)
tree3c511dcb1596e97903bfbb7bc035dbea359cc6ea /sys/fs/tmpfs/tmpfs_vnops.c
parentb6abc7d242e6b81169bb513bdf42663b15f6cc98 (diff)
downloadFreeBSD-src-1e2d5f7f4ae5c6c278371f5d357ee949df152bcc.zip
FreeBSD-src-1e2d5f7f4ae5c6c278371f5d357ee949df152bcc.tar.gz
MFp4:
- Respect cnflag and don't lock vnode always as LK_EXCLUSIVE [1] - Properly lock around tn_vnode to avoid NULL deference - Be more careful handling vnodes (*) (*) This is a WIP [1] by pjd via howardsu Thanks kib@ for his valuable VFS related comments. Tested with: fsx, fstest, tmpfs regression test set Found by: pho's stress2 suite Approved by: re (tmpfs blanket)
Diffstat (limited to 'sys/fs/tmpfs/tmpfs_vnops.c')
-rw-r--r--sys/fs/tmpfs/tmpfs_vnops.c45
1 files changed, 33 insertions, 12 deletions
diff --git a/sys/fs/tmpfs/tmpfs_vnops.c b/sys/fs/tmpfs/tmpfs_vnops.c
index 514aeb7..d43e267 100644
--- a/sys/fs/tmpfs/tmpfs_vnops.c
+++ b/sys/fs/tmpfs/tmpfs_vnops.c
@@ -95,12 +95,20 @@ tmpfs_lookup(struct vop_cachedlookup_args *v)
!(cnp->cn_flags & ISDOTDOT)));
if (cnp->cn_flags & ISDOTDOT) {
- VOP_UNLOCK(dvp, 0, td);
+ int ltype = 0;
+ ltype = VOP_ISLOCKED(dvp, td);
+ vholdl(dvp);
+ VOP_UNLOCK(dvp, 0, td);
/* Allocate a new vnode on the matching entry. */
- error = tmpfs_alloc_vp(dvp->v_mount, dnode->tn_dir.tn_parent, vpp, td);
+ error = tmpfs_alloc_vp(dvp->v_mount, dnode->tn_dir.tn_parent,
+ cnp->cn_lkflags, vpp, td);
- vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, td);
+ vn_lock(dvp, ltype | LK_RETRY, td);
+ if (ltype & LK_INTERLOCK)
+ vdropl(dvp);
+ else
+ vdrop(dvp);
dnode->tn_dir.tn_parent->tn_lookup_dirent = NULL;
} else if (cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') {
@@ -160,7 +168,8 @@ tmpfs_lookup(struct vop_cachedlookup_args *v)
goto out;
/* Allocate a new vnode on the matching entry. */
- error = tmpfs_alloc_vp(dvp->v_mount, tnode, vpp, td);
+ error = tmpfs_alloc_vp(dvp->v_mount, tnode,
+ cnp->cn_lkflags, vpp, td);
if (error != 0)
goto out;
@@ -174,10 +183,10 @@ tmpfs_lookup(struct vop_cachedlookup_args *v)
}
tnode->tn_lookup_dirent = de;
cnp->cn_flags |= SAVENAME;
+ } else {
+ error = tmpfs_alloc_vp(dvp->v_mount, tnode,
+ cnp->cn_lkflags, vpp, td);
}
- else
- error = tmpfs_alloc_vp(dvp->v_mount, tnode, vpp, td);
-
}
}
@@ -478,7 +487,7 @@ lookupvpg:
vm_page_wakeup(m);
VM_OBJECT_UNLOCK(vobj);
return (error);
- }
+ }
VM_OBJECT_UNLOCK(vobj);
nocache:
VM_OBJECT_LOCK(tobj);
@@ -886,13 +895,13 @@ tmpfs_rename(struct vop_rename_args *v)
struct vnode *tdvp = v->a_tdvp;
struct vnode *tvp = v->a_tvp;
struct componentname *tcnp = v->a_tcnp;
- struct tmpfs_node *tnode = 0; /* pacify gcc */
char *newname;
int error;
struct tmpfs_dirent *de;
struct tmpfs_node *fdnode;
struct tmpfs_node *fnode;
+ struct tmpfs_node *tnode;
struct tmpfs_node *tdnode;
MPASS(VOP_ISLOCKED(tdvp, tcnp->cn_thread));
@@ -902,6 +911,7 @@ tmpfs_rename(struct vop_rename_args *v)
fdnode = VP_TO_TMPFS_DIR(fdvp);
fnode = VP_TO_TMPFS_NODE(fvp);
+ tnode = (tvp == NULL) ? NULL : VP_TO_TMPFS_NODE(tvp);
de = fnode->tn_lookup_dirent;
/* Disallow cross-device renames.
@@ -934,7 +944,7 @@ tmpfs_rename(struct vop_rename_args *v)
* Kern_rename gurantees the destination to be a directory
* if the source is one. */
if (tvp != NULL) {
- tnode = VP_TO_TMPFS_NODE(tvp);
+ MPASS(tnode != NULL);
if ((tnode->tn_flags & (NOUNLINK | IMMUTABLE | APPEND)) ||
(tdnode->tn_flags & (APPEND | IMMUTABLE))) {
@@ -942,9 +952,20 @@ tmpfs_rename(struct vop_rename_args *v)
goto out;
}
- if ((de->td_node->tn_type == VDIR) && (tnode->tn_size > 0)) {
- error = ENOTEMPTY;
+ if (fnode->tn_type == VDIR && tnode->tn_type == VDIR) {
+ if (tnode->tn_size > 0) {
+ error = ENOTEMPTY;
+ goto out;
+ }
+ } else if (fnode->tn_type == VDIR && tnode->tn_type != VDIR) {
+ error = ENOTDIR;
goto out;
+ } else if (fnode->tn_type != VDIR && tnode->tn_type == VDIR) {
+ error = EISDIR;
+ goto out;
+ } else {
+ MPASS(fnode->tn_type != VDIR &&
+ tnode->tn_type != VDIR);
}
}
OpenPOWER on IntegriCloud