From patchwork Tue Jan 15 19:01:31 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Layton X-Patchwork-Id: 1980301 Return-Path: X-Original-To: patchwork-cifs-client@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork2.kernel.org (Postfix) with ESMTP id 223C2DF2F2 for ; Tue, 15 Jan 2013 19:01:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757414Ab3AOTBk (ORCPT ); Tue, 15 Jan 2013 14:01:40 -0500 Received: from mail-qc0-f177.google.com ([209.85.216.177]:49066 "EHLO mail-qc0-f177.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757376Ab3AOTBi (ORCPT ); Tue, 15 Jan 2013 14:01:38 -0500 Received: by mail-qc0-f177.google.com with SMTP id u28so294798qcs.22 for ; Tue, 15 Jan 2013 11:01:38 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-received:sender:from:to:cc:subject:date:message-id:x-mailer :x-gm-message-state; bh=pt7xkd4OwznPeWGqys95AithSg2TmDuwp62HkWLtWbU=; b=mXAGBfOq0Ezz8e11WYa/H5McCtzY/kC7SZEmyDd3KhhjoYmcPYv8qg7anoe4+TAQDh YX5rATTZR+Yt10jbizAeg6xXX9E+ZlPDOdnfFY0xgTSeLqIpDjdtr4LNijHGAHv/whg7 Yrkm3XC9s7kPmWyCi/qkB+itybKHkvwPubr+T1YQPbaJCoW3bV/XUgagwFfnjgmBHjBT vr0rwjxh1Sj6tpuest6oPESztBg6F/Cp8WR4Qw6nrcfIZCSBeA3cgAo6FsB4bCc7+41Z SUDpIPbjqyPczYew6xvF9Qtnbk5pTTc5UmvKx7WZrJlCMlLIaovDzj5wuoJWQ5/43FfB xqYg== X-Received: by 10.49.48.43 with SMTP id i11mr91690117qen.3.1358276497623; Tue, 15 Jan 2013 11:01:37 -0800 (PST) Received: from salusa.poochiereds.net (cpe-107-015-113-143.nc.res.rr.com. [107.15.113.143]) by mx.google.com with ESMTPS id hn9sm12420431qab.8.2013.01.15.11.01.34 (version=TLSv1 cipher=RC4-SHA bits=128/128); Tue, 15 Jan 2013 11:01:35 -0800 (PST) From: Jeff Layton To: smfrench@gmail.com Cc: linux-cifs@vger.kernel.org Subject: [PATCH RFC] cifs: revalidate directories instiantiated via FIND_* in order to handle DFS referrals Date: Tue, 15 Jan 2013 14:01:31 -0500 Message-Id: <1358276491-4835-1-git-send-email-jlayton@redhat.com> X-Mailer: git-send-email 1.7.11.7 X-Gm-Message-State: ALoCoQl0/vT2dxxylEG2d1kgCf82AUw4tGlibhdOjpTRC0gPpCi6m0vgZTMEAAwDOBGSL82s31Oa Sender: linux-cifs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-cifs@vger.kernel.org We've had a long-standing problem with DFS referral points. CIFS servers generally try to make them look like directories in FIND_FIRST/NEXT responses. When you go to try to do a FIND_FIRST on them though, the server will then (correctly) return STATUS_PATH_NOT_COVERED. Mostly this manifests as spurious EREMOTE errors back to userland. This patch attempts to fix this by marking directories that are discovered via FIND_FIRST/NEXT for revaldiation. When the lookup code runs across them again, we'll reissue a QPathInfo against them and that will make it chase the referral properly. There is some performance penalty involved here and no I haven't measured it -- it'll be highly dependent upon the workload and contents of the mounted share. To try and mitigate that though, the code only marks the inode for revalidation when it's possible to run across a DFS referral. i.e.: when the kernel has DFS support built in and the share is "in DFS". Signed-off-by: Jeff Layton --- fs/cifs/readdir.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index cdd6ff4..5fc9b4a 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -128,6 +128,22 @@ out: dput(dentry); } +/* + * Is it possible that this directory might turn out to be a DFS referral + * once we go to try and use it? + */ +static bool +cifs_dfs_is_possible(struct cifs_sb_info *cifs_sb) +{ +#ifdef CONFIG_CIFS_DFS_UPCALL + struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); + + if (tcon->Flags & SMB_SHARE_IS_IN_DFS) + return true; +#endif + return false; +} + static void cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb) { @@ -137,6 +153,14 @@ cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb) if (fattr->cf_cifsattrs & ATTR_DIRECTORY) { fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode; fattr->cf_dtype = DT_DIR; + /* + * CIFS servers generally make DFS referrals look like + * directories in FIND_* responses. Since there's no way to + * tell the difference, we must revalidate directory inodes + * before trying to use them. + */ + if (cifs_dfs_is_possible(cifs_sb)) + fattr->cf_flags |= CIFS_FATTR_NEED_REVAL; } else { fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode; fattr->cf_dtype = DT_REG;