public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: "Pali Rohár" <pali@kernel.org>
To: Steve French <sfrench@samba.org>,
	Paulo Alcantara <pc@manguebit.com>,
	Ronnie Sahlberg <ronniesahlberg@gmail.com>
Cc: linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH v2 4/7] cifs: Add support for creating NFS-style symlinks
Date: Sat, 12 Oct 2024 10:56:01 +0200	[thread overview]
Message-ID: <20241012085601.694-1-pali@kernel.org> (raw)
In-Reply-To: <20241012085252.560-1-pali@kernel.org>

CIFS client is currently able to parse NFS-style symlinks, but is not able
to create them. This functionality is useful when the mounted SMB share is
used also by Windows NFS server (on Windows Server 2012 or new). It allows
interop of symlinks between SMB share mounted by Linux CIFS client and same
export from Windows NFS server mounted by some NFS client.

New symlinks would be created in NFS-style only in case the mount option
-o reparse=nfs is specified, which is not by default. So default CIFS
mounts are not affected by this change.

Signed-off-by: Pali Rohár <pali@kernel.org>
---
 fs/smb/client/reparse.c | 47 ++++++++++++++++++++++++++++++++++-------
 1 file changed, 39 insertions(+), 8 deletions(-)

diff --git a/fs/smb/client/reparse.c b/fs/smb/client/reparse.c
index 57320a4c4d79..cd12704cae0c 100644
--- a/fs/smb/client/reparse.c
+++ b/fs/smb/client/reparse.c
@@ -406,6 +406,8 @@ static int create_native_socket(const unsigned int xid, struct inode *inode,
 
 static int nfs_set_reparse_buf(struct reparse_posix_data *buf,
 			       mode_t mode, dev_t dev,
+			       __le16 *symname_utf16,
+			       int symname_utf16_len,
 			       struct kvec *iov)
 {
 	u64 type;
@@ -416,13 +418,18 @@ static int nfs_set_reparse_buf(struct reparse_posix_data *buf,
 	switch ((type = reparse_mode_nfs_type(mode))) {
 	case NFS_SPECFILE_BLK:
 	case NFS_SPECFILE_CHR:
-		dlen = sizeof(__le64);
+		dlen = 2 * sizeof(__le32);
+		((__le32 *)buf->DataBuffer)[0] = MAJOR(dev);
+		((__le32 *)buf->DataBuffer)[1] = MINOR(dev);
+		break;
+	case NFS_SPECFILE_LNK:
+		dlen = symname_utf16_len;
+		memcpy(buf->DataBuffer, symname_utf16, symname_utf16_len);
 		break;
 	case NFS_SPECFILE_FIFO:
 	case NFS_SPECFILE_SOCK:
 		dlen = 0;
 		break;
-	case NFS_SPECFILE_LNK: /* TODO: add support for NFS symlinks */
 	default:
 		return -EOPNOTSUPP;
 	}
@@ -432,8 +439,6 @@ static int nfs_set_reparse_buf(struct reparse_posix_data *buf,
 	buf->InodeType = cpu_to_le64(type);
 	buf->ReparseDataLength = cpu_to_le16(len + dlen -
 					     sizeof(struct reparse_data_buffer));
-	*(__le64 *)buf->DataBuffer = cpu_to_le64(((u64)MINOR(dev) << 32) |
-						 MAJOR(dev));
 	iov->iov_base = buf;
 	iov->iov_len = len + dlen;
 	return 0;
@@ -444,21 +449,42 @@ static int mknod_nfs(unsigned int xid, struct inode *inode,
 		     const char *full_path, umode_t mode, dev_t dev,
 		     const char *symname)
 {
+	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
 	struct cifs_open_info_data data;
-	struct reparse_posix_data *p;
+	struct reparse_posix_data *p = NULL;
+	__le16 *symname_utf16 = NULL;
+	int symname_utf16_len = 0;
 	struct inode *new;
 	struct kvec iov;
 	__u8 buf[sizeof(*p) + sizeof(__le64)];
 	int rc;
 
-	p = (struct reparse_posix_data *)buf;
-	rc = nfs_set_reparse_buf(p, mode, dev, &iov);
+	if (S_ISLNK(mode)) {
+		symname_utf16 = cifs_strndup_to_utf16(symname, strlen(symname),
+						      &symname_utf16_len,
+						      cifs_sb->local_nls,
+						      NO_MAP_UNI_RSVD);
+		if (!symname_utf16) {
+			rc = -ENOMEM;
+			goto out;
+		}
+		symname_utf16_len -= 2; /* symlink is without trailing wide-nul */
+		p = kzalloc(sizeof(*p) + symname_utf16_len, GFP_KERNEL);
+		if (!p) {
+			rc = -ENOMEM;
+			goto out;
+		}
+	} else {
+		p = (struct reparse_posix_data *)buf;
+	}
+	rc = nfs_set_reparse_buf(p, mode, dev, symname_utf16, symname_utf16_len, &iov);
 	if (rc)
-		return rc;
+		goto out;
 
 	data = (struct cifs_open_info_data) {
 		.reparse_point = true,
 		.reparse = { .tag = IO_REPARSE_TAG_NFS, .posix = p, },
+		.symlink_target = kstrdup(symname, GFP_KERNEL),
 	};
 
 	new = smb2_get_reparse_inode(&data, inode->i_sb, xid,
@@ -468,6 +494,11 @@ static int mknod_nfs(unsigned int xid, struct inode *inode,
 	else
 		rc = PTR_ERR(new);
 	cifs_free_open_info(&data);
+out:
+	if (S_ISLNK(mode)) {
+		kfree(symname_utf16);
+		kfree(p);
+	}
 	return rc;
 }
 
-- 
2.20.1


  parent reply	other threads:[~2024-10-12  8:56 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-10-06 10:00 [PATCH 0/7] cifs: Improve mount option -o reparse and support for native Windows sockets Pali Rohár
2024-10-06 10:00 ` [PATCH 1/7] cifs: Add mount option -o reparse=native Pali Rohár
2024-10-07  4:28   ` Steve French
2024-10-07 18:36     ` Pali Rohár
     [not found]       ` <CAH2r5mttO-aDq94QrLQm10xJRGLg=PULqX9fcfoykAweVVO+uQ@mail.gmail.com>
2024-10-10 22:21         ` Steve French
2024-10-10 22:38           ` Pali Rohár
     [not found]             ` <CAH2r5msEiD05ehJs_a05sP_rX7BkVH-9LZp8Sj6EFbpZA9bfrg@mail.gmail.com>
2024-10-10 22:44               ` Pali Rohár
2024-10-06 10:00 ` [PATCH 2/7] cifs: Add mount option -o reparse=none Pali Rohár
2024-10-06 10:00 ` [PATCH 3/7] cifs: Add support for creating native Windows sockets Pali Rohár
2024-10-10 21:47   ` Pali Rohár
2024-10-06 10:00 ` [PATCH 4/7] cifs: Add support for creating NFS-style symlinks Pali Rohár
2024-10-06 10:00 ` [PATCH 5/7] cifs: Improve guard for excluding $LXDEV xattr Pali Rohár
2024-10-06 10:00 ` [PATCH 6/7] cifs: Add support for creating WSL-style symlinks Pali Rohár
2024-10-10 21:50   ` Pali Rohár
2024-10-06 10:00 ` [PATCH 7/7] cifs: Validate content of WSL reparse point buffers Pali Rohár
2024-10-12  8:52 ` [PATCH v2 0/7] Allow to choose symlink and socket type Pali Rohár
2024-10-12  8:55   ` [PATCH v2 1/7] cifs: Add mount option -o symlink= for choosing symlink create type Pali Rohár
2024-10-12  8:55   ` [PATCH v2 2/7] cifs: Add mount option -o reparse=none Pali Rohár
2024-10-12  8:55   ` [PATCH v2 3/7] cifs: Add support for creating native Windows sockets Pali Rohár
2024-10-12  8:56   ` Pali Rohár [this message]
2024-12-09 18:00     ` [PATCH v2 4/7] cifs: Add support for creating NFS-style symlinks Pali Rohár
2024-10-12  8:56   ` [PATCH v2 5/7] cifs: Improve guard for excluding $LXDEV xattr Pali Rohár
2024-10-12  8:56   ` [PATCH v2 6/7] cifs: Add support for creating WSL-style symlinks Pali Rohár
2024-10-12  8:56   ` [PATCH v2 7/7] cifs: Validate content of WSL reparse point buffers Pali Rohár
     [not found]   ` <CAH2r5mtGqqM35Cy5k9NN=X05rTZPk-adhb7LgoV8PGNVL9P6FQ@mail.gmail.com>
2024-10-13  4:19     ` Fwd: [PATCH v2 0/7] Allow to choose symlink and socket type Steve French
2024-10-13  8:59     ` Pali Rohár
2024-10-13 13:38     ` Pali Rohár
2024-10-14  9:32       ` Pali Rohár
2024-10-28 10:13   ` Pali Rohár

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20241012085601.694-1-pali@kernel.org \
    --to=pali@kernel.org \
    --cc=linux-cifs@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=pc@manguebit.com \
    --cc=ronniesahlberg@gmail.com \
    --cc=sfrench@samba.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox