From patchwork Mon Aug 9 17:07:14 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Metzmacher X-Patchwork-Id: 118431 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.4/8.14.3) with ESMTP id o79H7HtE004237 for ; Mon, 9 Aug 2010 17:07:36 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757197Ab0HIRHg (ORCPT ); Mon, 9 Aug 2010 13:07:36 -0400 Received: from mo-p05-ob.rzone.de ([81.169.146.180]:64448 "EHLO mo-p05-ob.rzone.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757190Ab0HIRHf (ORCPT ); Mon, 9 Aug 2010 13:07:35 -0400 X-RZG-AUTH: :IXQkeEW8Yfo/5haL0ckzWIsAYh739YBunhBBa3aCCCbZv/tK/4QIFiQT X-RZG-CLASS-ID: mo05 Received: from localhost.localdomain (xdsl-87-79-84-185.netcologne.de [87.79.84.185]) by post.strato.de (mrclete mo45) (RZmta 23.4) with (EDH-RSA-DES-CBC3-SHA encrypted) ESMTP id 600304m79Go2DU ; Mon, 9 Aug 2010 19:07:33 +0200 (MEST) From: Stefan Metzmacher To: smfrench@gmail.com Cc: linux-cifs@vger.kernel.org, Stefan Metzmacher Subject: [PATCH 6/7] cifs: use Minshall+French symlink functions Date: Mon, 9 Aug 2010 19:07:14 +0200 Message-Id: <1281373635-16202-7-git-send-email-metze@samba.org> X-Mailer: git-send-email 1.7.0.4 In-Reply-To: <1281373635-16202-6-git-send-email-metze@samba.org> References: <1281373635-16202-1-git-send-email-metze@samba.org> <1281373635-16202-2-git-send-email-metze@samba.org> <1281373635-16202-3-git-send-email-metze@samba.org> <1281373635-16202-4-git-send-email-metze@samba.org> <1281373635-16202-5-git-send-email-metze@samba.org> <1281373635-16202-6-git-send-email-metze@samba.org> 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.3 (demeter.kernel.org [140.211.167.41]); Mon, 09 Aug 2010 17:07:36 +0000 (UTC) diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h index 9e77145..7fde529 100644 --- a/fs/cifs/cifs_fs_sb.h +++ b/fs/cifs/cifs_fs_sb.h @@ -36,6 +36,7 @@ #define CIFS_MOUNT_NOPOSIXBRL 0x2000 /* mandatory not posix byte range lock */ #define CIFS_MOUNT_NOSSYNC 0x4000 /* don't do slow SMBflush on every sync*/ #define CIFS_MOUNT_FSCACHE 0x8000 /* local caching enabled */ +#define CIFS_MOUNT_MF_SYMLINKS 0x10000 /* Minshall+French Symlinks enabled */ struct cifs_sb_info { struct cifsTconInfo *tcon; /* primary mount */ diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index dc4c47a..cf0970b 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -332,6 +332,13 @@ int cifs_get_inode_info_unix(struct inode **pinode, return rc; } + /* check for Minshall+French symlinks */ + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) { + int tmprc = CIFSCheckMFSymlink(&fattr, full_path, cifs_sb, xid); + if (tmprc) + cFYI(1, "CIFSCheckMFSymlink: %d", tmprc); + } + if (*pinode == NULL) { /* get new inode */ cifs_fill_uniqueid(sb, &fattr); @@ -661,6 +668,13 @@ int cifs_get_inode_info(struct inode **pinode, if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) cifs_sfu_mode(&fattr, full_path, cifs_sb, xid); + /* check for Minshall+French symlinks */ + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) { + tmprc = CIFSCheckMFSymlink(&fattr, full_path, cifs_sb, xid); + if (tmprc) + cFYI(1, "CIFSCheckMFSymlink: %d", tmprc); + } + if (!*pinode) { *pinode = cifs_iget(sb, &fattr); if (!*pinode) diff --git a/fs/cifs/link.c b/fs/cifs/link.c index 1b2a8c9..cbf7b11 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c @@ -407,7 +407,8 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd) * but there doesn't seem to be any harm in allowing the client to * read them. */ - if (!(tcon->ses->capabilities & CAP_UNIX)) { + if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) + && !(tcon->ses->capabilities & CAP_UNIX)) { rc = -EACCES; goto out; } @@ -418,8 +419,21 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd) cFYI(1, "Full path: %s inode = 0x%p", full_path, inode); - rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, &target_path, - cifs_sb->local_nls); + rc = -EACCES; + /* + * First try Minshall+French Symlinks, if configured + * and fallback to UNIX Extensions Symlinks. + */ + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) + rc = CIFSQueryMFSymLink(xid, tcon, full_path, &target_path, + cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); + + if ((rc != 0) && (tcon->ses->capabilities & CAP_UNIX)) + rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, &target_path, + cifs_sb->local_nls); + kfree(full_path); out: if (rc != 0) { @@ -459,7 +473,12 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname) cFYI(1, "symname is %s", symname); /* BB what if DFS and this volume is on different share? BB */ - if (pTcon->unix_ext) + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) + rc = CIFSCreateMFSymLink(xid, pTcon, full_path, symname, + cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); + else if (pTcon->unix_ext) rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname, cifs_sb->local_nls); /* else diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index d5e591f..6a8b417 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -738,6 +738,15 @@ static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir, cifs_autodisable_serverino(cifs_sb); } + if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) && + CIFSCouldBeMFSymlink(&fattr)) + /* + * trying to get the type and mode can be slow, + * so just call those regular files for now, and mark + * for reval + */ + fattr.cf_flags |= CIFS_FATTR_NEED_REVAL; + ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid); tmp_dentry = cifs_readdir_lookup(file->f_dentry, &qstring, &fattr);