From: "Pali Rohár" <pali@kernel.org>
To: Paulo Alcantara <pc@manguebit.org>, Namjae Jeon <linkinjeon@kernel.org>
Cc: linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH 9/9] cifs: Add support for creating WSL symlinks in version 1 format
Date: Tue, 13 Oct 2026 10:48:27 +0200 [thread overview]
Message-ID: <20261013084827.ulqi2u2eebb4i3ay@pali> (raw)
In-Reply-To: <20260825230622.24617-10-pali@kernel.org>
On Wednesday 26 August 2026 01:06:22 Pali Rohár wrote:
> Add a new mount option -o symlink=wsl1 which cause that all newly created
> symlinks would be of WSL style in layout version 1 format. This type of
> symlinks is supported by all WSL versions.
>
> Existing mount option -o symlink=wsl will be now an alias to -o
> symlink=wsl2 which creates symlinks in layout version 2 format.
>
> Signed-off-by: Pali Rohár <pali@kernel.org>
> ---
> fs/smb/client/cifsglob.h | 9 +++--
> fs/smb/client/fs_context.c | 11 ++++--
> fs/smb/client/fs_context.h | 3 +-
> fs/smb/client/link.c | 3 +-
> fs/smb/client/reparse.c | 74 ++++++++++++++++++++++++++++++++------
> 5 files changed, 82 insertions(+), 18 deletions(-)
>
> diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h
> index c5fdc0138165..66d4370f37dc 100644
> --- a/fs/smb/client/cifsglob.h
> +++ b/fs/smb/client/cifsglob.h
> @@ -190,7 +190,8 @@ enum cifs_symlink_type {
> CIFS_SYMLINK_TYPE_MFSYMLINKS,
> CIFS_SYMLINK_TYPE_SFU,
> CIFS_SYMLINK_TYPE_NFS,
> - CIFS_SYMLINK_TYPE_WSL,
> + CIFS_SYMLINK_TYPE_WSL1,
> + CIFS_SYMLINK_TYPE_WSL2,
> };
>
> static inline const char *cifs_symlink_type_str(enum cifs_symlink_type type)
> @@ -208,8 +209,10 @@ static inline const char *cifs_symlink_type_str(enum cifs_symlink_type type)
> return "sfu";
> case CIFS_SYMLINK_TYPE_NFS:
> return "nfs";
> - case CIFS_SYMLINK_TYPE_WSL:
> - return "wsl";
> + case CIFS_SYMLINK_TYPE_WSL1:
> + return "wsl1";
> + case CIFS_SYMLINK_TYPE_WSL2:
> + return "wsl2";
> default:
> return "unknown";
> }
> diff --git a/fs/smb/client/fs_context.c b/fs/smb/client/fs_context.c
> index abc29500a664..3e8e4b43690a 100644
> --- a/fs/smb/client/fs_context.c
> +++ b/fs/smb/client/fs_context.c
> @@ -376,7 +376,9 @@ static const match_table_t symlink_flavor_tokens = {
> { Opt_symlink_mfsymlinks, "mfsymlinks" },
> { Opt_symlink_sfu, "sfu" },
> { Opt_symlink_nfs, "nfs" },
> - { Opt_symlink_wsl, "wsl" },
> + { Opt_symlink_wsl1, "wsl1" },
> + { Opt_symlink_wsl2, "wsl2" },
> + { Opt_symlink_wsl2, "wsl" }, /* wsl - alias for wsl2 */
> { Opt_symlink_err, NULL },
> };
>
> @@ -407,8 +409,11 @@ static int parse_symlink_flavor(struct fs_context *fc, char *value,
> case Opt_symlink_nfs:
> ctx->symlink_type = CIFS_SYMLINK_TYPE_NFS;
> break;
> - case Opt_symlink_wsl:
> - ctx->symlink_type = CIFS_SYMLINK_TYPE_WSL;
> + case Opt_symlink_wsl1:
> + ctx->symlink_type = CIFS_SYMLINK_TYPE_WSL1;
> + break;
> + case Opt_symlink_wsl2:
> + ctx->symlink_type = CIFS_SYMLINK_TYPE_WSL2;
> break;
> default:
> cifs_errorf(fc, "bad symlink= option: %s\n", value);
> diff --git a/fs/smb/client/fs_context.h b/fs/smb/client/fs_context.h
> index a80a5caff23c..56bbb20a30a3 100644
> --- a/fs/smb/client/fs_context.h
> +++ b/fs/smb/client/fs_context.h
> @@ -72,7 +72,8 @@ enum cifs_symlink_parm {
> Opt_symlink_mfsymlinks,
> Opt_symlink_sfu,
> Opt_symlink_nfs,
> - Opt_symlink_wsl,
> + Opt_symlink_wsl1,
> + Opt_symlink_wsl2,
> Opt_symlink_err
> };
>
> diff --git a/fs/smb/client/link.c b/fs/smb/client/link.c
> index 8d5d6aca742a..fd7203aa0917 100644
> --- a/fs/smb/client/link.c
> +++ b/fs/smb/client/link.c
> @@ -604,7 +604,8 @@ cifs_symlink(struct mnt_idmap *idmap, struct inode *inode,
>
> case CIFS_SYMLINK_TYPE_NATIVE:
> case CIFS_SYMLINK_TYPE_NFS:
> - case CIFS_SYMLINK_TYPE_WSL:
> + case CIFS_SYMLINK_TYPE_WSL1:
> + case CIFS_SYMLINK_TYPE_WSL2:
> if (CIFS_REPARSE_SUPPORT(pTcon)) {
> rc = create_reparse_symlink(xid, inode, direntry, pTcon,
> full_path, symname);
> diff --git a/fs/smb/client/reparse.c b/fs/smb/client/reparse.c
> index bed6f764c0bc..8db3e4917788 100644
> --- a/fs/smb/client/reparse.c
> +++ b/fs/smb/client/reparse.c
> @@ -22,7 +22,7 @@ static int mknod_nfs(unsigned int xid, struct inode *inode,
> static int mknod_wsl(unsigned int xid, struct inode *inode,
> struct dentry *dentry, struct cifs_tcon *tcon,
> const char *full_path, umode_t mode, dev_t dev,
> - const char *symname);
> + const char *symname, int symver);
>
> static int create_native_symlink(const unsigned int xid, struct inode *inode,
> struct dentry *dentry, struct cifs_tcon *tcon,
> @@ -43,8 +43,10 @@ int create_reparse_symlink(const unsigned int xid, struct inode *inode,
> return create_native_symlink(xid, inode, dentry, tcon, full_path, symname);
> case CIFS_SYMLINK_TYPE_NFS:
> return mknod_nfs(xid, inode, dentry, tcon, full_path, S_IFLNK, 0, symname);
> - case CIFS_SYMLINK_TYPE_WSL:
> - return mknod_wsl(xid, inode, dentry, tcon, full_path, S_IFLNK, 0, symname);
> + case CIFS_SYMLINK_TYPE_WSL1:
> + return mknod_wsl(xid, inode, dentry, tcon, full_path, S_IFLNK, 0, symname, 1);
> + case CIFS_SYMLINK_TYPE_WSL2:
> + return mknod_wsl(xid, inode, dentry, tcon, full_path, S_IFLNK, 0, symname, 2);
> default:
> return -EOPNOTSUPP;
> }
> @@ -554,6 +556,7 @@ static int mknod_nfs(unsigned int xid, struct inode *inode,
>
> static int wsl_set_reparse_buf(struct reparse_data_buffer **buf,
> mode_t mode, const char *symname,
> + int symver,
> struct cifs_sb_info *cifs_sb,
> struct kvec *iov)
> {
> @@ -589,15 +592,20 @@ static int wsl_set_reparse_buf(struct reparse_data_buffer **buf,
> kfree(symname_utf16);
> return -ENOMEM;
> }
> - /* Version field must be set to 2 (MS-FSCC 2.1.2.7) */
> - symlink_buf->Version = cpu_to_le32(2);
> - /* Target for Version 2 is in UTF-8 but without trailing null-term byte */
> + symlink_buf->Version = cpu_to_le32(symver);
> + /* Target is in UTF-8 but without trailing null-term byte */
> symname_utf8_len = utf16s_to_utf8s((wchar_t *)symname_utf16, symname_utf16_len/2,
> UTF16_LITTLE_ENDIAN,
> symlink_buf->Target,
> symname_utf8_maxlen);
> *buf = (struct reparse_data_buffer *)symlink_buf;
> - buf_len = sizeof(struct reparse_wsl_symlink_data_buffer) + symname_utf8_len;
> + buf_len = sizeof(struct reparse_wsl_symlink_data_buffer);
> + /*
> + * Layout version 2 stores the symlink target in the reparse point buffer.
> + * Layout version 1 stores the symlink target in the data section of the file.
> + */
> + if (symver == 2)
> + buf_len += symname_utf8_len;
> kfree(symname_utf16);
> break;
> default:
> @@ -698,7 +706,7 @@ static int wsl_set_xattrs(struct inode *inode, umode_t _mode,
> static int mknod_wsl(unsigned int xid, struct inode *inode,
> struct dentry *dentry, struct cifs_tcon *tcon,
> const char *full_path, umode_t mode, dev_t dev,
> - const char *symname)
> + const char *symname, int symver)
> {
> struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
> struct cifs_open_info_data data;
> @@ -707,6 +715,12 @@ static int mknod_wsl(unsigned int xid, struct inode *inode,
> struct inode *new;
> unsigned int len;
> struct kvec reparse_iov, xattr_iov;
> + struct cifs_open_parms oparms;
> + struct cifs_io_parms io_parms;
> + unsigned int bytes_written;
> + struct kvec symv1_iov[2];
> + struct cifs_fid fid;
> + __u32 oplock;
> int rc;
>
> /*
> @@ -716,7 +730,7 @@ static int mknod_wsl(unsigned int xid, struct inode *inode,
> if (!(le32_to_cpu(tcon->fsAttrInfo.Attributes) & FILE_SUPPORTS_EXTENDED_ATTRIBUTES))
> return -EOPNOTSUPP;
>
> - rc = wsl_set_reparse_buf(&buf, mode, symname, cifs_sb, &reparse_iov);
> + rc = wsl_set_reparse_buf(&buf, mode, symname, symver, cifs_sb, &reparse_iov);
> if (rc)
> return rc;
>
> @@ -741,6 +755,46 @@ static int mknod_wsl(unsigned int xid, struct inode *inode,
> &data, inode->i_sb,
> xid, tcon, full_path, false,
> &reparse_iov, &xattr_iov);
> + if (!IS_ERR(new) && mode == S_IFLNK && symver == 1) {
> + /*
> + * WSL symlink layout version 1 stores the symlink target
> + * location into the data section of the file.
> + * Store it now after the reparse point file was created.
> + * The target location was allocated into the buf but iov
> + * size filled in reparse_iov by wsl_set_reparse_buf() was
> + * set to smaller so the created reparse point does not
> + * contain it.
> + */
> + oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, FILE_WRITE_DATA,
> + FILE_OPEN, CREATE_NOT_DIR | OPEN_REPARSE_POINT,
> + ACL_NO_MODE);
> + oparms.fid = &fid;
> + oplock = tcon->ses->server->oplocks ? REQ_OPLOCK : 0;
> + rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, NULL);
> + if (!rc) {
> + symv1_iov[1].iov_base = ((struct reparse_wsl_symlink_data_buffer *)buf)->Target;
> + symv1_iov[1].iov_len = strlen((const char *)symv1_iov[1].iov_base);
> + io_parms = (struct cifs_io_parms) {
> + .netfid = fid.netfid,
> + .pid = current->tgid,
> + .tcon = tcon,
> + .offset = 0,
> + .length = symv1_iov[1].iov_len,
> + };
> + rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms,
> + &bytes_written,
> + symv1_iov,
> + ARRAY_SIZE(symv1_iov)-1);
> + if (bytes_written != symv1_iov[1].iov_len)
> + rc = -EIO;
> + tcon->ses->server->ops->close(xid, tcon, &fid);
> + }
> + if (rc) {
> + tcon->ses->server->ops->unlink(xid, tcon, full_path, cifs_sb, NULL);
> + iput(new);
> + new = ERR_PTR(rc);
> + }
> + }
> if (!IS_ERR(new))
> d_instantiate(dentry, new);
> else
> @@ -764,7 +818,7 @@ int mknod_reparse(unsigned int xid, struct inode *inode,
> case CIFS_REPARSE_TYPE_NFS:
> return mknod_nfs(xid, inode, dentry, tcon, full_path, mode, dev, NULL);
> case CIFS_REPARSE_TYPE_WSL:
> - return mknod_wsl(xid, inode, dentry, tcon, full_path, mode, dev, NULL);
> + return mknod_wsl(xid, inode, dentry, tcon, full_path, mode, dev, NULL, 0);
> default:
> return -EOPNOTSUPP;
> }
> --
> 2.20.1
>
For visibility, this is fixup for sashiko review:
diff --git a/fs/smb/client/reparse.c b/fs/smb/client/reparse.c
index c3e125669e9b..679ba469b77e 100644
--- a/fs/smb/client/reparse.c
+++ b/fs/smb/client/reparse.c
@@ -775,7 +775,6 @@ static int mknod_wsl(unsigned int xid, struct inode *inode,
symv1_iov[1].iov_base = ((struct reparse_wsl_symlink_data_buffer *)buf)->Target;
symv1_iov[1].iov_len = strlen((const char *)symv1_iov[1].iov_base);
io_parms = (struct cifs_io_parms) {
- .netfid = fid.netfid,
.pid = current->tgid,
.tcon = tcon,
.offset = 0,
@@ -785,7 +784,7 @@ static int mknod_wsl(unsigned int xid, struct inode *inode,
&bytes_written,
symv1_iov,
ARRAY_SIZE(symv1_iov)-1);
- if (bytes_written != symv1_iov[1].iov_len)
+ if (!rc && bytes_written != symv1_iov[1].iov_len)
rc = -EIO;
tcon->ses->server->ops->close(xid, tcon, &fid);
}
next prev parent reply other threads:[~2026-10-13 8:48 UTC|newest]
Thread overview: 43+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-06 18:48 [PATCH RESEND 00/11] cifs: Various changes Pali Rohár
2026-07-06 18:48 ` [PATCH RESEND 01/11] cifs: Fix and improve cifs_is_path_accessible() function Pali Rohár
2026-07-06 18:48 ` [PATCH RESEND 02/11] cifs: Remove code for querying FILE_INFO_STANDARD via CIFSSMBQPathInfo() Pali Rohár
2026-07-06 18:48 ` [PATCH RESEND 03/11] cifs: Remove CIFSSMBSetPathInfoFB() fallback function Pali Rohár
2026-07-06 18:48 ` [PATCH RESEND 04/11] cifs: Remove cifs_backup_query_path_info() and replace it by cifs_query_path_info() Pali Rohár
2026-07-06 18:48 ` [PATCH RESEND 05/11] cifs: Fix validation of EAs for WSL reparse points Pali Rohár
2026-07-06 18:48 ` [PATCH RESEND 06/11] cifs: Validate presence of EA $LXMOD " Pali Rohár
2026-07-06 18:48 ` [PATCH RESEND 07/11] cifs: Check if server supports EAs before trying to set it for WSL Pali Rohár
2026-07-06 22:33 ` Steve French
2026-07-06 22:42 ` Pali Rohár
[not found] ` <CAH2r5mvDGM7i8EsdPkW681a_AnXOAsHkg38eJqegO7g2gV8qAw@mail.gmail.com>
2026-07-06 22:58 ` Pali Rohár
2026-07-06 18:48 ` [PATCH RESEND 08/11] cifs: Extend ->set_EA() callback to allow operate on reparse point Pali Rohár
2026-07-06 18:48 ` [PATCH RESEND 09/11] cifs: Create native Window socket file compatible also with WSL subsystem Pali Rohár
2026-08-09 12:09 ` Pali Rohár
2026-07-06 18:48 ` [PATCH RESEND 10/11] cifs: Add support for parsing WSL symlinks in version 1 format Pali Rohár
2026-07-06 20:50 ` Pali Rohár
2026-07-06 21:02 ` Pali Rohár
2026-08-09 12:09 ` [PATCH v2] " Pali Rohár
2026-07-06 18:48 ` [PATCH RESEND 11/11] cifs: Add support for creating " Pali Rohár
2026-08-09 12:13 ` [PATCH v2] " Pali Rohár
2026-08-21 21:47 ` [PATCH RESEND 00/11] cifs: Various changes Pali Rohár
2026-08-22 13:28 ` Namjae Jeon
2026-08-22 13:31 ` Pali Rohár
2026-08-24 22:45 ` Paulo Alcantara
2026-08-25 20:26 ` Pali Rohár
2026-08-25 23:06 ` [PATCH 0/9] " Pali Rohár
2026-08-25 23:06 ` [PATCH 1/9] cifs: Remove code for querying FILE_INFO_STANDARD via CIFSSMBQPathInfo() Pali Rohár
2026-08-25 23:06 ` [PATCH 2/9] cifs: Remove cifs_backup_query_path_info() and replace it by cifs_query_path_info() Pali Rohár
2026-08-25 23:06 ` [PATCH 3/9] cifs: Fix validation of EAs for WSL reparse points Pali Rohár
2026-08-25 23:06 ` [PATCH 4/9] cifs: Validate presence of EA $LXMOD " Pali Rohár
2026-08-25 23:06 ` [PATCH 5/9] cifs: Check if server supports EAs before trying to set it for WSL Pali Rohár
2026-08-25 23:06 ` [PATCH 6/9] cifs: Extend ->set_EA() callback to allow operate on reparse point Pali Rohár
2026-08-25 23:06 ` [PATCH 7/9] cifs: Create native Window socket file compatible also with WSL subsystem Pali Rohár
2026-08-25 23:06 ` [PATCH 8/9] cifs: Add support for parsing WSL symlinks in version 1 format Pali Rohár
2026-10-13 8:47 ` Pali Rohár
2026-08-25 23:06 ` [PATCH 9/9] cifs: Add support for creating " Pali Rohár
2026-10-13 8:48 ` Pali Rohár [this message]
2026-10-12 14:10 ` [PATCH 0/9] Various changes Pali Rohár
2026-10-13 5:25 ` Namjae Jeon
2026-10-13 6:55 ` Pali Rohár
2026-10-13 7:56 ` Namjae Jeon
2026-10-13 8:11 ` Pali Rohár
2026-10-13 8:20 ` Namjae Jeon
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=20261013084827.ulqi2u2eebb4i3ay@pali \
--to=pali@kernel.org \
--cc=linkinjeon@kernel.org \
--cc=linux-cifs@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=pc@manguebit.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
all inboxes | Powered by JetHome®