summaryrefslogtreecommitdiff
path: root/sys/fs/smbfs/smbfs_node.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/fs/smbfs/smbfs_node.c')
-rw-r--r--sys/fs/smbfs/smbfs_node.c17
1 files changed, 17 insertions, 0 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);
}
/*