summaryrefslogtreecommitdiffstats
path: root/sys/fs/smbfs/smbfs_vnops.c
diff options
context:
space:
mode:
authortjr <tjr@FreeBSD.org>2004-02-10 05:53:02 +0000
committertjr <tjr@FreeBSD.org>2004-02-10 05:53:02 +0000
commit40b810244fbce5f951ac0c46dbf1181adb21a0b7 (patch)
treeba73a74265f497f6e197c646b862844380ff2f4b /sys/fs/smbfs/smbfs_vnops.c
parent72c7aa83c9ff6fcca227bada024389ad5063cce1 (diff)
downloadFreeBSD-src-40b810244fbce5f951ac0c46dbf1181adb21a0b7.zip
FreeBSD-src-40b810244fbce5f951ac0c46dbf1181adb21a0b7.tar.gz
Fixes problems that occurred when a file was removed and a directory
created with the same name, and vice versa: - Immediately recycle vnodes of files & directories that have been deleted or renamed. - When looking an entry in the VFS name cache or smbfs's private cache, make sure the vnode type is consistent with the type of file the server thinks it is, and re-create the vnode if it isn't. The alternative to this is to recycle vnodes unconditionally when their use count drops to 0, but this would make all the caching we do mostly useless. PR: 62342 MFC after: 2 weeks
Diffstat (limited to 'sys/fs/smbfs/smbfs_vnops.c')
-rw-r--r--sys/fs/smbfs/smbfs_vnops.c25
1 files changed, 24 insertions, 1 deletions
diff --git a/sys/fs/smbfs/smbfs_vnops.c b/sys/fs/smbfs/smbfs_vnops.c
index e9fc5a8..c6e031f 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);
}
OpenPOWER on IntegriCloud