diff options
Diffstat (limited to 'sys/fs/smbfs/smbfs_node.c')
| -rw-r--r-- | sys/fs/smbfs/smbfs_node.c | 17 |
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); } /* |
