From patchwork Wed May 25 19:12:29 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pavel Shilovsky X-Patchwork-Id: 817032 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p4PJDkkX022234 for ; Wed, 25 May 2011 19:13:49 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753931Ab1EYTNt (ORCPT ); Wed, 25 May 2011 15:13:49 -0400 Received: from mail-fx0-f46.google.com ([209.85.161.46]:61070 "EHLO mail-fx0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751605Ab1EYTNt (ORCPT ); Wed, 25 May 2011 15:13:49 -0400 Received: by mail-fx0-f46.google.com with SMTP id 17so39001fxm.19 for ; Wed, 25 May 2011 12:13:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:sender:from:to:subject:date:message-id:x-mailer :in-reply-to:references; bh=w0ph0HrEUFjWMUQKnG/j55eWakWF2jusvy/2C/U7Ylk=; b=bzIBC56fOvhBOEwKS1j+aJSx0qKfJG6uZJcJd57h0L06LycbT1YTfV2sdEXWogfopL ZG5FiLz8i24UXUBe4Kg2w4D59VjqGTMdU7NYWuZgHe0z4VZG8B9mrVuEx8z44jWU2chb ZEHux6ENX532NGr+bjUkOd2ifdmMKTllnvivY= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=sender:from:to:subject:date:message-id:x-mailer:in-reply-to :references; b=j2INrIyhCQHYJ2RD6WW13828zZt33z1OQqmufPgVMScTQ/cjWcQvP4uKsKUPAf0GFP 4qvJJf2Dh7ZrN1nAKUA+EXony1wS0kJFGgv7tgKRtL1kpHxHk9eN2OWBBOluibrDZTv+ gi0euzTp6DOZQbbySCMITfeGGDIYgcL5J9tXk= Received: by 10.223.59.146 with SMTP id l18mr332221fah.58.1306350827550; Wed, 25 May 2011 12:13:47 -0700 (PDT) Received: from localhost.localdomain (PPPoE-78-29-101-206.san.ru [78.29.101.206]) by mx.google.com with ESMTPS id f2sm337511fah.45.2011.05.25.12.13.43 (version=TLSv1/SSLv3 cipher=OTHER); Wed, 25 May 2011 12:13:44 -0700 (PDT) From: Pavel Shilovsky To: linux-cifs@vger.kernel.org Subject: [v3 4/4] CIFS: Migrate to shared superblock model Date: Wed, 25 May 2011 23:12:29 +0400 Message-Id: <1306350749-28975-2-git-send-email-piastry@etersoft.ru> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1306350749-28975-1-git-send-email-piastry@etersoft.ru> References: <1306350749-28975-1-git-send-email-piastry@etersoft.ru> Sender: linux-cifs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-cifs@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Wed, 25 May 2011 19:13:49 +0000 (UTC) Add cifs_match_super to use in sget to share superblock between mounts that have the same //server/sharename, credentials and mount options. It helps us to improve performance on work with future SMB2.1 leases. Reviewed-by: Jeff Layton Signed-off-by: Pavel Shilovsky --- fs/cifs/cifsfs.c | 24 ++++++++++++-- fs/cifs/cifsglob.h | 19 +++++++++++ fs/cifs/connect.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 126 insertions(+), 4 deletions(-) diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index b7dbb26..7200f1a 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -630,6 +630,7 @@ cifs_do_mount(struct file_system_type *fs_type, struct super_block *sb; struct cifs_sb_info *cifs_sb; struct smb_vol *volume_info; + struct cifs_mnt_data mnt_data; struct dentry *root; cFYI(1, "Devname: %s flags: %d ", dev_name, flags); @@ -646,13 +647,22 @@ cifs_do_mount(struct file_system_type *fs_type, cifs_setup_cifs_sb(volume_info, cifs_sb); - sb = sget(fs_type, NULL, set_anon_super, NULL); + mnt_data.vol = volume_info; + mnt_data.cifs_sb = cifs_sb; + mnt_data.flags = flags; + + sb = sget(fs_type, cifs_match_super, set_anon_super, &mnt_data); if (IS_ERR(sb)) { kfree(cifs_sb); root = ERR_CAST(sb); goto out; } + if (sb->s_fs_info) { + cFYI(1, "Use existing superblock"); + goto out_shared; + } + /* * Copy mount params for use in submounts. Better to do * the copy here and deal with the error before cleanup gets @@ -679,15 +689,21 @@ cifs_do_mount(struct file_system_type *fs_type, sb->s_flags |= MS_ACTIVE; root = cifs_get_root(volume_info, sb); - if (root == NULL) { - kfree(copied_data); + if (root == NULL) goto err_out; - } + cFYI(1, "dentry root is: %p", root); out: cifs_cleanup_volume_info(&volume_info); return root; +out_shared: + root = cifs_get_root(volume_info, sb); + if (root) + cFYI(1, "dentry root is: %p", root); + cifs_cleanup_volume_info(&volume_info); + return root; + err_out: kfree(cifs_sb->mountdata); unload_nls(cifs_sb->local_nls); diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index f57387a..7f90488 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -210,6 +210,25 @@ struct smb_vol { struct nls_table *local_nls; }; +#define CIFS_MOUNT_MASK (CIFS_MOUNT_NO_PERM | CIFS_MOUNT_SET_UID | \ + CIFS_MOUNT_SERVER_INUM | CIFS_MOUNT_DIRECT_IO | \ + CIFS_MOUNT_NO_XATTR | CIFS_MOUNT_MAP_SPECIAL_CHR | \ + CIFS_MOUNT_UNX_EMUL | CIFS_MOUNT_NO_BRL | \ + CIFS_MOUNT_CIFS_ACL | CIFS_MOUNT_OVERR_UID | \ + CIFS_MOUNT_OVERR_GID | CIFS_MOUNT_DYNPERM | \ + CIFS_MOUNT_NOPOSIXBRL | CIFS_MOUNT_NOSSYNC | \ + CIFS_MOUNT_FSCACHE | CIFS_MOUNT_MF_SYMLINKS | \ + CIFS_MOUNT_MULTIUSER | CIFS_MOUNT_STRICT_IO) + +#define CIFS_MS_MASK (MS_RDONLY | MS_MANDLOCK | MS_NOEXEC | MS_NOSUID | \ + MS_NODEV | MS_SYNCHRONOUS) + +struct cifs_mnt_data { + struct cifs_sb_info *cifs_sb; + struct smb_vol *vol; + int flags; +}; + struct TCP_Server_Info { struct list_head tcp_ses_list; struct list_head smb_ses_list; diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 6d567b6..4b4c2fb 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -2146,6 +2146,93 @@ cifs_put_tlink(struct tcon_link *tlink) return; } +static inline struct tcon_link * +cifs_sb_master_tlink(struct cifs_sb_info *cifs_sb); + +static int +compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data) +{ + struct cifs_sb_info *old = CIFS_SB(sb); + struct cifs_sb_info *new = mnt_data->cifs_sb; + + if ((sb->s_flags & CIFS_MS_MASK) != (mnt_data->flags & CIFS_MS_MASK)) + return 0; + + if ((old->mnt_cifs_flags & CIFS_MOUNT_MASK) != + (new->mnt_cifs_flags & CIFS_MOUNT_MASK)) + return 0; + + if (old->rsize != new->rsize || old->wsize != new->wsize) + return 0; + + if (old->mnt_uid != new->mnt_uid || old->mnt_gid != new->mnt_gid) + return 0; + + if (old->mnt_file_mode != new->mnt_file_mode || + old->mnt_dir_mode != new->mnt_dir_mode) + return 0; + + if (strcmp(old->local_nls->charset, new->local_nls->charset)) + return 0; + + if (old->actimeo != new->actimeo) + return 0; + + return 1; +} + +int +cifs_match_super(struct super_block *sb, void *data) +{ + struct cifs_mnt_data *mnt_data = (struct cifs_mnt_data *)data; + struct smb_vol *volume_info; + struct cifs_sb_info *cifs_sb; + struct TCP_Server_Info *tcp_srv; + struct cifsSesInfo *ses; + struct cifsTconInfo *tcon; + struct tcon_link *tlink; + struct sockaddr_storage addr; + int rc = 0; + + memset(&addr, 0, sizeof(struct sockaddr_storage)); + + spin_lock(&cifs_tcp_ses_lock); + cifs_sb = CIFS_SB(sb); + tlink = cifs_get_tlink(cifs_sb_master_tlink(cifs_sb)); + if (IS_ERR(tlink)) { + spin_unlock(&cifs_tcp_ses_lock); + return rc; + } + tcon = tlink_tcon(tlink); + ses = tcon->ses; + tcp_srv = ses->server; + + volume_info = mnt_data->vol; + + if (!volume_info->UNCip || !volume_info->UNC) + goto out; + + rc = cifs_fill_sockaddr((struct sockaddr *)&addr, + volume_info->UNCip, + strlen(volume_info->UNCip), + volume_info->port); + if (!rc) + goto out; + + if (!match_server(tcp_srv, (struct sockaddr *)&addr, volume_info) || + !match_session(ses, volume_info) || + !match_tcon(tcon, volume_info->UNC)) { + rc = 0; + goto out; + } + + rc = compare_mount_options(sb, mnt_data); +out: + cifs_put_tlink(tlink); + spin_unlock(&cifs_tcp_ses_lock); + return rc; +} + int get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, const char *old_path, const struct nls_table *nls_codepage, unsigned int *pnum_referrals,