linux-cifs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [CIFS] Support for Minshall+French symlinks
@ 2010-08-03 15:05 Stefan Metzmacher
       [not found] ` <1280847960-16371-1-git-send-email-metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
  0 siblings, 1 reply; 31+ messages in thread
From: Stefan Metzmacher @ 2010-08-03 15:05 UTC (permalink / raw)
  To: smfrench-Re5JQEeQqe8AvxtiuMwx3w; +Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA

Hi Steve,

The following patchset adds support Minshall+French symlinks for Linux.
See http://wiki.samba.org/index.php/UNIX_Extensions#Minshall.2BFrench_symlinks

I've added a new mount option 'mfsymlinks', which is off by default.

If the option is pass to a mount, Minshall+French symlinks will be used
to support symlinks for the local client.

This is compatible with the Darwin implementation.

Can you review this patches? It would be wonderful if they would endup
in Linux 2.6.36.

metze

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 1/8] cifs: add "mfsymlinks" mount option
       [not found] ` <1280847960-16371-1-git-send-email-metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
@ 2010-08-03 15:05   ` Stefan Metzmacher
       [not found]     ` <1280847960-16371-2-git-send-email-metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
  2010-08-03 15:05   ` [PATCH 2/8] cifs: add CIFSCreateMFSymLink() and CIFSQueryMFSymLink() as stubs Stefan Metzmacher
                     ` (7 subsequent siblings)
  8 siblings, 1 reply; 31+ messages in thread
From: Stefan Metzmacher @ 2010-08-03 15:05 UTC (permalink / raw)
  To: smfrench-Re5JQEeQqe8AvxtiuMwx3w
  Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA, Stefan Metzmacher

This is the start for an implementation of "Minshall+French Symlinks"
(see http://wiki.samba.org/index.php/UNIX_Extensions#Minshall.2BFrench_symlinks).

Signed-off-by: Stefan Metzmacher <metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
---
 fs/cifs/README       |    5 +++++
 fs/cifs/cifs_fs_sb.h |    1 +
 fs/cifs/cifsfs.c     |    2 ++
 fs/cifs/connect.c    |   11 +++++++++++
 4 files changed, 19 insertions(+), 0 deletions(-)

diff --git a/fs/cifs/README b/fs/cifs/README
index a727b7c..228c239 100644
--- a/fs/cifs/README
+++ b/fs/cifs/README
@@ -517,6 +517,11 @@ A partial list of the supported mount options follows:
 		SFU does).  In the future the bottom 9 bits of the
 		mode also will be emulated using queries of the security
 		descriptor (ACL).
+ mfsymlinks     Enable support for Minshall+French symlinks
+		(see http://wiki.samba.org/index.php/UNIX_Extensions#Minshall.2BFrench_symlinks)
+		This option is ignored when specified together with the
+		'sfu' option. Minshall+French symlinks are used event if
+		the server supports the CIFS Unix Extensions.
  sign           Must use packet signing (helps avoid unwanted data modification
 		by intermediate systems in the route).  Note that signing
 		does not work with lanman or plaintext authentication.
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/cifsfs.c b/fs/cifs/cifsfs.c
index 8a2cf12..ec48c96 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -421,6 +421,8 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m)
 		seq_printf(s, ",dynperm");
 	if (m->mnt_sb->s_flags & MS_POSIXACL)
 		seq_printf(s, ",acl");
+	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
+		seq_printf(s, ",mfsymlinks");
 
 	seq_printf(s, ",rsize=%d", cifs_sb->rsize);
 	seq_printf(s, ",wsize=%d", cifs_sb->wsize);
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 2a43a0a..b3b8752 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -100,6 +100,7 @@ struct smb_vol {
 	bool noautotune:1;
 	bool nostrictsync:1; /* do not force expensive SMBflush on every sync */
 	bool fsc:1;	/* enable fscache */
+	bool mfsymlinks:1; /* use Minshall+French Symlinks */
 	unsigned int rsize;
 	unsigned int wsize;
 	bool sockopt_tcp_nodelay:1;
@@ -1343,6 +1344,8 @@ cifs_parse_mount_options(char *options, const char *devname,
 				"/proc/fs/cifs/LookupCacheEnabled to 0\n");
 		} else if (strnicmp(data, "fsc", 3) == 0) {
 			vol->fsc = true;
+		} else if (strnicmp(data, "mfsymlinks", 22) == 0) {
+			vol->mfsymlinks = true;
 		} else
 			printk(KERN_WARNING "CIFS: Unknown mount option %s\n",
 						data);
@@ -2481,6 +2484,14 @@ static void setup_cifs_sb(struct smb_vol *pvolume_info,
 		cFYI(1, "mounting share using direct i/o");
 		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
 	}
+	if (pvolume_info->mfsymlinks) {
+		if (pvolume_info->sfu_emul) {
+			cERROR(1,  "mount option mfsymlinks ignored if sfu "
+				   "mount option is used");
+		} else {
+			cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS;
+		}
+	}
 
 	if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm))
 		cERROR(1, "mount option dynperm ignored if cifsacl "
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 2/8] cifs: add CIFSCreateMFSymLink() and CIFSQueryMFSymLink() as stubs
       [not found] ` <1280847960-16371-1-git-send-email-metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
  2010-08-03 15:05   ` [PATCH 1/8] cifs: add "mfsymlinks" mount option Stefan Metzmacher
@ 2010-08-03 15:05   ` Stefan Metzmacher
       [not found]     ` <1280847960-16371-3-git-send-email-metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
  2010-08-03 15:05   ` [PATCH 3/8] cifs: add CIFSCheckMFSymlink() as stub Stefan Metzmacher
                     ` (6 subsequent siblings)
  8 siblings, 1 reply; 31+ messages in thread
From: Stefan Metzmacher @ 2010-08-03 15:05 UTC (permalink / raw)
  To: smfrench-Re5JQEeQqe8AvxtiuMwx3w
  Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA, Stefan Metzmacher

Signed-off-by: Stefan Metzmacher <metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
---
 fs/cifs/link.c |   34 ++++++++++++++++++++++++++++++----
 1 files changed, 30 insertions(+), 4 deletions(-)

diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 473ca80..2358a5f 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -29,6 +29,24 @@
 #include "cifs_debug.h"
 #include "cifs_fs_sb.h"
 
+static int
+CIFSCreateMFSymLink(const int xid, struct cifsTconInfo *tcon,
+		    const char *fromName, const char *toName,
+		    const struct nls_table *nls_codepage)
+{
+	int rc = -EOPNOTSUPP;
+	return rc;
+}
+
+static int
+CIFSQueryMFSymLink(const int xid, struct cifsTconInfo *tcon,
+		   const unsigned char *searchName, char **symlinkinfo,
+		   const struct nls_table *nls_codepage)
+{
+	int rc = -EOPNOTSUPP;
+	return rc;
+}
+
 int
 cifs_hardlink(struct dentry *old_file, struct inode *inode,
 	      struct dentry *direntry)
@@ -130,7 +148,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;
 	}
@@ -141,8 +160,12 @@ 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);
+	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
+		rc = CIFSQueryMFSymLink(xid, tcon, full_path, &target_path,
+					cifs_sb->local_nls);
+	else
+		rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, &target_path,
+					     cifs_sb->local_nls);
 	kfree(full_path);
 out:
 	if (rc != 0) {
@@ -182,7 +205,10 @@ 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);
+	else if (pTcon->unix_ext)
 		rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname,
 					   cifs_sb->local_nls);
 	/* else
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 3/8] cifs: add CIFSCheckMFSymlink() as stub
       [not found] ` <1280847960-16371-1-git-send-email-metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
  2010-08-03 15:05   ` [PATCH 1/8] cifs: add "mfsymlinks" mount option Stefan Metzmacher
  2010-08-03 15:05   ` [PATCH 2/8] cifs: add CIFSCreateMFSymLink() and CIFSQueryMFSymLink() as stubs Stefan Metzmacher
@ 2010-08-03 15:05   ` Stefan Metzmacher
  2010-08-03 15:05   ` [PATCH 4/8] cifs: implement CIFSParseMFSymlink() Stefan Metzmacher
                     ` (5 subsequent siblings)
  8 siblings, 0 replies; 31+ messages in thread
From: Stefan Metzmacher @ 2010-08-03 15:05 UTC (permalink / raw)
  To: smfrench-Re5JQEeQqe8AvxtiuMwx3w
  Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA, Stefan Metzmacher

Signed-off-by: Stefan Metzmacher <metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
---
 fs/cifs/cifsproto.h |    3 +++
 fs/cifs/inode.c     |    7 +++++++
 fs/cifs/link.c      |    8 ++++++++
 3 files changed, 18 insertions(+), 0 deletions(-)

diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 2eaebbd..e94e095 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -409,4 +409,7 @@ extern int CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
 extern int CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
 			const int netfid, __u64 *pExtAttrBits, __u64 *pMask);
 extern void cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb);
+extern int CIFSCheckMFSymlink(struct cifs_fattr *fattr,
+		const unsigned char *path,
+		struct cifs_sb_info *cifs_sb, int xid);
 #endif			/* _CIFSPROTO_H */
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index a15b3a9..c4121de 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -661,6 +661,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);
 
+	/* query for SFU type info if supported and needed */
+	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 2358a5f..985373c 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -48,6 +48,14 @@ CIFSQueryMFSymLink(const int xid, struct cifsTconInfo *tcon,
 }
 
 int
+CIFSCheckMFSymlink(struct cifs_fattr *fattr,
+		   const unsigned char *path,
+		   struct cifs_sb_info *cifs_sb, int xid)
+{
+	return 0;
+}
+
+int
 cifs_hardlink(struct dentry *old_file, struct inode *inode,
 	      struct dentry *direntry)
 {
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 4/8] cifs: implement CIFSParseMFSymlink()
       [not found] ` <1280847960-16371-1-git-send-email-metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
                     ` (2 preceding siblings ...)
  2010-08-03 15:05   ` [PATCH 3/8] cifs: add CIFSCheckMFSymlink() as stub Stefan Metzmacher
@ 2010-08-03 15:05   ` Stefan Metzmacher
  2010-08-03 15:05   ` [PATCH 5/8] cifs: implement CIFSCheckMFSymlink() Stefan Metzmacher
                     ` (4 subsequent siblings)
  8 siblings, 0 replies; 31+ messages in thread
From: Stefan Metzmacher @ 2010-08-03 15:05 UTC (permalink / raw)
  To: smfrench-Re5JQEeQqe8AvxtiuMwx3w
  Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA, Stefan Metzmacher

Signed-off-by: Stefan Metzmacher <metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
---
 fs/cifs/link.c |   61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 61 insertions(+), 0 deletions(-)

diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 985373c..33307b1 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -28,6 +28,67 @@
 #include "cifsproto.h"
 #include "cifs_debug.h"
 #include "cifs_fs_sb.h"
+#include "md5.h"
+
+#define CIFS_MF_SYMLINK_LEN_OFFSET (4+1)
+#define CIFS_MF_SYMLINK_MD5_OFFSET (CIFS_MF_SYMLINK_LEN_OFFSET+(4+1))
+#define CIFS_MF_SYMLINK_LINK_OFFSET (CIFS_MF_SYMLINK_MD5_OFFSET+(32+1))
+#define CIFS_MF_SYMLINK_LINK_MAXLEN (1024)
+#define CIFS_MF_SYMLINK_FILE_SIZE (CIFS_MF_SYMLINK_LINK_OFFSET + CIFS_MF_SYMLINK_LINK_MAXLEN)
+
+#define CIFS_MF_SYMLINK_LEN_FORMAT "XSym\n%04u\n"
+#define CIFS_MF_SYMLINK_MD5_FORMAT \
+	"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n"
+#define CIFS_MF_SYMLINK_MD5_ARGS(md5_hash) \
+	md5_hash[0],  md5_hash[1],  md5_hash[2],  md5_hash[3], \
+	md5_hash[4],  md5_hash[5],  md5_hash[6],  md5_hash[7], \
+	md5_hash[8],  md5_hash[9],  md5_hash[10], md5_hash[11],\
+	md5_hash[12], md5_hash[13], md5_hash[14], md5_hash[15]
+
+static int
+CIFSParseMFSymlink(const u8 *buf,
+		   unsigned int buf_len,
+		   unsigned int *_link_len,
+		   char **_link_str)
+{
+	int rc;
+	unsigned int link_len;
+	const char *md5_str1;
+	const char *link_str;
+	struct MD5Context md5_ctx;
+	u8 md5_hash[16];
+	char md5_str2[34];
+
+	if (buf_len != CIFS_MF_SYMLINK_FILE_SIZE)
+		return -EINVAL;
+
+	md5_str1 = (const char *)&buf[CIFS_MF_SYMLINK_MD5_OFFSET];
+	link_str = (const char *)&buf[CIFS_MF_SYMLINK_LINK_OFFSET];
+
+	rc = sscanf(buf, CIFS_MF_SYMLINK_LEN_FORMAT, &link_len);
+	if (rc != 1)
+		return -EINVAL;
+
+	cifs_MD5_init(&md5_ctx);
+	cifs_MD5_update(&md5_ctx, (const u8 *)link_str, link_len);
+	cifs_MD5_final(md5_hash, &md5_ctx);
+
+	snprintf(md5_str2, sizeof(md5_str2),
+		 CIFS_MF_SYMLINK_MD5_FORMAT,
+		 CIFS_MF_SYMLINK_MD5_ARGS(md5_hash));
+
+	if (strncmp(md5_str1, md5_str2, 17) != 0)
+		return -EINVAL;
+
+	if (_link_str) {
+		*_link_str = kstrndup(link_str, link_len, GFP_KERNEL);
+		if (!*_link_str)
+			return -ENOMEM;
+	}
+
+	*_link_len = link_len;
+	return 0;
+}
 
 static int
 CIFSCreateMFSymLink(const int xid, struct cifsTconInfo *tcon,
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 5/8] cifs: implement CIFSCheckMFSymlink()
       [not found] ` <1280847960-16371-1-git-send-email-metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
                     ` (3 preceding siblings ...)
  2010-08-03 15:05   ` [PATCH 4/8] cifs: implement CIFSParseMFSymlink() Stefan Metzmacher
@ 2010-08-03 15:05   ` Stefan Metzmacher
  2010-08-03 15:05   ` [PATCH 6/8] cifs: implement CIFSQueryMFSymLink() Stefan Metzmacher
                     ` (3 subsequent siblings)
  8 siblings, 0 replies; 31+ messages in thread
From: Stefan Metzmacher @ 2010-08-03 15:05 UTC (permalink / raw)
  To: smfrench-Re5JQEeQqe8AvxtiuMwx3w
  Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA, Stefan Metzmacher

Signed-off-by: Stefan Metzmacher <metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
---
 fs/cifs/link.c |   60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 60 insertions(+), 0 deletions(-)

diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 33307b1..f7636f9 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -113,6 +113,66 @@ CIFSCheckMFSymlink(struct cifs_fattr *fattr,
 		   const unsigned char *path,
 		   struct cifs_sb_info *cifs_sb, int xid)
 {
+	int rc;
+	int oplock = 0;
+	__u16 netfid = 0;
+	struct cifsTconInfo *pTcon = cifs_sb->tcon;
+	u8 buf[CIFS_MF_SYMLINK_FILE_SIZE];
+	char *pbuf = buf;
+	unsigned int bytes_read = 0;
+	int buf_type = CIFS_NO_BUFFER;
+	unsigned int link_len = 0;
+	FILE_ALL_INFO file_info;
+
+	if (!(fattr->cf_mode & S_IFREG)) {
+		/* it's not a symlink */
+		return 0;
+	}
+
+	if (fattr->cf_eof != CIFS_MF_SYMLINK_FILE_SIZE) {
+		/* it's not a symlink */
+		return 0;
+	}
+
+	rc = CIFSSMBOpen(xid, pTcon, path, FILE_OPEN, GENERIC_READ,
+			 CREATE_NOT_DIR, &netfid, &oplock, &file_info,
+			 cifs_sb->local_nls,
+			 cifs_sb->mnt_cifs_flags &
+				CIFS_MOUNT_MAP_SPECIAL_CHR);
+	if (rc != 0) {
+		return rc;
+	}
+
+	if (file_info.EndOfFile != CIFS_MF_SYMLINK_FILE_SIZE) {
+		CIFSSMBClose(xid, pTcon, netfid);
+		/* it's not a symlink */
+		return 0;
+	}
+
+	/* Read header */
+	rc = CIFSSMBRead(xid, pTcon, netfid,
+			 CIFS_MF_SYMLINK_FILE_SIZE /* length */,
+			 0 /* offset */,
+			 &bytes_read, &pbuf, &buf_type);
+	CIFSSMBClose(xid, pTcon, netfid);
+	if (rc != 0) {
+		return rc;
+	}
+
+	rc = CIFSParseMFSymlink(buf, bytes_read, &link_len, NULL);
+	if (rc == EINVAL) {
+		/* it's not a symlink */
+		return 0;
+	}
+	if (rc != 0) {
+		return rc;
+	}
+
+	/* it is a symlink */
+	fattr->cf_eof = link_len;
+	fattr->cf_mode &= ~S_IFMT;
+	fattr->cf_mode |= S_IFLNK;
+	fattr->cf_dtype = DT_LNK;
 	return 0;
 }
 
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 6/8] cifs: implement CIFSQueryMFSymLink()
       [not found] ` <1280847960-16371-1-git-send-email-metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
                     ` (4 preceding siblings ...)
  2010-08-03 15:05   ` [PATCH 5/8] cifs: implement CIFSCheckMFSymlink() Stefan Metzmacher
@ 2010-08-03 15:05   ` Stefan Metzmacher
       [not found]     ` <1280847960-16371-7-git-send-email-metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
  2010-08-03 15:05   ` [PATCH 7/8] cifs: implement CIFSFormatMFSymlink() Stefan Metzmacher
                     ` (2 subsequent siblings)
  8 siblings, 1 reply; 31+ messages in thread
From: Stefan Metzmacher @ 2010-08-03 15:05 UTC (permalink / raw)
  To: smfrench-Re5JQEeQqe8AvxtiuMwx3w
  Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA, Stefan Metzmacher

Signed-off-by: Stefan Metzmacher <metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
---
 fs/cifs/link.c |   46 ++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 42 insertions(+), 4 deletions(-)

diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index f7636f9..77f5a40 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -102,10 +102,46 @@ CIFSCreateMFSymLink(const int xid, struct cifsTconInfo *tcon,
 static int
 CIFSQueryMFSymLink(const int xid, struct cifsTconInfo *tcon,
 		   const unsigned char *searchName, char **symlinkinfo,
-		   const struct nls_table *nls_codepage)
+		   const struct nls_table *nls_codepage, int remap)
 {
-	int rc = -EOPNOTSUPP;
-	return rc;
+	int rc;
+	int oplock = 0;
+	__u16 netfid = 0;
+	u8 buf[CIFS_MF_SYMLINK_FILE_SIZE];
+	char *pbuf = buf;
+	unsigned int bytes_read = 0;
+	int buf_type = CIFS_NO_BUFFER;
+	unsigned int link_len = 0;
+	FILE_ALL_INFO file_info;
+
+	rc = CIFSSMBOpen(xid, tcon, searchName, FILE_OPEN, GENERIC_READ,
+			 CREATE_NOT_DIR, &netfid, &oplock, &file_info,
+			 nls_codepage, remap);
+	if (rc != 0) {
+		return rc;
+	}
+
+	if (file_info.EndOfFile != CIFS_MF_SYMLINK_FILE_SIZE) {
+		CIFSSMBClose(xid, tcon, netfid);
+		/* it's not a symlink */
+		return -EINVAL;
+	}
+
+	rc = CIFSSMBRead(xid, tcon, netfid,
+			 CIFS_MF_SYMLINK_FILE_SIZE /* length */,
+			 0 /* offset */,
+			 &bytes_read, &pbuf, &buf_type);
+	CIFSSMBClose(xid, tcon, netfid);
+	if (rc != 0) {
+		return rc;
+	}
+
+	rc = CIFSParseMFSymlink(buf, bytes_read, &link_len, symlinkinfo);
+	if (rc != 0) {
+		return rc;
+	}
+
+	return 0;
 }
 
 int
@@ -291,7 +327,9 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
 
 	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
 		rc = CIFSQueryMFSymLink(xid, tcon, full_path, &target_path,
-					cifs_sb->local_nls);
+					cifs_sb->local_nls,
+					cifs_sb->mnt_cifs_flags &
+						CIFS_MOUNT_MAP_SPECIAL_CHR);
 	else
 		rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, &target_path,
 					     cifs_sb->local_nls);
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 7/8] cifs: implement CIFSFormatMFSymlink()
       [not found] ` <1280847960-16371-1-git-send-email-metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
                     ` (5 preceding siblings ...)
  2010-08-03 15:05   ` [PATCH 6/8] cifs: implement CIFSQueryMFSymLink() Stefan Metzmacher
@ 2010-08-03 15:05   ` Stefan Metzmacher
  2010-08-03 15:06   ` [PATCH 8/8] cifs: implement CIFSCreateMFSymLink() Stefan Metzmacher
  2010-08-03 18:00   ` [CIFS] Support for Minshall+French symlinks Steve French
  8 siblings, 0 replies; 31+ messages in thread
From: Stefan Metzmacher @ 2010-08-03 15:05 UTC (permalink / raw)
  To: smfrench-Re5JQEeQqe8AvxtiuMwx3w
  Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA, Stefan Metzmacher

Signed-off-by: Stefan Metzmacher <metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
---
 fs/cifs/link.c |   42 ++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 42 insertions(+), 0 deletions(-)

diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 77f5a40..b281d26 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -91,6 +91,48 @@ CIFSParseMFSymlink(const u8 *buf,
 }
 
 static int
+CIFSFormatMFSymlink(u8 *buf, unsigned int buf_len, const char *link_str)
+{
+	unsigned int link_len;
+	unsigned int ofs;
+	struct MD5Context md5_ctx;
+	u8 md5_hash[16];
+
+	if (buf_len != CIFS_MF_SYMLINK_FILE_SIZE)
+		return -EINVAL;
+
+	link_len = strlen(link_str);
+
+	if (link_len > CIFS_MF_SYMLINK_LINK_MAXLEN)
+		return -ENAMETOOLONG;
+
+	cifs_MD5_init(&md5_ctx);
+	cifs_MD5_update(&md5_ctx, (const u8 *)link_str, link_len);
+	cifs_MD5_final(md5_hash, &md5_ctx);
+
+	snprintf(buf, buf_len,
+		 CIFS_MF_SYMLINK_LEN_FORMAT CIFS_MF_SYMLINK_MD5_FORMAT,
+		 link_len,
+		 CIFS_MF_SYMLINK_MD5_ARGS(md5_hash));
+
+	ofs = CIFS_MF_SYMLINK_LINK_OFFSET;
+	memcpy(buf + ofs, link_str, link_len);
+
+	ofs += link_len;
+	if (ofs < CIFS_MF_SYMLINK_FILE_SIZE) {
+		buf[ofs] = '\n';
+		ofs++;
+	}
+
+	while (ofs < CIFS_MF_SYMLINK_FILE_SIZE) {
+		buf[ofs] = ' ';
+		ofs++;
+	}
+
+	return 0;
+}
+
+static int
 CIFSCreateMFSymLink(const int xid, struct cifsTconInfo *tcon,
 		    const char *fromName, const char *toName,
 		    const struct nls_table *nls_codepage)
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 8/8] cifs: implement CIFSCreateMFSymLink()
       [not found] ` <1280847960-16371-1-git-send-email-metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
                     ` (6 preceding siblings ...)
  2010-08-03 15:05   ` [PATCH 7/8] cifs: implement CIFSFormatMFSymlink() Stefan Metzmacher
@ 2010-08-03 15:06   ` Stefan Metzmacher
       [not found]     ` <1280847960-16371-9-git-send-email-metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
  2010-08-03 18:00   ` [CIFS] Support for Minshall+French symlinks Steve French
  8 siblings, 1 reply; 31+ messages in thread
From: Stefan Metzmacher @ 2010-08-03 15:06 UTC (permalink / raw)
  To: smfrench-Re5JQEeQqe8AvxtiuMwx3w
  Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA, Stefan Metzmacher

Signed-off-by: Stefan Metzmacher <metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
---
 fs/cifs/link.c |   39 +++++++++++++++++++++++++++++++++++----
 1 files changed, 35 insertions(+), 4 deletions(-)

diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index b281d26..93d2dfd 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -135,10 +135,39 @@ CIFSFormatMFSymlink(u8 *buf, unsigned int buf_len, const char *link_str)
 static int
 CIFSCreateMFSymLink(const int xid, struct cifsTconInfo *tcon,
 		    const char *fromName, const char *toName,
-		    const struct nls_table *nls_codepage)
+		    const struct nls_table *nls_codepage, int remap)
 {
-	int rc = -EOPNOTSUPP;
-	return rc;
+	int rc;
+	int oplock = 0;
+	__u16 netfid = 0;
+	u8 buf[CIFS_MF_SYMLINK_FILE_SIZE];
+	unsigned int bytes_written = 0;
+
+	rc = CIFSFormatMFSymlink(buf, sizeof(buf), toName);
+	if (rc != 0) {
+		return rc;
+	}
+
+	rc = CIFSSMBOpen(xid, tcon, fromName, FILE_CREATE, GENERIC_WRITE,
+			 CREATE_NOT_DIR, &netfid, &oplock, NULL,
+			 nls_codepage, remap);
+	if (rc != 0) {
+		return rc;
+	}
+
+	rc = CIFSSMBWrite(xid, tcon, netfid,
+			  sizeof(buf) /* length */,
+			  0 /* offset */,
+			  &bytes_written, buf, NULL, 0);
+	CIFSSMBClose(xid, tcon, netfid);
+	if (rc != 0) {
+		return rc;
+	}
+
+	if (bytes_written != sizeof(buf))
+		return -EIO;
+
+	return 0;
 }
 
 static int
@@ -416,7 +445,9 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
 	/* BB what if DFS and this volume is on different share? BB */
 	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
 		rc = CIFSCreateMFSymLink(xid, pTcon, full_path, symname,
-					 cifs_sb->local_nls);
+					 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);
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* Re: [PATCH 8/8] cifs: implement CIFSCreateMFSymLink()
       [not found]     ` <1280847960-16371-9-git-send-email-metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
@ 2010-08-03 15:29       ` Jeff Layton
  0 siblings, 0 replies; 31+ messages in thread
From: Jeff Layton @ 2010-08-03 15:29 UTC (permalink / raw)
  To: Stefan Metzmacher
  Cc: smfrench-Re5JQEeQqe8AvxtiuMwx3w,
	linux-cifs-u79uwXL29TY76Z2rM5mHXA

On Tue,  3 Aug 2010 17:06:00 +0200
Stefan Metzmacher <metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org> wrote:

> Signed-off-by: Stefan Metzmacher <metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
> ---
>  fs/cifs/link.c |   39 +++++++++++++++++++++++++++++++++++----
>  1 files changed, 35 insertions(+), 4 deletions(-)
> 
> diff --git a/fs/cifs/link.c b/fs/cifs/link.c
> index b281d26..93d2dfd 100644
> --- a/fs/cifs/link.c
> +++ b/fs/cifs/link.c
> @@ -135,10 +135,39 @@ CIFSFormatMFSymlink(u8 *buf, unsigned int buf_len, const char *link_str)
>  static int
>  CIFSCreateMFSymLink(const int xid, struct cifsTconInfo *tcon,
>  		    const char *fromName, const char *toName,
> -		    const struct nls_table *nls_codepage)
> +		    const struct nls_table *nls_codepage, int remap)
>  {
> -	int rc = -EOPNOTSUPP;
> -	return rc;
> +	int rc;
> +	int oplock = 0;
> +	__u16 netfid = 0;
> +	u8 buf[CIFS_MF_SYMLINK_FILE_SIZE];
	^^^^^^^^^^^^^^
Oof. You really don't want to do this -- allocating this much on the
stack is a good way to get memory corruption. I'd kmalloc this
buffer instead.

> +	unsigned int bytes_written = 0;
> +
> +	rc = CIFSFormatMFSymlink(buf, sizeof(buf), toName);
> +	if (rc != 0) {
> +		return rc;
> +	}
> +
> +	rc = CIFSSMBOpen(xid, tcon, fromName, FILE_CREATE, GENERIC_WRITE,
> +			 CREATE_NOT_DIR, &netfid, &oplock, NULL,
> +			 nls_codepage, remap);
> +	if (rc != 0) {
> +		return rc;
> +	}
> +
> +	rc = CIFSSMBWrite(xid, tcon, netfid,
> +			  sizeof(buf) /* length */,
> +			  0 /* offset */,
> +			  &bytes_written, buf, NULL, 0);
> +	CIFSSMBClose(xid, tcon, netfid);
> +	if (rc != 0) {
> +		return rc;
> +	}
> +
> +	if (bytes_written != sizeof(buf))
> +		return -EIO;
> +
> +	return 0;
>  }
>  
>  static int
> @@ -416,7 +445,9 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
>  	/* BB what if DFS and this volume is on different share? BB */
>  	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
>  		rc = CIFSCreateMFSymLink(xid, pTcon, full_path, symname,
> -					 cifs_sb->local_nls);
> +					 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);


-- 
Jeff Layton <jlayton-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 6/8] cifs: implement CIFSQueryMFSymLink()
       [not found]     ` <1280847960-16371-7-git-send-email-metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
@ 2010-08-03 16:31       ` Jeff Layton
  0 siblings, 0 replies; 31+ messages in thread
From: Jeff Layton @ 2010-08-03 16:31 UTC (permalink / raw)
  To: Stefan Metzmacher
  Cc: smfrench-Re5JQEeQqe8AvxtiuMwx3w,
	linux-cifs-u79uwXL29TY76Z2rM5mHXA

On Tue,  3 Aug 2010 17:05:58 +0200
Stefan Metzmacher <metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org> wrote:

> Signed-off-by: Stefan Metzmacher <metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
> ---
>  fs/cifs/link.c |   46 ++++++++++++++++++++++++++++++++++++++++++----
>  1 files changed, 42 insertions(+), 4 deletions(-)
> 
> diff --git a/fs/cifs/link.c b/fs/cifs/link.c
> index f7636f9..77f5a40 100644
> --- a/fs/cifs/link.c
> +++ b/fs/cifs/link.c
> @@ -102,10 +102,46 @@ CIFSCreateMFSymLink(const int xid, struct cifsTconInfo *tcon,
>  static int
>  CIFSQueryMFSymLink(const int xid, struct cifsTconInfo *tcon,
>  		   const unsigned char *searchName, char **symlinkinfo,
> -		   const struct nls_table *nls_codepage)
> +		   const struct nls_table *nls_codepage, int remap)
>  {
> -	int rc = -EOPNOTSUPP;
> -	return rc;
> +	int rc;
> +	int oplock = 0;
> +	__u16 netfid = 0;
> +	u8 buf[CIFS_MF_SYMLINK_FILE_SIZE];
	^^^^
	as noted before, you don't want to allocate these big buffers on the stack

> +	char *pbuf = buf;
> +	unsigned int bytes_read = 0;
> +	int buf_type = CIFS_NO_BUFFER;
> +	unsigned int link_len = 0;
> +	FILE_ALL_INFO file_info;
> +
> +	rc = CIFSSMBOpen(xid, tcon, searchName, FILE_OPEN, GENERIC_READ,
> +			 CREATE_NOT_DIR, &netfid, &oplock, &file_info,
> +			 nls_codepage, remap);
> +	if (rc != 0) {
> +		return rc;
> +	}
> +
	In general, kernel coding style leaves out braces when the
	inside of an if block is a single statement. IOW, this should
	read:

	if (rc != 0)
		return rc;

> +	if (file_info.EndOfFile != CIFS_MF_SYMLINK_FILE_SIZE) {
> +		CIFSSMBClose(xid, tcon, netfid);
> +		/* it's not a symlink */
> +		return -EINVAL;
> +	}
> +
> +	rc = CIFSSMBRead(xid, tcon, netfid,
> +			 CIFS_MF_SYMLINK_FILE_SIZE /* length */,
> +			 0 /* offset */,
> +			 &bytes_read, &pbuf, &buf_type);
> +	CIFSSMBClose(xid, tcon, netfid);
> +	if (rc != 0) {
> +		return rc;
> +	}
> +
> +	rc = CIFSParseMFSymlink(buf, bytes_read, &link_len, symlinkinfo);
> +	if (rc != 0) {
> +		return rc;
> +	}
> +
> +	return 0;
>  }
>  
>  int
> @@ -291,7 +327,9 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
>  
>  	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
>  		rc = CIFSQueryMFSymLink(xid, tcon, full_path, &target_path,
> -					cifs_sb->local_nls);
> +					cifs_sb->local_nls,
> +					cifs_sb->mnt_cifs_flags &
> +						CIFS_MOUNT_MAP_SPECIAL_CHR);
>  	else
>  		rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, &target_path,
>  					     cifs_sb->local_nls);


-- 
Jeff Layton <jlayton-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [CIFS] Support for Minshall+French symlinks
       [not found] ` <1280847960-16371-1-git-send-email-metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
                     ` (7 preceding siblings ...)
  2010-08-03 15:06   ` [PATCH 8/8] cifs: implement CIFSCreateMFSymLink() Stefan Metzmacher
@ 2010-08-03 18:00   ` Steve French
       [not found]     ` <AANLkTinJ1WRBT_Q3TqOZdMQExV66LSUAPG4c01yK-XRK-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  8 siblings, 1 reply; 31+ messages in thread
From: Steve French @ 2010-08-03 18:00 UTC (permalink / raw)
  To: Stefan Metzmacher; +Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA

Interesting.

Generally seems like a good idea.

Jeff made two valid review comments already (on the kmalloc vs. stack,
and the kernel coding style) but note that scripts/checkpatch.pl will
catch additional minor coding style things:

stevef@stevef-laptop:~/smb2$ scripts/checkpatch.pl ~/sm1.patch
WARNING: braces {} are not necessary for single statement blocks
#62: FILE: fs/cifs/link.c:120:
+	if (rc != 0) {
+		return rc;
+	}

Could you clean up the things scripts/checkpatch.pl (and sparse
issues, ie "make modules C=1"  -- if any)

On Tue, Aug 3, 2010 at 10:05 AM, Stefan Metzmacher <metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org> wrote:
> Hi Steve,
>
> The following patchset adds support Minshall+French symlinks for Linux.
> See http://wiki.samba.org/index.php/UNIX_Extensions#Minshall.2BFrench_symlinks
>
> I've added a new mount option 'mfsymlinks', which is off by default.
>
> If the option is pass to a mount, Minshall+French symlinks will be used
> to support symlinks for the local client.
>
> This is compatible with the Darwin implementation.
>
> Can you review this patches? It would be wonderful if they would endup
> in Linux 2.6.36.
>
> metze
>
>



-- 
Thanks,

Steve

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [CIFS] Support for Minshall+French symlinks
       [not found]     ` <AANLkTinJ1WRBT_Q3TqOZdMQExV66LSUAPG4c01yK-XRK-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2010-08-04 14:11       ` Stefan Metzmacher
  2010-08-04 14:11       ` [PATCH 1/8] cifs: add "mfsymlinks" mount option Stefan Metzmacher
                         ` (7 subsequent siblings)
  8 siblings, 0 replies; 31+ messages in thread
From: Stefan Metzmacher @ 2010-08-04 14:11 UTC (permalink / raw)
  To: smfrench-Re5JQEeQqe8AvxtiuMwx3w; +Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA

Hi Steve,

here's the updated patchset.

metze

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 1/8] cifs: add "mfsymlinks" mount option
       [not found]     ` <AANLkTinJ1WRBT_Q3TqOZdMQExV66LSUAPG4c01yK-XRK-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  2010-08-04 14:11       ` Stefan Metzmacher
@ 2010-08-04 14:11       ` Stefan Metzmacher
  2010-08-04 14:11       ` [PATCH 2/8] cifs: add CIFSCreateMFSymLink() and CIFSQueryMFSymLink() as stubs Stefan Metzmacher
                         ` (6 subsequent siblings)
  8 siblings, 0 replies; 31+ messages in thread
From: Stefan Metzmacher @ 2010-08-04 14:11 UTC (permalink / raw)
  To: smfrench-Re5JQEeQqe8AvxtiuMwx3w
  Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA, Stefan Metzmacher

This is the start for an implementation of "Minshall+French Symlinks"
(see http://wiki.samba.org/index.php/UNIX_Extensions#Minshall.2BFrench_symlinks).

Signed-off-by: Stefan Metzmacher <metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
---
 fs/cifs/README       |    5 +++++
 fs/cifs/cifs_fs_sb.h |    1 +
 fs/cifs/cifsfs.c     |    2 ++
 fs/cifs/connect.c    |   11 +++++++++++
 4 files changed, 19 insertions(+), 0 deletions(-)

diff --git a/fs/cifs/README b/fs/cifs/README
index a727b7c..228c239 100644
--- a/fs/cifs/README
+++ b/fs/cifs/README
@@ -517,6 +517,11 @@ A partial list of the supported mount options follows:
 		SFU does).  In the future the bottom 9 bits of the
 		mode also will be emulated using queries of the security
 		descriptor (ACL).
+ mfsymlinks     Enable support for Minshall+French symlinks
+		(see http://wiki.samba.org/index.php/UNIX_Extensions#Minshall.2BFrench_symlinks)
+		This option is ignored when specified together with the
+		'sfu' option. Minshall+French symlinks are used event if
+		the server supports the CIFS Unix Extensions.
  sign           Must use packet signing (helps avoid unwanted data modification
 		by intermediate systems in the route).  Note that signing
 		does not work with lanman or plaintext authentication.
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/cifsfs.c b/fs/cifs/cifsfs.c
index 8a2cf12..ec48c96 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -421,6 +421,8 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m)
 		seq_printf(s, ",dynperm");
 	if (m->mnt_sb->s_flags & MS_POSIXACL)
 		seq_printf(s, ",acl");
+	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
+		seq_printf(s, ",mfsymlinks");
 
 	seq_printf(s, ",rsize=%d", cifs_sb->rsize);
 	seq_printf(s, ",wsize=%d", cifs_sb->wsize);
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 2a43a0a..b3b8752 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -100,6 +100,7 @@ struct smb_vol {
 	bool noautotune:1;
 	bool nostrictsync:1; /* do not force expensive SMBflush on every sync */
 	bool fsc:1;	/* enable fscache */
+	bool mfsymlinks:1; /* use Minshall+French Symlinks */
 	unsigned int rsize;
 	unsigned int wsize;
 	bool sockopt_tcp_nodelay:1;
@@ -1343,6 +1344,8 @@ cifs_parse_mount_options(char *options, const char *devname,
 				"/proc/fs/cifs/LookupCacheEnabled to 0\n");
 		} else if (strnicmp(data, "fsc", 3) == 0) {
 			vol->fsc = true;
+		} else if (strnicmp(data, "mfsymlinks", 22) == 0) {
+			vol->mfsymlinks = true;
 		} else
 			printk(KERN_WARNING "CIFS: Unknown mount option %s\n",
 						data);
@@ -2481,6 +2484,14 @@ static void setup_cifs_sb(struct smb_vol *pvolume_info,
 		cFYI(1, "mounting share using direct i/o");
 		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
 	}
+	if (pvolume_info->mfsymlinks) {
+		if (pvolume_info->sfu_emul) {
+			cERROR(1,  "mount option mfsymlinks ignored if sfu "
+				   "mount option is used");
+		} else {
+			cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS;
+		}
+	}
 
 	if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm))
 		cERROR(1, "mount option dynperm ignored if cifsacl "
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 2/8] cifs: add CIFSCreateMFSymLink() and CIFSQueryMFSymLink() as stubs
       [not found]     ` <AANLkTinJ1WRBT_Q3TqOZdMQExV66LSUAPG4c01yK-XRK-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  2010-08-04 14:11       ` Stefan Metzmacher
  2010-08-04 14:11       ` [PATCH 1/8] cifs: add "mfsymlinks" mount option Stefan Metzmacher
@ 2010-08-04 14:11       ` Stefan Metzmacher
  2010-08-04 14:11       ` [PATCH 3/8] cifs: add CIFSCheckMFSymlink() as stub Stefan Metzmacher
                         ` (5 subsequent siblings)
  8 siblings, 0 replies; 31+ messages in thread
From: Stefan Metzmacher @ 2010-08-04 14:11 UTC (permalink / raw)
  To: smfrench-Re5JQEeQqe8AvxtiuMwx3w
  Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA, Stefan Metzmacher

Signed-off-by: Stefan Metzmacher <metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
---
 fs/cifs/link.c |   34 ++++++++++++++++++++++++++++++----
 1 files changed, 30 insertions(+), 4 deletions(-)

diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 473ca80..2358a5f 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -29,6 +29,24 @@
 #include "cifs_debug.h"
 #include "cifs_fs_sb.h"
 
+static int
+CIFSCreateMFSymLink(const int xid, struct cifsTconInfo *tcon,
+		    const char *fromName, const char *toName,
+		    const struct nls_table *nls_codepage)
+{
+	int rc = -EOPNOTSUPP;
+	return rc;
+}
+
+static int
+CIFSQueryMFSymLink(const int xid, struct cifsTconInfo *tcon,
+		   const unsigned char *searchName, char **symlinkinfo,
+		   const struct nls_table *nls_codepage)
+{
+	int rc = -EOPNOTSUPP;
+	return rc;
+}
+
 int
 cifs_hardlink(struct dentry *old_file, struct inode *inode,
 	      struct dentry *direntry)
@@ -130,7 +148,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;
 	}
@@ -141,8 +160,12 @@ 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);
+	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
+		rc = CIFSQueryMFSymLink(xid, tcon, full_path, &target_path,
+					cifs_sb->local_nls);
+	else
+		rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, &target_path,
+					     cifs_sb->local_nls);
 	kfree(full_path);
 out:
 	if (rc != 0) {
@@ -182,7 +205,10 @@ 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);
+	else if (pTcon->unix_ext)
 		rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname,
 					   cifs_sb->local_nls);
 	/* else
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 3/8] cifs: add CIFSCheckMFSymlink() as stub
       [not found]     ` <AANLkTinJ1WRBT_Q3TqOZdMQExV66LSUAPG4c01yK-XRK-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
                         ` (2 preceding siblings ...)
  2010-08-04 14:11       ` [PATCH 2/8] cifs: add CIFSCreateMFSymLink() and CIFSQueryMFSymLink() as stubs Stefan Metzmacher
@ 2010-08-04 14:11       ` Stefan Metzmacher
       [not found]         ` <1280931109-22380-4-git-send-email-metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
  2010-08-04 14:11       ` [PATCH 4/8] cifs: implement CIFSParseMFSymlink() Stefan Metzmacher
                         ` (4 subsequent siblings)
  8 siblings, 1 reply; 31+ messages in thread
From: Stefan Metzmacher @ 2010-08-04 14:11 UTC (permalink / raw)
  To: smfrench-Re5JQEeQqe8AvxtiuMwx3w
  Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA, Stefan Metzmacher

Signed-off-by: Stefan Metzmacher <metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
---
 fs/cifs/cifsproto.h |    3 +++
 fs/cifs/inode.c     |    7 +++++++
 fs/cifs/link.c      |    8 ++++++++
 3 files changed, 18 insertions(+), 0 deletions(-)

diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 2eaebbd..e94e095 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -409,4 +409,7 @@ extern int CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
 extern int CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
 			const int netfid, __u64 *pExtAttrBits, __u64 *pMask);
 extern void cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb);
+extern int CIFSCheckMFSymlink(struct cifs_fattr *fattr,
+		const unsigned char *path,
+		struct cifs_sb_info *cifs_sb, int xid);
 #endif			/* _CIFSPROTO_H */
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index a15b3a9..c4121de 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -661,6 +661,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);
 
+	/* query for SFU type info if supported and needed */
+	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 2358a5f..985373c 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -48,6 +48,14 @@ CIFSQueryMFSymLink(const int xid, struct cifsTconInfo *tcon,
 }
 
 int
+CIFSCheckMFSymlink(struct cifs_fattr *fattr,
+		   const unsigned char *path,
+		   struct cifs_sb_info *cifs_sb, int xid)
+{
+	return 0;
+}
+
+int
 cifs_hardlink(struct dentry *old_file, struct inode *inode,
 	      struct dentry *direntry)
 {
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 4/8] cifs: implement CIFSParseMFSymlink()
       [not found]     ` <AANLkTinJ1WRBT_Q3TqOZdMQExV66LSUAPG4c01yK-XRK-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
                         ` (3 preceding siblings ...)
  2010-08-04 14:11       ` [PATCH 3/8] cifs: add CIFSCheckMFSymlink() as stub Stefan Metzmacher
@ 2010-08-04 14:11       ` Stefan Metzmacher
  2010-08-04 14:11       ` [PATCH 5/8] cifs: implement CIFSCheckMFSymlink() Stefan Metzmacher
                         ` (3 subsequent siblings)
  8 siblings, 0 replies; 31+ messages in thread
From: Stefan Metzmacher @ 2010-08-04 14:11 UTC (permalink / raw)
  To: smfrench-Re5JQEeQqe8AvxtiuMwx3w
  Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA, Stefan Metzmacher

Signed-off-by: Stefan Metzmacher <metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
---
 fs/cifs/link.c |   62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 62 insertions(+), 0 deletions(-)

diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 985373c..0d90a89 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -28,6 +28,68 @@
 #include "cifsproto.h"
 #include "cifs_debug.h"
 #include "cifs_fs_sb.h"
+#include "md5.h"
+
+#define CIFS_MF_SYMLINK_LEN_OFFSET (4+1)
+#define CIFS_MF_SYMLINK_MD5_OFFSET (CIFS_MF_SYMLINK_LEN_OFFSET+(4+1))
+#define CIFS_MF_SYMLINK_LINK_OFFSET (CIFS_MF_SYMLINK_MD5_OFFSET+(32+1))
+#define CIFS_MF_SYMLINK_LINK_MAXLEN (1024)
+#define CIFS_MF_SYMLINK_FILE_SIZE \
+	(CIFS_MF_SYMLINK_LINK_OFFSET + CIFS_MF_SYMLINK_LINK_MAXLEN)
+
+#define CIFS_MF_SYMLINK_LEN_FORMAT "XSym\n%04u\n"
+#define CIFS_MF_SYMLINK_MD5_FORMAT \
+	"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n"
+#define CIFS_MF_SYMLINK_MD5_ARGS(md5_hash) \
+	md5_hash[0],  md5_hash[1],  md5_hash[2],  md5_hash[3], \
+	md5_hash[4],  md5_hash[5],  md5_hash[6],  md5_hash[7], \
+	md5_hash[8],  md5_hash[9],  md5_hash[10], md5_hash[11],\
+	md5_hash[12], md5_hash[13], md5_hash[14], md5_hash[15]
+
+static int
+CIFSParseMFSymlink(const u8 *buf,
+		   unsigned int buf_len,
+		   unsigned int *_link_len,
+		   char **_link_str)
+{
+	int rc;
+	unsigned int link_len;
+	const char *md5_str1;
+	const char *link_str;
+	struct MD5Context md5_ctx;
+	u8 md5_hash[16];
+	char md5_str2[34];
+
+	if (buf_len != CIFS_MF_SYMLINK_FILE_SIZE)
+		return -EINVAL;
+
+	md5_str1 = (const char *)&buf[CIFS_MF_SYMLINK_MD5_OFFSET];
+	link_str = (const char *)&buf[CIFS_MF_SYMLINK_LINK_OFFSET];
+
+	rc = sscanf(buf, CIFS_MF_SYMLINK_LEN_FORMAT, &link_len);
+	if (rc != 1)
+		return -EINVAL;
+
+	cifs_MD5_init(&md5_ctx);
+	cifs_MD5_update(&md5_ctx, (const u8 *)link_str, link_len);
+	cifs_MD5_final(md5_hash, &md5_ctx);
+
+	snprintf(md5_str2, sizeof(md5_str2),
+		 CIFS_MF_SYMLINK_MD5_FORMAT,
+		 CIFS_MF_SYMLINK_MD5_ARGS(md5_hash));
+
+	if (strncmp(md5_str1, md5_str2, 17) != 0)
+		return -EINVAL;
+
+	if (_link_str) {
+		*_link_str = kstrndup(link_str, link_len, GFP_KERNEL);
+		if (!*_link_str)
+			return -ENOMEM;
+	}
+
+	*_link_len = link_len;
+	return 0;
+}
 
 static int
 CIFSCreateMFSymLink(const int xid, struct cifsTconInfo *tcon,
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 5/8] cifs: implement CIFSCheckMFSymlink()
       [not found]     ` <AANLkTinJ1WRBT_Q3TqOZdMQExV66LSUAPG4c01yK-XRK-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
                         ` (4 preceding siblings ...)
  2010-08-04 14:11       ` [PATCH 4/8] cifs: implement CIFSParseMFSymlink() Stefan Metzmacher
@ 2010-08-04 14:11       ` Stefan Metzmacher
       [not found]         ` <1280931109-22380-6-git-send-email-metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
  2010-08-04 14:11       ` [PATCH 6/8] cifs: implement CIFSQueryMFSymLink() Stefan Metzmacher
                         ` (2 subsequent siblings)
  8 siblings, 1 reply; 31+ messages in thread
From: Stefan Metzmacher @ 2010-08-04 14:11 UTC (permalink / raw)
  To: smfrench-Re5JQEeQqe8AvxtiuMwx3w
  Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA, Stefan Metzmacher

Signed-off-by: Stefan Metzmacher <metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
---
 fs/cifs/link.c |   65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 65 insertions(+), 0 deletions(-)

diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 0d90a89..6cd0879 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -114,6 +114,71 @@ CIFSCheckMFSymlink(struct cifs_fattr *fattr,
 		   const unsigned char *path,
 		   struct cifs_sb_info *cifs_sb, int xid)
 {
+	int rc;
+	int oplock = 0;
+	__u16 netfid = 0;
+	struct cifsTconInfo *pTcon = cifs_sb->tcon;
+	u8 *buf;
+	char *pbuf;
+	unsigned int bytes_read = 0;
+	int buf_type = CIFS_NO_BUFFER;
+	unsigned int link_len = 0;
+	FILE_ALL_INFO file_info;
+
+	if (!(fattr->cf_mode & S_IFREG))
+		/* it's not a symlink */
+		return 0;
+
+	if (fattr->cf_eof != CIFS_MF_SYMLINK_FILE_SIZE)
+		/* it's not a symlink */
+		return 0;
+
+	buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+	pbuf = buf;
+
+	rc = CIFSSMBOpen(xid, pTcon, path, FILE_OPEN, GENERIC_READ,
+			 CREATE_NOT_DIR, &netfid, &oplock, &file_info,
+			 cifs_sb->local_nls,
+			 cifs_sb->mnt_cifs_flags &
+				CIFS_MOUNT_MAP_SPECIAL_CHR);
+	if (rc != 0) {
+		kfree(buf);
+		return rc;
+	}
+
+	if (file_info.EndOfFile != CIFS_MF_SYMLINK_FILE_SIZE) {
+		CIFSSMBClose(xid, pTcon, netfid);
+		kfree(buf);
+		/* it's not a symlink */
+		return 0;
+	}
+
+	/* Read header */
+	rc = CIFSSMBRead(xid, pTcon, netfid,
+			 CIFS_MF_SYMLINK_FILE_SIZE /* length */,
+			 0 /* offset */,
+			 &bytes_read, &pbuf, &buf_type);
+	CIFSSMBClose(xid, pTcon, netfid);
+	if (rc != 0) {
+		kfree(buf);
+		return rc;
+	}
+
+	rc = CIFSParseMFSymlink(buf, bytes_read, &link_len, NULL);
+	kfree(buf);
+	if (rc == -EINVAL)
+		/* it's not a symlink */
+		return 0;
+	if (rc != 0)
+		return rc;
+
+	/* it is a symlink */
+	fattr->cf_eof = link_len;
+	fattr->cf_mode &= ~S_IFMT;
+	fattr->cf_mode |= S_IFLNK;
+	fattr->cf_dtype = DT_LNK;
 	return 0;
 }
 
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 6/8] cifs: implement CIFSQueryMFSymLink()
       [not found]     ` <AANLkTinJ1WRBT_Q3TqOZdMQExV66LSUAPG4c01yK-XRK-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
                         ` (5 preceding siblings ...)
  2010-08-04 14:11       ` [PATCH 5/8] cifs: implement CIFSCheckMFSymlink() Stefan Metzmacher
@ 2010-08-04 14:11       ` Stefan Metzmacher
  2010-08-04 14:11       ` [PATCH 7/8] cifs: implement CIFSFormatMFSymlink() Stefan Metzmacher
  2010-08-04 14:11       ` [PATCH 8/8] cifs: implement CIFSCreateMFSymLink() Stefan Metzmacher
  8 siblings, 0 replies; 31+ messages in thread
From: Stefan Metzmacher @ 2010-08-04 14:11 UTC (permalink / raw)
  To: smfrench-Re5JQEeQqe8AvxtiuMwx3w
  Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA, Stefan Metzmacher

Signed-off-by: Stefan Metzmacher <metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
---
 fs/cifs/link.c |   54 ++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 50 insertions(+), 4 deletions(-)

diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 6cd0879..6d00712 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -103,10 +103,54 @@ CIFSCreateMFSymLink(const int xid, struct cifsTconInfo *tcon,
 static int
 CIFSQueryMFSymLink(const int xid, struct cifsTconInfo *tcon,
 		   const unsigned char *searchName, char **symlinkinfo,
-		   const struct nls_table *nls_codepage)
+		   const struct nls_table *nls_codepage, int remap)
 {
-	int rc = -EOPNOTSUPP;
-	return rc;
+	int rc;
+	int oplock = 0;
+	__u16 netfid = 0;
+	u8 *buf;
+	char *pbuf;
+	unsigned int bytes_read = 0;
+	int buf_type = CIFS_NO_BUFFER;
+	unsigned int link_len = 0;
+	FILE_ALL_INFO file_info;
+
+	buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+	pbuf = buf;
+
+	rc = CIFSSMBOpen(xid, tcon, searchName, FILE_OPEN, GENERIC_READ,
+			 CREATE_NOT_DIR, &netfid, &oplock, &file_info,
+			 nls_codepage, remap);
+	if (rc != 0) {
+		kfree(buf);
+		return rc;
+	}
+
+	if (file_info.EndOfFile != CIFS_MF_SYMLINK_FILE_SIZE) {
+		CIFSSMBClose(xid, tcon, netfid);
+		kfree(buf);
+		/* it's not a symlink */
+		return -EINVAL;
+	}
+
+	rc = CIFSSMBRead(xid, tcon, netfid,
+			 CIFS_MF_SYMLINK_FILE_SIZE /* length */,
+			 0 /* offset */,
+			 &bytes_read, &pbuf, &buf_type);
+	CIFSSMBClose(xid, tcon, netfid);
+	if (rc != 0) {
+		kfree(buf);
+		return rc;
+	}
+
+	rc = CIFSParseMFSymlink(buf, bytes_read, &link_len, symlinkinfo);
+	kfree(buf);
+	if (rc != 0)
+		return rc;
+
+	return 0;
 }
 
 int
@@ -297,7 +341,9 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
 
 	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
 		rc = CIFSQueryMFSymLink(xid, tcon, full_path, &target_path,
-					cifs_sb->local_nls);
+					cifs_sb->local_nls,
+					cifs_sb->mnt_cifs_flags &
+						CIFS_MOUNT_MAP_SPECIAL_CHR);
 	else
 		rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, &target_path,
 					     cifs_sb->local_nls);
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 7/8] cifs: implement CIFSFormatMFSymlink()
       [not found]     ` <AANLkTinJ1WRBT_Q3TqOZdMQExV66LSUAPG4c01yK-XRK-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
                         ` (6 preceding siblings ...)
  2010-08-04 14:11       ` [PATCH 6/8] cifs: implement CIFSQueryMFSymLink() Stefan Metzmacher
@ 2010-08-04 14:11       ` Stefan Metzmacher
  2010-08-04 14:11       ` [PATCH 8/8] cifs: implement CIFSCreateMFSymLink() Stefan Metzmacher
  8 siblings, 0 replies; 31+ messages in thread
From: Stefan Metzmacher @ 2010-08-04 14:11 UTC (permalink / raw)
  To: smfrench-Re5JQEeQqe8AvxtiuMwx3w
  Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA, Stefan Metzmacher

Signed-off-by: Stefan Metzmacher <metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
---
 fs/cifs/link.c |   42 ++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 42 insertions(+), 0 deletions(-)

diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 6d00712..89e09da 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -92,6 +92,48 @@ CIFSParseMFSymlink(const u8 *buf,
 }
 
 static int
+CIFSFormatMFSymlink(u8 *buf, unsigned int buf_len, const char *link_str)
+{
+	unsigned int link_len;
+	unsigned int ofs;
+	struct MD5Context md5_ctx;
+	u8 md5_hash[16];
+
+	if (buf_len != CIFS_MF_SYMLINK_FILE_SIZE)
+		return -EINVAL;
+
+	link_len = strlen(link_str);
+
+	if (link_len > CIFS_MF_SYMLINK_LINK_MAXLEN)
+		return -ENAMETOOLONG;
+
+	cifs_MD5_init(&md5_ctx);
+	cifs_MD5_update(&md5_ctx, (const u8 *)link_str, link_len);
+	cifs_MD5_final(md5_hash, &md5_ctx);
+
+	snprintf(buf, buf_len,
+		 CIFS_MF_SYMLINK_LEN_FORMAT CIFS_MF_SYMLINK_MD5_FORMAT,
+		 link_len,
+		 CIFS_MF_SYMLINK_MD5_ARGS(md5_hash));
+
+	ofs = CIFS_MF_SYMLINK_LINK_OFFSET;
+	memcpy(buf + ofs, link_str, link_len);
+
+	ofs += link_len;
+	if (ofs < CIFS_MF_SYMLINK_FILE_SIZE) {
+		buf[ofs] = '\n';
+		ofs++;
+	}
+
+	while (ofs < CIFS_MF_SYMLINK_FILE_SIZE) {
+		buf[ofs] = ' ';
+		ofs++;
+	}
+
+	return 0;
+}
+
+static int
 CIFSCreateMFSymLink(const int xid, struct cifsTconInfo *tcon,
 		    const char *fromName, const char *toName,
 		    const struct nls_table *nls_codepage)
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 8/8] cifs: implement CIFSCreateMFSymLink()
       [not found]     ` <AANLkTinJ1WRBT_Q3TqOZdMQExV66LSUAPG4c01yK-XRK-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
                         ` (7 preceding siblings ...)
  2010-08-04 14:11       ` [PATCH 7/8] cifs: implement CIFSFormatMFSymlink() Stefan Metzmacher
@ 2010-08-04 14:11       ` Stefan Metzmacher
  8 siblings, 0 replies; 31+ messages in thread
From: Stefan Metzmacher @ 2010-08-04 14:11 UTC (permalink / raw)
  To: smfrench-Re5JQEeQqe8AvxtiuMwx3w
  Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA, Stefan Metzmacher

Signed-off-by: Stefan Metzmacher <metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
---
 fs/cifs/link.c |   45 +++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 41 insertions(+), 4 deletions(-)

diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 89e09da..7fecd4f 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -136,10 +136,45 @@ CIFSFormatMFSymlink(u8 *buf, unsigned int buf_len, const char *link_str)
 static int
 CIFSCreateMFSymLink(const int xid, struct cifsTconInfo *tcon,
 		    const char *fromName, const char *toName,
-		    const struct nls_table *nls_codepage)
+		    const struct nls_table *nls_codepage, int remap)
 {
-	int rc = -EOPNOTSUPP;
-	return rc;
+	int rc;
+	int oplock = 0;
+	__u16 netfid = 0;
+	u8 *buf;
+	unsigned int bytes_written = 0;
+
+	buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	rc = CIFSFormatMFSymlink(buf, CIFS_MF_SYMLINK_FILE_SIZE, toName);
+	if (rc != 0) {
+		kfree(buf);
+		return rc;
+	}
+
+	rc = CIFSSMBOpen(xid, tcon, fromName, FILE_CREATE, GENERIC_WRITE,
+			 CREATE_NOT_DIR, &netfid, &oplock, NULL,
+			 nls_codepage, remap);
+	if (rc != 0) {
+		kfree(buf);
+		return rc;
+	}
+
+	rc = CIFSSMBWrite(xid, tcon, netfid,
+			  CIFS_MF_SYMLINK_FILE_SIZE /* length */,
+			  0 /* offset */,
+			  &bytes_written, buf, NULL, 0);
+	CIFSSMBClose(xid, tcon, netfid);
+	kfree(buf);
+	if (rc != 0)
+		return rc;
+
+	if (bytes_written != CIFS_MF_SYMLINK_FILE_SIZE)
+		return -EIO;
+
+	return 0;
 }
 
 static int
@@ -430,7 +465,9 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
 	/* BB what if DFS and this volume is on different share? BB */
 	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
 		rc = CIFSCreateMFSymLink(xid, pTcon, full_path, symname,
-					 cifs_sb->local_nls);
+					 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);
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* Re: [PATCH 5/8] cifs: implement CIFSCheckMFSymlink()
       [not found]         ` <1280931109-22380-6-git-send-email-metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
@ 2010-08-04 14:22           ` Jeff Layton
  2010-08-05 12:44           ` Suresh Jayaraman
  1 sibling, 0 replies; 31+ messages in thread
From: Jeff Layton @ 2010-08-04 14:22 UTC (permalink / raw)
  To: Stefan Metzmacher
  Cc: smfrench-Re5JQEeQqe8AvxtiuMwx3w,
	linux-cifs-u79uwXL29TY76Z2rM5mHXA

On Wed,  4 Aug 2010 16:11:46 +0200
Stefan Metzmacher <metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org> wrote:

> Signed-off-by: Stefan Metzmacher <metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
> ---
>  fs/cifs/link.c |   65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 65 insertions(+), 0 deletions(-)
> 
> diff --git a/fs/cifs/link.c b/fs/cifs/link.c
> index 0d90a89..6cd0879 100644
> --- a/fs/cifs/link.c
> +++ b/fs/cifs/link.c
> @@ -114,6 +114,71 @@ CIFSCheckMFSymlink(struct cifs_fattr *fattr,
>  		   const unsigned char *path,
>  		   struct cifs_sb_info *cifs_sb, int xid)
>  {
> +	int rc;
> +	int oplock = 0;
> +	__u16 netfid = 0;
> +	struct cifsTconInfo *pTcon = cifs_sb->tcon;
> +	u8 *buf;
> +	char *pbuf;
> +	unsigned int bytes_read = 0;
> +	int buf_type = CIFS_NO_BUFFER;
> +	unsigned int link_len = 0;
> +	FILE_ALL_INFO file_info;
> +
> +	if (!(fattr->cf_mode & S_IFREG))
> +		/* it's not a symlink */
> +		return 0;
> +
> +	if (fattr->cf_eof != CIFS_MF_SYMLINK_FILE_SIZE)
> +		/* it's not a symlink */
> +		return 0;
> +
> +	buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL);
> +	if (!buf)
> +		return -ENOMEM;
> +	pbuf = buf;
> +
> +	rc = CIFSSMBOpen(xid, pTcon, path, FILE_OPEN, GENERIC_READ,
> +			 CREATE_NOT_DIR, &netfid, &oplock, &file_info,
> +			 cifs_sb->local_nls,
> +			 cifs_sb->mnt_cifs_flags &
> +				CIFS_MOUNT_MAP_SPECIAL_CHR);
> +	if (rc != 0) {
> +		kfree(buf);
> +		return rc;
> +	}
> +
> +	if (file_info.EndOfFile != CIFS_MF_SYMLINK_FILE_SIZE) {
> +		CIFSSMBClose(xid, pTcon, netfid);
> +		kfree(buf);
> +		/* it's not a symlink */
> +		return 0;
> +	}
> +

Might be better to move the kmalloc() here. If the open fails, or the
size is wrong you won't need the buffer. Allocating memory can lead to
reclaim events too, so it's best not to do it unless you really need it.

> +	/* Read header */
> +	rc = CIFSSMBRead(xid, pTcon, netfid,
> +			 CIFS_MF_SYMLINK_FILE_SIZE /* length */,
> +			 0 /* offset */,
> +			 &bytes_read, &pbuf, &buf_type);
> +	CIFSSMBClose(xid, pTcon, netfid);
> +	if (rc != 0) {
> +		kfree(buf);
> +		return rc;
> +	}
> +
> +	rc = CIFSParseMFSymlink(buf, bytes_read, &link_len, NULL);
> +	kfree(buf);
> +	if (rc == -EINVAL)
> +		/* it's not a symlink */
> +		return 0;
> +	if (rc != 0)
> +		return rc;
> +
> +	/* it is a symlink */
> +	fattr->cf_eof = link_len;
> +	fattr->cf_mode &= ~S_IFMT;
> +	fattr->cf_mode |= S_IFLNK;
> +	fattr->cf_dtype = DT_LNK;
>  	return 0;
>  }
>  


-- 
Jeff Layton <jlayton-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 3/8] cifs: add CIFSCheckMFSymlink() as stub
       [not found]         ` <1280931109-22380-4-git-send-email-metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
@ 2010-08-04 14:37           ` Jeff Layton
       [not found]             ` <20100804103748.521163e6-9yPaYZwiELC+kQycOl6kW4xkIHaj4LzF@public.gmane.org>
  0 siblings, 1 reply; 31+ messages in thread
From: Jeff Layton @ 2010-08-04 14:37 UTC (permalink / raw)
  To: Stefan Metzmacher
  Cc: smfrench-Re5JQEeQqe8AvxtiuMwx3w,
	linux-cifs-u79uwXL29TY76Z2rM5mHXA

On Wed,  4 Aug 2010 16:11:44 +0200
Stefan Metzmacher <metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org> wrote:

> Signed-off-by: Stefan Metzmacher <metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
> ---
>  fs/cifs/cifsproto.h |    3 +++
>  fs/cifs/inode.c     |    7 +++++++
>  fs/cifs/link.c      |    8 ++++++++
>  3 files changed, 18 insertions(+), 0 deletions(-)
> 
> diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
> index 2eaebbd..e94e095 100644
> --- a/fs/cifs/cifsproto.h
> +++ b/fs/cifs/cifsproto.h
> @@ -409,4 +409,7 @@ extern int CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
>  extern int CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
>  			const int netfid, __u64 *pExtAttrBits, __u64 *pMask);
>  extern void cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb);
> +extern int CIFSCheckMFSymlink(struct cifs_fattr *fattr,
> +		const unsigned char *path,
> +		struct cifs_sb_info *cifs_sb, int xid);
>  #endif			/* _CIFSPROTO_H */
> diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
> index a15b3a9..c4121de 100644
> --- a/fs/cifs/inode.c
> +++ b/fs/cifs/inode.c
> @@ -661,6 +661,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);
>  
> +	/* query for SFU type info if supported and needed */
> +	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);
> +	}
> +

		^^^^^^^^^^^^^^

This only seems to touch the codepath without posix extensions. What
about when unix extensions are enabled? The previous patch seems to
indicate that the behavior is that mfsymlinks are always used when that
mount option is used even if unix extensions are enabled. If so, then I
think you'll need a similar change in cifs_get_inode_info_unix.

>  	if (!*pinode) {
>  		*pinode = cifs_iget(sb, &fattr);
>  		if (!*pinode)
> diff --git a/fs/cifs/link.c b/fs/cifs/link.c
> index 2358a5f..985373c 100644
> --- a/fs/cifs/link.c
> +++ b/fs/cifs/link.c
> @@ -48,6 +48,14 @@ CIFSQueryMFSymLink(const int xid, struct cifsTconInfo *tcon,
>  }
>  
>  int
> +CIFSCheckMFSymlink(struct cifs_fattr *fattr,
> +		   const unsigned char *path,
> +		   struct cifs_sb_info *cifs_sb, int xid)
> +{
> +	return 0;
> +}
> +
> +int
>  cifs_hardlink(struct dentry *old_file, struct inode *inode,
>  	      struct dentry *direntry)
>  {


-- 
Jeff Layton <jlayton-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 1/8] cifs: add "mfsymlinks" mount option
       [not found]     ` <1280847960-16371-2-git-send-email-metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
@ 2010-08-05 11:44       ` Suresh Jayaraman
  0 siblings, 0 replies; 31+ messages in thread
From: Suresh Jayaraman @ 2010-08-05 11:44 UTC (permalink / raw)
  To: Stefan Metzmacher
  Cc: smfrench-Re5JQEeQqe8AvxtiuMwx3w,
	linux-cifs-u79uwXL29TY76Z2rM5mHXA

On 08/03/2010 08:35 PM, Stefan Metzmacher wrote:
> This is the start for an implementation of "Minshall+French Symlinks"
> (see http://wiki.samba.org/index.php/UNIX_Extensions#Minshall.2BFrench_symlinks).
> 
> Signed-off-by: Stefan Metzmacher <metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
> ---
>  fs/cifs/README       |    5 +++++
>  fs/cifs/cifs_fs_sb.h |    1 +
>  fs/cifs/cifsfs.c     |    2 ++
>  fs/cifs/connect.c    |   11 +++++++++++
>  4 files changed, 19 insertions(+), 0 deletions(-)
> 
> diff --git a/fs/cifs/README b/fs/cifs/README
> index a727b7c..228c239 100644
> --- a/fs/cifs/README
> +++ b/fs/cifs/README
> @@ -517,6 +517,11 @@ A partial list of the supported mount options follows:
>  		SFU does).  In the future the bottom 9 bits of the
>  		mode also will be emulated using queries of the security
>  		descriptor (ACL).
> + mfsymlinks     Enable support for Minshall+French symlinks
> +		(see http://wiki.samba.org/index.php/UNIX_Extensions#Minshall.2BFrench_symlinks)
> +		This option is ignored when specified together with the
> +		'sfu' option. Minshall+French symlinks are used event if

nit..  Did you mean "even" here?                               ^^^^

> +		the server supports the CIFS Unix Extensions.
>   sign           Must use packet signing (helps avoid unwanted data modification
>  		by intermediate systems in the route).  Note that signing
>  		does not work with lanman or plaintext authentication.
> diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
> index 2a43a0a..b3b8752 100644
> --- a/fs/cifs/connect.c
> +++ b/fs/cifs/connect.c
> @@ -100,6 +100,7 @@ struct smb_vol {
>  	bool noautotune:1;
>  	bool nostrictsync:1; /* do not force expensive SMBflush on every sync */
>  	bool fsc:1;	/* enable fscache */
> +	bool mfsymlinks:1; /* use Minshall+French Symlinks */
>  	unsigned int rsize;
>  	unsigned int wsize;
>  	bool sockopt_tcp_nodelay:1;
> @@ -1343,6 +1344,8 @@ cifs_parse_mount_options(char *options, const char *devname,
>  				"/proc/fs/cifs/LookupCacheEnabled to 0\n");
>  		} else if (strnicmp(data, "fsc", 3) == 0) {
>  			vol->fsc = true;
> +		} else if (strnicmp(data, "mfsymlinks", 22) == 0) {
				
 Why 22 here?


Thanks,


-- 
Suresh Jayaraman

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 2/8] cifs: add CIFSCreateMFSymLink() and CIFSQueryMFSymLink() as stubs
       [not found]     ` <1280847960-16371-3-git-send-email-metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
@ 2010-08-05 11:50       ` Suresh Jayaraman
  0 siblings, 0 replies; 31+ messages in thread
From: Suresh Jayaraman @ 2010-08-05 11:50 UTC (permalink / raw)
  To: Stefan Metzmacher
  Cc: smfrench-Re5JQEeQqe8AvxtiuMwx3w,
	linux-cifs-u79uwXL29TY76Z2rM5mHXA

On 08/03/2010 08:35 PM, Stefan Metzmacher wrote:
> Signed-off-by: Stefan Metzmacher <metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
> ---
>  fs/cifs/link.c |   34 ++++++++++++++++++++++++++++++----
>  1 files changed, 30 insertions(+), 4 deletions(-)
> 
> diff --git a/fs/cifs/link.c b/fs/cifs/link.c
> index 473ca80..2358a5f 100644
> --- a/fs/cifs/link.c
> +++ b/fs/cifs/link.c
> @@ -29,6 +29,24 @@
>  #include "cifs_debug.h"
>  #include "cifs_fs_sb.h"
>  
> +static int
> +CIFSCreateMFSymLink(const int xid, struct cifsTconInfo *tcon,
> +		    const char *fromName, const char *toName,
> +		    const struct nls_table *nls_codepage)
> +{
> +	int rc = -EOPNOTSUPP;
> +	return rc;
> +}
> +
> +static int
> +CIFSQueryMFSymLink(const int xid, struct cifsTconInfo *tcon,
> +		   const unsigned char *searchName, char **symlinkinfo,
> +		   const struct nls_table *nls_codepage)
> +{
> +	int rc = -EOPNOTSUPP;
> +	return rc;
> +}

Perhaps these two should be added to cifssmb.c because that is where the
other related functions are defined?

Thanks,

-- 
Suresh Jayaraman

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 3/8] cifs: add CIFSCheckMFSymlink() as stub
       [not found]             ` <20100804103748.521163e6-9yPaYZwiELC+kQycOl6kW4xkIHaj4LzF@public.gmane.org>
@ 2010-08-05 12:10               ` Suresh Jayaraman
       [not found]                 ` <4C5AAA3C.1000304-l3A5Bk7waGM@public.gmane.org>
  0 siblings, 1 reply; 31+ messages in thread
From: Suresh Jayaraman @ 2010-08-05 12:10 UTC (permalink / raw)
  To: Jeff Layton
  Cc: Stefan Metzmacher, smfrench-Re5JQEeQqe8AvxtiuMwx3w,
	linux-cifs-u79uwXL29TY76Z2rM5mHXA

On 08/04/2010 08:07 PM, Jeff Layton wrote:
> On Wed,  4 Aug 2010 16:11:44 +0200
> Stefan Metzmacher <metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org> wrote:
> 
>> Signed-off-by: Stefan Metzmacher <metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
>> ---
>>  fs/cifs/cifsproto.h |    3 +++
>>  fs/cifs/inode.c     |    7 +++++++
>>  fs/cifs/link.c      |    8 ++++++++
>>  3 files changed, 18 insertions(+), 0 deletions(-)
>>
>> diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
>> index 2eaebbd..e94e095 100644
>> --- a/fs/cifs/cifsproto.h
>> +++ b/fs/cifs/cifsproto.h
>> @@ -409,4 +409,7 @@ extern int CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
>>  extern int CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
>>  			const int netfid, __u64 *pExtAttrBits, __u64 *pMask);
>>  extern void cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb);
>> +extern int CIFSCheckMFSymlink(struct cifs_fattr *fattr,
>> +		const unsigned char *path,
>> +		struct cifs_sb_info *cifs_sb, int xid);
>>  #endif			/* _CIFSPROTO_H */
>> diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
>> index a15b3a9..c4121de 100644
>> --- a/fs/cifs/inode.c
>> +++ b/fs/cifs/inode.c
>> @@ -661,6 +661,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);
>>  
>> +	/* query for SFU type info if supported and needed */
>> +	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);
>> +	}
>> +
> 
> 		^^^^^^^^^^^^^^
> 
> This only seems to touch the codepath without posix extensions. What
> about when unix extensions are enabled? The previous patch seems to
> indicate that the behavior is that mfsymlinks are always used when that
> mount option is used even if unix extensions are enabled. If so, then I
> think you'll need a similar change in cifs_get_inode_info_unix.
> 

I initially thought so. But, looking again - there is no point in
querying for SFU type info if unix extensions are enabled..?

Thanks,


-- 
Suresh Jayaraman

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 3/8] cifs: add CIFSCheckMFSymlink() as stub
       [not found]                 ` <4C5AAA3C.1000304-l3A5Bk7waGM@public.gmane.org>
@ 2010-08-05 12:31                   ` Jeff Layton
       [not found]                     ` <20100805083113.2e7bfbb9-xSBYVWDuneFaJnirhKH9O4GKTjYczspe@public.gmane.org>
  0 siblings, 1 reply; 31+ messages in thread
From: Jeff Layton @ 2010-08-05 12:31 UTC (permalink / raw)
  To: Suresh Jayaraman
  Cc: Stefan Metzmacher, smfrench-Re5JQEeQqe8AvxtiuMwx3w,
	linux-cifs-u79uwXL29TY76Z2rM5mHXA

On Thu, 05 Aug 2010 17:40:36 +0530
Suresh Jayaraman <sjayaraman-l3A5Bk7waGM@public.gmane.org> wrote:

> On 08/04/2010 08:07 PM, Jeff Layton wrote:
> > On Wed,  4 Aug 2010 16:11:44 +0200
> > Stefan Metzmacher <metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org> wrote:
> > 
> >> Signed-off-by: Stefan Metzmacher <metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
> >> ---
> >>  fs/cifs/cifsproto.h |    3 +++
> >>  fs/cifs/inode.c     |    7 +++++++
> >>  fs/cifs/link.c      |    8 ++++++++
> >>  3 files changed, 18 insertions(+), 0 deletions(-)
> >>
> >> diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
> >> index 2eaebbd..e94e095 100644
> >> --- a/fs/cifs/cifsproto.h
> >> +++ b/fs/cifs/cifsproto.h
> >> @@ -409,4 +409,7 @@ extern int CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
> >>  extern int CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
> >>  			const int netfid, __u64 *pExtAttrBits, __u64 *pMask);
> >>  extern void cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb);
> >> +extern int CIFSCheckMFSymlink(struct cifs_fattr *fattr,
> >> +		const unsigned char *path,
> >> +		struct cifs_sb_info *cifs_sb, int xid);
> >>  #endif			/* _CIFSPROTO_H */
> >> diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
> >> index a15b3a9..c4121de 100644
> >> --- a/fs/cifs/inode.c
> >> +++ b/fs/cifs/inode.c
> >> @@ -661,6 +661,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);
> >>  
> >> +	/* query for SFU type info if supported and needed */
> >> +	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);
> >> +	}
> >> +
> > 
> > 		^^^^^^^^^^^^^^
> > 
> > This only seems to touch the codepath without posix extensions. What
> > about when unix extensions are enabled? The previous patch seems to
> > indicate that the behavior is that mfsymlinks are always used when that
> > mount option is used even if unix extensions are enabled. If so, then I
> > think you'll need a similar change in cifs_get_inode_info_unix.
> > 
> 
> I initially thought so. But, looking again - there is no point in
> querying for SFU type info if unix extensions are enabled..?
> 
> Thanks,
> 

I'm not sure that addresses the concern. It's very confusing, but:

    SFU != POSIX extensions

The SFU codepath goes through the "normal" cifs code
(cifs_get_inode_info). The POSIX extensions codepath goes through a
different codepath (cifs_get_inode_info_unix). Yes, all of this is
sorely in need of being cleaned up, but that's the way it works today...

Metze's patches seem to indicate that mfsymlinks and unix extensions
aren't mutually exclusive. The unix codepaths that determine inode
type and fill out inode data should be using the mfsymlink stuff too.

-- 
Jeff Layton <jlayton-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 5/8] cifs: implement CIFSCheckMFSymlink()
       [not found]         ` <1280931109-22380-6-git-send-email-metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
  2010-08-04 14:22           ` Jeff Layton
@ 2010-08-05 12:44           ` Suresh Jayaraman
       [not found]             ` <4C5AB228.90800-l3A5Bk7waGM@public.gmane.org>
  1 sibling, 1 reply; 31+ messages in thread
From: Suresh Jayaraman @ 2010-08-05 12:44 UTC (permalink / raw)
  To: Stefan Metzmacher
  Cc: smfrench-Re5JQEeQqe8AvxtiuMwx3w,
	linux-cifs-u79uwXL29TY76Z2rM5mHXA

On 08/04/2010 07:41 PM, Stefan Metzmacher wrote:
> Signed-off-by: Stefan Metzmacher <metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
> ---
>  fs/cifs/link.c |   65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 65 insertions(+), 0 deletions(-)
> 
> diff --git a/fs/cifs/link.c b/fs/cifs/link.c
> index 0d90a89..6cd0879 100644
> --- a/fs/cifs/link.c
> +++ b/fs/cifs/link.c
> @@ -114,6 +114,71 @@ CIFSCheckMFSymlink(struct cifs_fattr *fattr,
>  		   const unsigned char *path,
>  		   struct cifs_sb_info *cifs_sb, int xid)
>  {
> +	int rc;
> +	int oplock = 0;
> +	__u16 netfid = 0;
> +	struct cifsTconInfo *pTcon = cifs_sb->tcon;
> +	u8 *buf;
> +	char *pbuf;
> +	unsigned int bytes_read = 0;
> +	int buf_type = CIFS_NO_BUFFER;
> +	unsigned int link_len = 0;
> +	FILE_ALL_INFO file_info;
> +
> +	if (!(fattr->cf_mode & S_IFREG))
> +		/* it's not a symlink */
> +		return 0;

Perhaps a little naive - what if cf_mode is S_IFDIR?

Thanks,


-- 
Suresh Jayaraman

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 5/8] cifs: implement CIFSCheckMFSymlink()
       [not found]             ` <4C5AB228.90800-l3A5Bk7waGM@public.gmane.org>
@ 2010-08-05 15:47               ` Stefan (metze) Metzmacher
  0 siblings, 0 replies; 31+ messages in thread
From: Stefan (metze) Metzmacher @ 2010-08-05 15:47 UTC (permalink / raw)
  To: Suresh Jayaraman
  Cc: smfrench-Re5JQEeQqe8AvxtiuMwx3w,
	linux-cifs-u79uwXL29TY76Z2rM5mHXA

[-- Attachment #1: Type: text/plain, Size: 1120 bytes --]

Am 05.08.2010 14:44, schrieb Suresh Jayaraman:
> On 08/04/2010 07:41 PM, Stefan Metzmacher wrote:
>> Signed-off-by: Stefan Metzmacher <metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
>> ---
>>  fs/cifs/link.c |   65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>>  1 files changed, 65 insertions(+), 0 deletions(-)
>>
>> diff --git a/fs/cifs/link.c b/fs/cifs/link.c
>> index 0d90a89..6cd0879 100644
>> --- a/fs/cifs/link.c
>> +++ b/fs/cifs/link.c
>> @@ -114,6 +114,71 @@ CIFSCheckMFSymlink(struct cifs_fattr *fattr,
>>  		   const unsigned char *path,
>>  		   struct cifs_sb_info *cifs_sb, int xid)
>>  {
>> +	int rc;
>> +	int oplock = 0;
>> +	__u16 netfid = 0;
>> +	struct cifsTconInfo *pTcon = cifs_sb->tcon;
>> +	u8 *buf;
>> +	char *pbuf;
>> +	unsigned int bytes_read = 0;
>> +	int buf_type = CIFS_NO_BUFFER;
>> +	unsigned int link_len = 0;
>> +	FILE_ALL_INFO file_info;
>> +
>> +	if (!(fattr->cf_mode & S_IFREG))
>> +		/* it's not a symlink */
>> +		return 0;
> 
> Perhaps a little naive - what if cf_mode is S_IFDIR?

Then it's a directory and not a symlink.

metze


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 262 bytes --]

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 3/8] cifs: add CIFSCheckMFSymlink() as stub
       [not found]                     ` <20100805083113.2e7bfbb9-xSBYVWDuneFaJnirhKH9O4GKTjYczspe@public.gmane.org>
@ 2010-08-09 14:04                       ` Stefan (metze) Metzmacher
       [not found]                         ` <4C600AEA.607-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
  0 siblings, 1 reply; 31+ messages in thread
From: Stefan (metze) Metzmacher @ 2010-08-09 14:04 UTC (permalink / raw)
  To: Jeff Layton
  Cc: Suresh Jayaraman, smfrench-Re5JQEeQqe8AvxtiuMwx3w,
	linux-cifs-u79uwXL29TY76Z2rM5mHXA

[-- Attachment #1: Type: text/plain, Size: 5041 bytes --]

Hi,

I noticed that I also need to hook the cifs_readdir() path.

Can someone tell me how I can construct the file name
relative to the mount point. The TODO in this change.

--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -679,7 +679,7 @@ static int cifs_get_name_from_search_buf(struct qstr
*pqst,
        return rc;
 }

-static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t
filldir,
+static int cifs_filldir(int xid, char *pfindEntry, struct file *file,
filldir_t filldir,
                        void *direntry, char *scratch_buf, unsigned int
max_len)
 {
        int rc = 0;
@@ -731,6 +731,15 @@ static int cifs_filldir(char *pfindEntry, struct
file *file, filldir_t filldir,
                cifs_dir_info_to_fattr(&fattr, (FILE_DIRECTORY_INFO *)
                                        pfindEntry, cifs_sb);

+       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
+               int tmprc;
+               const char *full_path = qstring.name;
+               /* TODO: build full path relative to the mount point */
+               tmprc = CIFSCheckMFSymlink(&fattr, full_path, cifs_sb, xid);
+               if (tmprc)
+                       cFYI(1, "CIFSCheckMFSymlink: %d", tmprc);
+       }
+
        if (inum && (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
                fattr.cf_uniqueid = inum;
        } else {
@@ -856,7 +865,7 @@ int cifs_readdir(struct file *file, void *direntry,
filldir_t filldir)
                        }
                        /* if buggy server returns . and .. late do
                        we want to check for that here? */
-                       rc = cifs_filldir(current_entry, file,
+                       rc = cifs_filldir(xid, current_entry, file,
                                        filldir, direntry, tmp_buf,
max_len);
                        if (rc == -EOVERFLOW) {
                                rc = 0;

metze

Am 05.08.2010 14:31, schrieb Jeff Layton:
> On Thu, 05 Aug 2010 17:40:36 +0530
> Suresh Jayaraman <sjayaraman-l3A5Bk7waGM@public.gmane.org> wrote:
> 
>> On 08/04/2010 08:07 PM, Jeff Layton wrote:
>>> On Wed,  4 Aug 2010 16:11:44 +0200
>>> Stefan Metzmacher <metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org> wrote:
>>>
>>>> Signed-off-by: Stefan Metzmacher <metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
>>>> ---
>>>>  fs/cifs/cifsproto.h |    3 +++
>>>>  fs/cifs/inode.c     |    7 +++++++
>>>>  fs/cifs/link.c      |    8 ++++++++
>>>>  3 files changed, 18 insertions(+), 0 deletions(-)
>>>>
>>>> diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
>>>> index 2eaebbd..e94e095 100644
>>>> --- a/fs/cifs/cifsproto.h
>>>> +++ b/fs/cifs/cifsproto.h
>>>> @@ -409,4 +409,7 @@ extern int CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
>>>>  extern int CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
>>>>  			const int netfid, __u64 *pExtAttrBits, __u64 *pMask);
>>>>  extern void cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb);
>>>> +extern int CIFSCheckMFSymlink(struct cifs_fattr *fattr,
>>>> +		const unsigned char *path,
>>>> +		struct cifs_sb_info *cifs_sb, int xid);
>>>>  #endif			/* _CIFSPROTO_H */
>>>> diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
>>>> index a15b3a9..c4121de 100644
>>>> --- a/fs/cifs/inode.c
>>>> +++ b/fs/cifs/inode.c
>>>> @@ -661,6 +661,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);
>>>>  
>>>> +	/* query for SFU type info if supported and needed */
>>>> +	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);
>>>> +	}
>>>> +
>>>
>>> 		^^^^^^^^^^^^^^
>>>
>>> This only seems to touch the codepath without posix extensions. What
>>> about when unix extensions are enabled? The previous patch seems to
>>> indicate that the behavior is that mfsymlinks are always used when that
>>> mount option is used even if unix extensions are enabled. If so, then I
>>> think you'll need a similar change in cifs_get_inode_info_unix.
>>>
>>
>> I initially thought so. But, looking again - there is no point in
>> querying for SFU type info if unix extensions are enabled..?
>>
>> Thanks,
>>
> 
> I'm not sure that addresses the concern. It's very confusing, but:
> 
>     SFU != POSIX extensions
> 
> The SFU codepath goes through the "normal" cifs code
> (cifs_get_inode_info). The POSIX extensions codepath goes through a
> different codepath (cifs_get_inode_info_unix). Yes, all of this is
> sorely in need of being cleaned up, but that's the way it works today...
> 
> Metze's patches seem to indicate that mfsymlinks and unix extensions
> aren't mutually exclusive. The unix codepaths that determine inode
> type and fill out inode data should be using the mfsymlink stuff too.
> 


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 262 bytes --]

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 3/8] cifs: add CIFSCheckMFSymlink() as stub
       [not found]                         ` <4C600AEA.607-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
@ 2010-08-09 14:16                           ` Suresh Jayaraman
  0 siblings, 0 replies; 31+ messages in thread
From: Suresh Jayaraman @ 2010-08-09 14:16 UTC (permalink / raw)
  To: Stefan (metze) Metzmacher
  Cc: Jeff Layton, smfrench-Re5JQEeQqe8AvxtiuMwx3w,
	linux-cifs-u79uwXL29TY76Z2rM5mHXA

On 08/09/2010 07:34 PM, Stefan (metze) Metzmacher wrote:
> Hi,
> 
> I noticed that I also need to hook the cifs_readdir() path.
> 
> Can someone tell me how I can construct the file name
> relative to the mount point. The TODO in this change.

build_path_from_dentry() ?


-- 
Suresh Jayaraman

^ permalink raw reply	[flat|nested] 31+ messages in thread

end of thread, other threads:[~2010-08-09 14:16 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-08-03 15:05 [CIFS] Support for Minshall+French symlinks Stefan Metzmacher
     [not found] ` <1280847960-16371-1-git-send-email-metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
2010-08-03 15:05   ` [PATCH 1/8] cifs: add "mfsymlinks" mount option Stefan Metzmacher
     [not found]     ` <1280847960-16371-2-git-send-email-metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
2010-08-05 11:44       ` Suresh Jayaraman
2010-08-03 15:05   ` [PATCH 2/8] cifs: add CIFSCreateMFSymLink() and CIFSQueryMFSymLink() as stubs Stefan Metzmacher
     [not found]     ` <1280847960-16371-3-git-send-email-metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
2010-08-05 11:50       ` Suresh Jayaraman
2010-08-03 15:05   ` [PATCH 3/8] cifs: add CIFSCheckMFSymlink() as stub Stefan Metzmacher
2010-08-03 15:05   ` [PATCH 4/8] cifs: implement CIFSParseMFSymlink() Stefan Metzmacher
2010-08-03 15:05   ` [PATCH 5/8] cifs: implement CIFSCheckMFSymlink() Stefan Metzmacher
2010-08-03 15:05   ` [PATCH 6/8] cifs: implement CIFSQueryMFSymLink() Stefan Metzmacher
     [not found]     ` <1280847960-16371-7-git-send-email-metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
2010-08-03 16:31       ` Jeff Layton
2010-08-03 15:05   ` [PATCH 7/8] cifs: implement CIFSFormatMFSymlink() Stefan Metzmacher
2010-08-03 15:06   ` [PATCH 8/8] cifs: implement CIFSCreateMFSymLink() Stefan Metzmacher
     [not found]     ` <1280847960-16371-9-git-send-email-metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
2010-08-03 15:29       ` Jeff Layton
2010-08-03 18:00   ` [CIFS] Support for Minshall+French symlinks Steve French
     [not found]     ` <AANLkTinJ1WRBT_Q3TqOZdMQExV66LSUAPG4c01yK-XRK-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2010-08-04 14:11       ` Stefan Metzmacher
2010-08-04 14:11       ` [PATCH 1/8] cifs: add "mfsymlinks" mount option Stefan Metzmacher
2010-08-04 14:11       ` [PATCH 2/8] cifs: add CIFSCreateMFSymLink() and CIFSQueryMFSymLink() as stubs Stefan Metzmacher
2010-08-04 14:11       ` [PATCH 3/8] cifs: add CIFSCheckMFSymlink() as stub Stefan Metzmacher
     [not found]         ` <1280931109-22380-4-git-send-email-metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
2010-08-04 14:37           ` Jeff Layton
     [not found]             ` <20100804103748.521163e6-9yPaYZwiELC+kQycOl6kW4xkIHaj4LzF@public.gmane.org>
2010-08-05 12:10               ` Suresh Jayaraman
     [not found]                 ` <4C5AAA3C.1000304-l3A5Bk7waGM@public.gmane.org>
2010-08-05 12:31                   ` Jeff Layton
     [not found]                     ` <20100805083113.2e7bfbb9-xSBYVWDuneFaJnirhKH9O4GKTjYczspe@public.gmane.org>
2010-08-09 14:04                       ` Stefan (metze) Metzmacher
     [not found]                         ` <4C600AEA.607-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
2010-08-09 14:16                           ` Suresh Jayaraman
2010-08-04 14:11       ` [PATCH 4/8] cifs: implement CIFSParseMFSymlink() Stefan Metzmacher
2010-08-04 14:11       ` [PATCH 5/8] cifs: implement CIFSCheckMFSymlink() Stefan Metzmacher
     [not found]         ` <1280931109-22380-6-git-send-email-metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
2010-08-04 14:22           ` Jeff Layton
2010-08-05 12:44           ` Suresh Jayaraman
     [not found]             ` <4C5AB228.90800-l3A5Bk7waGM@public.gmane.org>
2010-08-05 15:47               ` Stefan (metze) Metzmacher
2010-08-04 14:11       ` [PATCH 6/8] cifs: implement CIFSQueryMFSymLink() Stefan Metzmacher
2010-08-04 14:11       ` [PATCH 7/8] cifs: implement CIFSFormatMFSymlink() Stefan Metzmacher
2010-08-04 14:11       ` [PATCH 8/8] cifs: implement CIFSCreateMFSymLink() Stefan Metzmacher

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).