From ce589ae2a75beb3d7632d3826a944801de7ea2c9 Mon Sep 17 00:00:00 2001 From: Davide Italiano Date: Sat, 9 Mar 2013 13:25:45 +0000 Subject: [PATCH] smbfs_lookup() in the DOTDOT case operates on dvp->n_parent without proper locking. This doesn't prevent in any case reclaim of the vnode. Avoid this not going over-the-wire in this case and relying on subsequent smbfs_getattr() call to restore consistency. While I'm here, change a couple of SMBVDEBUG() in MPASS(). sbmfs_smb_lookup() doesn't and shouldn't know about '.' and '..' Reported by: pho's stress2 suite --- sys/fs/smbfs/smbfs_smb.c | 12 +++--------- sys/fs/smbfs/smbfs_vnops.c | 19 +++++++++++++------ 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/sys/fs/smbfs/smbfs_smb.c b/sys/fs/smbfs/smbfs_smb.c index 05d482ef6e8..ec4a49d899a 100644 --- a/sys/fs/smbfs/smbfs_smb.c +++ b/sys/fs/smbfs/smbfs_smb.c @@ -1455,15 +1455,9 @@ smbfs_smb_lookup(struct smbnode *dnp, const char *name, int nmlen, fap->fa_ino = 2; return 0; } - if (nmlen == 1 && name[0] == '.') { - error = smbfs_smb_lookup(dnp, NULL, 0, fap, scred); - return error; - } else if (nmlen == 2 && name[0] == '.' && name[1] == '.') { - error = smbfs_smb_lookup(VTOSMB(dnp->n_parent), NULL, 0, fap, - scred); - printf("%s: knows NOTHING about '..'\n", __func__); - return error; - } + MPASS(!(nmlen == 2 && name[0] == '.' && name[1] == '.')); + MPASS(!(nmlen == 1 && name[0] == '.')); + ASSERT_VOP_ELOCKED(dnp->n_vnode, "smbfs_smb_lookup"); error = smbfs_findopen(dnp, name, nmlen, SMB_FA_SYSTEM | SMB_FA_HIDDEN | SMB_FA_DIR, scred, &ctx); if (error) diff --git a/sys/fs/smbfs/smbfs_vnops.c b/sys/fs/smbfs/smbfs_vnops.c index 6285dfdc47e..6ceed9c10eb 100644 --- a/sys/fs/smbfs/smbfs_vnops.c +++ b/sys/fs/smbfs/smbfs_vnops.c @@ -1204,13 +1204,20 @@ smbfs_lookup(ap) smb_makescred(scred, td, cnp->cn_cred); fap = &fattr; if (flags & ISDOTDOT) { - error = smbfs_smb_lookup(VTOSMB(dnp->n_parent), NULL, 0, fap, - scred); - SMBVDEBUG("result of dotdot lookup: %d\n", error); - } else { - fap = &fattr; + /* + * In the DOTDOT case, don't go over-the-wire + * in order to request attributes. We already + * know it's a directory and subsequent call to + * smbfs_getattr() will restore consistency. + * + */ + SMBVDEBUG("smbfs_smb_lookup: dotdot\n"); + } else if (isdot) { + error = smbfs_smb_lookup(dnp, NULL, 0, fap, scred); + SMBVDEBUG("result of smbfs_smb_lookup: %d\n", error); + } + else { error = smbfs_smb_lookup(dnp, name, nmlen, fap, scred); -/* if (cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.')*/ SMBVDEBUG("result of smbfs_smb_lookup: %d\n", error); } if (error && error != ENOENT)