summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim J. Robbins <tjr@FreeBSD.org>2004-02-10 05:53:02 +0000
committerTim J. Robbins <tjr@FreeBSD.org>2004-02-10 05:53:02 +0000
commitb4484bf0310023f41d70c74bf7b51b7092737223 (patch)
treeba73a74265f497f6e197c646b862844380ff2f4b
parentb257d4a02509714ec04cef872690072ebe8ece7f (diff)
Notes
-rw-r--r--sys/fs/smbfs/smbfs_node.c17
-rw-r--r--sys/fs/smbfs/smbfs_node.h1
-rw-r--r--sys/fs/smbfs/smbfs_vnops.c25
3 files changed, 42 insertions, 1 deletions
diff --git a/sys/fs/smbfs/smbfs_node.c b/sys/fs/smbfs/smbfs_node.c
index dcc0adab72f4..830e1e504da8 100644
--- a/sys/fs/smbfs/smbfs_node.c
+++ b/sys/fs/smbfs/smbfs_node.c
@@ -164,6 +164,7 @@ static int
smbfs_node_alloc(struct mount *mp, struct vnode *dvp,
const char *name, int nmlen, struct smbfattr *fap, struct vnode **vpp)
{
+ struct vattr vattr;
struct thread *td = curthread; /* XXX */
struct smbmount *smp = VFSTOSMBFS(mp);
struct smbnode_hashhead *nhpp;
@@ -208,6 +209,20 @@ loop:
smbfs_hash_unlock(smp, td);
if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td) != 0)
goto retry;
+ /* Force cached attributes to be refreshed if stale. */
+ (void)VOP_GETATTR(vp, &vattr, td->td_ucred, td);
+ /*
+ * If the file type on the server is inconsistent with
+ * what it was when we created the vnode, kill the
+ * bogus vnode now and fall through to the code below
+ * to create a new one with the right type.
+ */
+ if ((vp->v_type == VDIR && (np->n_dosattr & SMB_FA_DIR) == 0) ||
+ (vp->v_type == VREG && (np->n_dosattr & SMB_FA_DIR) != 0)) {
+ vput(vp);
+ vgone(vp);
+ break;
+ }
*vpp = vp;
return 0;
}
@@ -361,6 +376,8 @@ smbfs_inactive(ap)
smbfs_attr_cacheremove(vp);
}
VOP_UNLOCK(vp, 0, td);
+ if (np->n_flag & NGONE)
+ vrecycle(vp, NULL, td);
return (0);
}
/*
diff --git a/sys/fs/smbfs/smbfs_node.h b/sys/fs/smbfs/smbfs_node.h
index 884831c87453..7a8d545d1ef4 100644
--- a/sys/fs/smbfs/smbfs_node.h
+++ b/sys/fs/smbfs/smbfs_node.h
@@ -44,6 +44,7 @@
#define NREFPARENT 0x0010 /* node holds parent from recycling */
#define NFLUSHWIRE 0x1000 /* pending flush request */
#define NOPEN 0x2000 /* file is open */
+#define NGONE 0x4000 /* file has been removed/renamed */
struct smbfs_fctx;
diff --git a/sys/fs/smbfs/smbfs_vnops.c b/sys/fs/smbfs/smbfs_vnops.c
index e9fc5a8cfeed..c6e031f4858c 100644
--- a/sys/fs/smbfs/smbfs_vnops.c
+++ b/sys/fs/smbfs/smbfs_vnops.c
@@ -538,6 +538,8 @@ smbfs_remove(ap)
return EPERM;
smb_makescred(&scred, cnp->cn_thread, cnp->cn_cred);
error = smbfs_smb_delete(np, &scred);
+ if (error == 0)
+ np->n_flag |= NGONE;
cache_purge(vp);
return error;
}
@@ -604,6 +606,7 @@ smbfs_rename(ap)
error = smbfs_smb_delete(VTOSMB(tvp), &scred);
if (error)
goto out_cacherem;
+ VTOSMB(fvp)->n_flag |= NGONE;
}
error = smbfs_smb_rename(VTOSMB(fvp), VTOSMB(tdvp),
tcnp->cn_nameptr, tcnp->cn_namelen, &scred);
@@ -739,6 +742,8 @@ smbfs_rmdir(ap)
smb_makescred(&scred, cnp->cn_thread, cnp->cn_cred);
error = smbfs_smb_rmdir(np, &scred);
+ if (error == 0)
+ np->n_flag |= NGONE;
dnp->n_flag |= NMODIFIED;
smbfs_attr_cacheremove(dvp);
/* cache_purge(dvp);*/
@@ -1096,6 +1101,7 @@ smbfs_lookup(ap)
int nameiop = cnp->cn_nameiop;
int nmlen = cnp->cn_namelen;
int lockparent, wantparent, error, islastcn, isdot;
+ int killit;
SMBVDEBUG("\n");
cnp->cn_flags &= ~PDIRUNLOCK;
@@ -1165,8 +1171,23 @@ smbfs_lookup(ap)
}
}
if (!error) {
+ killit = 0;
if (vpid == vp->v_id) {
- if (!VOP_GETATTR(vp, &vattr, cnp->cn_cred, td)
+ error = VOP_GETATTR(vp, &vattr, cnp->cn_cred, td);
+ /*
+ * If the file type on the server is inconsistent
+ * with what it was when we created the vnode,
+ * kill the bogus vnode now and fall through to
+ * the code below to create a new one with the
+ * right type.
+ */
+ if (error == 0 &&
+ ((vp->v_type == VDIR &&
+ (VTOSMB(vp)->n_dosattr & SMB_FA_DIR) == 0) ||
+ (vp->v_type == VREG &&
+ (VTOSMB(vp)->n_dosattr & SMB_FA_DIR) != 0)))
+ killit = 1;
+ else if (error == 0
/* && vattr.va_ctime.tv_sec == VTOSMB(vp)->n_ctime*/) {
if (nameiop != LOOKUP && islastcn)
cnp->cn_flags |= SAVENAME;
@@ -1176,6 +1197,8 @@ smbfs_lookup(ap)
cache_purge(vp);
}
vput(vp);
+ if (killit)
+ vgone(vp);
if (lockparent && dvp != vp && islastcn)
VOP_UNLOCK(dvp, 0, td);
}