diff options
| author | Tim J. Robbins <tjr@FreeBSD.org> | 2004-02-10 05:53:02 +0000 |
|---|---|---|
| committer | Tim J. Robbins <tjr@FreeBSD.org> | 2004-02-10 05:53:02 +0000 |
| commit | b4484bf0310023f41d70c74bf7b51b7092737223 (patch) | |
| tree | ba73a74265f497f6e197c646b862844380ff2f4b | |
| parent | b257d4a02509714ec04cef872690072ebe8ece7f (diff) | |
Notes
| -rw-r--r-- | sys/fs/smbfs/smbfs_node.c | 17 | ||||
| -rw-r--r-- | sys/fs/smbfs/smbfs_node.h | 1 | ||||
| -rw-r--r-- | sys/fs/smbfs/smbfs_vnops.c | 25 |
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); } |
