[PATCH 5/7] ntfs: clean up target name conversion for WSL symlinks

From: Hyunchul Lee

Date: Fri Jun 12 2026 - 03:39:59 EST


WSL symlink target names are stored as narrow NLS/UTF-8 strings on
disk. Converting the target name to Unicode in ntfs_symlink and
converting it back to NLS in ntfs_reparse_set_wsl_symlink is
redundant.

Remove this conversion and pass the symname directly to the reparse
data setter.

Signed-off-by: Hyunchul Lee <hyc.lee@xxxxxxxxx>
---
fs/ntfs/namei.c | 17 ++---------------
fs/ntfs/reparse.c | 49 ++++++++++++++++++++++++-------------------------
fs/ntfs/reparse.h | 2 +-
3 files changed, 27 insertions(+), 41 deletions(-)

diff --git a/fs/ntfs/namei.c b/fs/ntfs/namei.c
index 9c1c36acfad2..88c0b05dde3b 100644
--- a/fs/ntfs/namei.c
+++ b/fs/ntfs/namei.c
@@ -394,7 +394,7 @@ static int ntfs_sd_add_everyone(struct ntfs_inode *ni)

static struct ntfs_inode *__ntfs_create(struct mnt_idmap *idmap, struct inode *dir,
__le16 *name, u8 name_len, mode_t mode, dev_t dev,
- __le16 *target, int target_len)
+ const char *target, int target_len)
{
struct ntfs_inode *dir_ni = NTFS_I(dir);
struct ntfs_volume *vol = dir_ni->vol;
@@ -1409,9 +1409,7 @@ static int ntfs_symlink(struct mnt_idmap *idmap, struct inode *dir,
int err = 0;
struct ntfs_inode *ni;
__le16 *usrc;
- __le16 *utarget;
int usrc_len;
- int utarget_len;
int symlen = strlen(symname);

if (NVolShutdown(vol))
@@ -1432,23 +1430,12 @@ static int ntfs_symlink(struct mnt_idmap *idmap, struct inode *dir,
goto out;
}

- utarget_len = ntfs_nlstoucs(vol, symname, symlen, &utarget,
- PATH_MAX);
- if (utarget_len < 0) {
- if (utarget_len != -ENAMETOOLONG)
- ntfs_error(sb, "Failed to convert target name to Unicode.");
- err = -ENOMEM;
- kmem_cache_free(ntfs_name_cache, usrc);
- goto out;
- }
-
if (!(vol->vol_flags & VOLUME_IS_DIRTY))
ntfs_set_volume_flags(vol, VOLUME_IS_DIRTY);

ni = __ntfs_create(idmap, dir, usrc, usrc_len, S_IFLNK | 0777, 0,
- utarget, utarget_len);
+ symname, symlen);
kmem_cache_free(ntfs_name_cache, usrc);
- kvfree(utarget);
if (IS_ERR(ni)) {
err = PTR_ERR(ni);
goto out;
diff --git a/fs/ntfs/reparse.c b/fs/ntfs/reparse.c
index fb8c42a27699..eb1e4424e50d 100644
--- a/fs/ntfs/reparse.c
+++ b/fs/ntfs/reparse.c
@@ -750,39 +750,38 @@ static int ntfs_set_ntfs_reparse_data(struct ntfs_inode *ni, char *value, size_t
* Set reparse data for a WSL type symlink
*/
int ntfs_reparse_set_wsl_symlink(struct ntfs_inode *ni,
- const __le16 *target, int target_len)
+ const char *target, int target_len)
{
int err = 0;
- int len;
int reparse_len;
- unsigned char *utarget = NULL;
struct reparse_point *reparse;
struct wsl_link_reparse_data *data;

- len = ntfs_ucstonls(ni->vol, target, target_len, &utarget, 0);
- if (len <= 0)
- return -EINVAL;
-
- reparse_len = sizeof(struct reparse_point) + sizeof(data->type) + len;
+ reparse_len = sizeof(struct reparse_point) + sizeof(data->type) +
+ target_len;
reparse = kvzalloc(reparse_len, GFP_NOFS);
- if (!reparse) {
- err = -ENOMEM;
- kfree(utarget);
- } else {
- data = (struct wsl_link_reparse_data *)reparse->reparse_data;
- reparse->reparse_tag = IO_REPARSE_TAG_LX_SYMLINK;
- reparse->reparse_data_length =
- cpu_to_le16(sizeof(data->type) + len);
- reparse->reserved = 0;
- data->type = cpu_to_le32(2);
- memcpy(data->link, utarget, len);
- err = ntfs_set_ntfs_reparse_data(ni,
- (char *)reparse, reparse_len);
+ if (!reparse)
+ return -ENOMEM;
+
+ ni->target = kstrdup(target, GFP_NOFS);
+ if (!ni->target) {
kvfree(reparse);
- if (!err)
- ni->target = utarget;
- else
- kfree(utarget);
+ return -ENOMEM;
+ }
+
+ data = (struct wsl_link_reparse_data *)reparse->reparse_data;
+ reparse->reparse_tag = IO_REPARSE_TAG_LX_SYMLINK;
+ reparse->reparse_data_length =
+ cpu_to_le16(sizeof(data->type) + target_len);
+ reparse->reserved = 0;
+ data->type = cpu_to_le32(2);
+ memcpy(data->link, target, target_len);
+ err = ntfs_set_ntfs_reparse_data(ni,
+ (char *)reparse, reparse_len);
+ kvfree(reparse);
+ if (err) {
+ kfree(ni->target);
+ ni->target = NULL;
}
return err;
}
diff --git a/fs/ntfs/reparse.h b/fs/ntfs/reparse.h
index ed7b93c359c1..e36557f29677 100644
--- a/fs/ntfs/reparse.h
+++ b/fs/ntfs/reparse.h
@@ -14,7 +14,7 @@ unsigned int ntfs_reparse_tag_dt_types(struct ntfs_volume *vol, unsigned long mr
int ntfs_translate_symlink_path(struct dentry *dentry, const char *target,
char **translated);
int ntfs_reparse_set_wsl_symlink(struct ntfs_inode *ni,
- const __le16 *target, int target_len);
+ const char *target, int target_len);
int ntfs_reparse_set_wsl_not_symlink(struct ntfs_inode *ni, mode_t mode);
int ntfs_delete_reparse_index(struct ntfs_inode *ni);
int ntfs_remove_ntfs_reparse_data(struct ntfs_inode *ni);

--
2.43.0