Message ID | 20240713031147.20332-1-apanyaki@amazon.com |
---|---|
State | New |
Headers | show |
Series | [6.1] cifs: use origin fullpath for automounts | expand |
On Sat, Jul 13, 2024 at 03:11:47AM +0000, Andrew Paniakin wrote: > From: Paulo Alcantara <pc@cjr.nz> > > commit 7ad54b98fc1f141cfb70cfe2a3d6def5a85169ff upstream. > > Use TCP_Server_Info::origin_fullpath instead of cifs_tcon::tree_name > when building source paths for automounts as it will be useful for > domain-based DFS referrals where the connections and referrals would > get either re-used from the cache or re-created when chasing the dfs > link. > > Signed-off-by: Paulo Alcantara (SUSE) <pc@cjr.nz> > Signed-off-by: Steve French <stfrench@microsoft.com> > [apanyaki: backport to v6.1-stable] > Signed-off-by: Andrew Paniakin <apanyaki@amazon.com> > --- > This patch fixes issue reported in > https://lore.kernel.org/regressions/ZnMkNzmitQdP9OIC@3c06303d853a.ant.amazon.com > > 1. The set_dest_addr function gets ip address differntly. In kernel 6.1 > the dns_resolve_server_name_to_ip function returns string instead of > struct sockaddr, this string needs to be converted with > cifs_convert_address then. > > 2. There's no tmp.leaf_fullpath field in kernel 6.1, it was introduced > later in a1c0d00572fc ("cifs: share dfs connections and supers") > > 3. __build_path_from_dentry_optional_prefix and > dfs_get_automount_devname were added to fs/smb/client/cifsproto.h > instead of fs/cifs/dfs.h which doesn't exist in 6.1 Now queued up, thanks. greg k-h
On Mon, Jul 15, 2024 at 01:48:44PM +0200, Greg KH wrote: > On Sat, Jul 13, 2024 at 03:11:47AM +0000, Andrew Paniakin wrote: > > From: Paulo Alcantara <pc@cjr.nz> > > > > commit 7ad54b98fc1f141cfb70cfe2a3d6def5a85169ff upstream. > > > > Use TCP_Server_Info::origin_fullpath instead of cifs_tcon::tree_name > > when building source paths for automounts as it will be useful for > > domain-based DFS referrals where the connections and referrals would > > get either re-used from the cache or re-created when chasing the dfs > > link. > > > > Signed-off-by: Paulo Alcantara (SUSE) <pc@cjr.nz> > > Signed-off-by: Steve French <stfrench@microsoft.com> > > [apanyaki: backport to v6.1-stable] > > Signed-off-by: Andrew Paniakin <apanyaki@amazon.com> > > --- > > This patch fixes issue reported in > > https://lore.kernel.org/regressions/ZnMkNzmitQdP9OIC@3c06303d853a.ant.amazon.com > > > > 1. The set_dest_addr function gets ip address differntly. In kernel 6.1 > > the dns_resolve_server_name_to_ip function returns string instead of > > struct sockaddr, this string needs to be converted with > > cifs_convert_address then. > > > > 2. There's no tmp.leaf_fullpath field in kernel 6.1, it was introduced > > later in a1c0d00572fc ("cifs: share dfs connections and supers") > > > > 3. __build_path_from_dentry_optional_prefix and > > dfs_get_automount_devname were added to fs/smb/client/cifsproto.h > > instead of fs/cifs/dfs.h which doesn't exist in 6.1 > > Now queued up, thanks. Nope, now dropped. This required me to apply d5a863a153e9 ("cifs: avoid dup prefix path in dfs_get_automount_devname()") to the tree (and attempt to backport it myself), but that didn't work, as it caused reported build errors as seen here: https://lore.kernel.org/r/aaccd8cc-2bfe-4b2e-b690-be50540f9965@gmail.com So I'm dropping this, and the fix-up patch. Please be careful when sending backports that you do NOT miss additional patches that are required as well. I'll be glad to take backports, as long as they are correct :) thanks, greg k-h
diff --git a/fs/smb/client/cifs_dfs_ref.c b/fs/smb/client/cifs_dfs_ref.c index 020e71fe1454..876f9a43a99d 100644 --- a/fs/smb/client/cifs_dfs_ref.c +++ b/fs/smb/client/cifs_dfs_ref.c @@ -258,6 +258,31 @@ char *cifs_compose_mount_options(const char *sb_mountdata, goto compose_mount_options_out; } +static int set_dest_addr(struct smb3_fs_context *ctx, const char *full_path) +{ + struct sockaddr *addr = (struct sockaddr *)&ctx->dstaddr; + char *str_addr = NULL; + int rc; + + rc = dns_resolve_server_name_to_ip(full_path, &str_addr, NULL); + if (rc < 0) + goto out; + + rc = cifs_convert_address(addr, str_addr, strlen(str_addr)); + if (!rc) { + cifs_dbg(FYI, "%s: failed to convert ip address\n", __func__); + rc = -EINVAL; + goto out; + } + + cifs_set_port(addr, ctx->port); + rc = 0; + +out: + kfree(str_addr); + return rc; +} + /* * Create a vfsmount that we can automount */ @@ -295,8 +320,7 @@ static struct vfsmount *cifs_dfs_do_automount(struct path *path) ctx = smb3_fc2context(fc); page = alloc_dentry_path(); - /* always use tree name prefix */ - full_path = build_path_from_dentry_optional_prefix(mntpt, page, true); + full_path = dfs_get_automount_devname(mntpt, page); if (IS_ERR(full_path)) { mnt = ERR_CAST(full_path); goto out; @@ -315,6 +339,12 @@ static struct vfsmount *cifs_dfs_do_automount(struct path *path) goto out; } + rc = set_dest_addr(ctx, full_path); + if (rc) { + mnt = ERR_PTR(rc); + goto out; + } + rc = smb3_parse_devname(full_path, ctx); if (!rc) mnt = fc_mount(fc); diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h index f37e4da0fe40..6dbc9afd6728 100644 --- a/fs/smb/client/cifsproto.h +++ b/fs/smb/client/cifsproto.h @@ -57,8 +57,26 @@ extern void exit_cifs_idmap(void); extern int init_cifs_spnego(void); extern void exit_cifs_spnego(void); extern const char *build_path_from_dentry(struct dentry *, void *); +char *__build_path_from_dentry_optional_prefix(struct dentry *direntry, void *page, + const char *tree, int tree_len, + bool prefix); extern char *build_path_from_dentry_optional_prefix(struct dentry *direntry, void *page, bool prefix); +static inline char *dfs_get_automount_devname(struct dentry *dentry, void *page) +{ + struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb); + struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); + struct TCP_Server_Info *server = tcon->ses->server; + + if (unlikely(!server->origin_fullpath)) + return ERR_PTR(-EREMOTE); + + return __build_path_from_dentry_optional_prefix(dentry, page, + server->origin_fullpath, + strlen(server->origin_fullpath), + true); +} + static inline void *alloc_dentry_path(void) { return __getname(); diff --git a/fs/smb/client/dir.c b/fs/smb/client/dir.c index 863c7bc3db86..477302157ab3 100644 --- a/fs/smb/client/dir.c +++ b/fs/smb/client/dir.c @@ -78,14 +78,13 @@ build_path_from_dentry(struct dentry *direntry, void *page) prefix); } -char * -build_path_from_dentry_optional_prefix(struct dentry *direntry, void *page, - bool prefix) +char *__build_path_from_dentry_optional_prefix(struct dentry *direntry, void *page, + const char *tree, int tree_len, + bool prefix) { int dfsplen; int pplen = 0; struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb); - struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); char dirsep = CIFS_DIR_SEP(cifs_sb); char *s; @@ -93,7 +92,7 @@ build_path_from_dentry_optional_prefix(struct dentry *direntry, void *page, return ERR_PTR(-ENOMEM); if (prefix) - dfsplen = strnlen(tcon->tree_name, MAX_TREE_SIZE + 1); + dfsplen = strnlen(tree, tree_len + 1); else dfsplen = 0; @@ -123,7 +122,7 @@ build_path_from_dentry_optional_prefix(struct dentry *direntry, void *page, } if (dfsplen) { s -= dfsplen; - memcpy(s, tcon->tree_name, dfsplen); + memcpy(s, tree, dfsplen); if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) { int i; for (i = 0; i < dfsplen; i++) { @@ -135,6 +134,16 @@ build_path_from_dentry_optional_prefix(struct dentry *direntry, void *page, return s; } +char *build_path_from_dentry_optional_prefix(struct dentry *direntry, void *page, + bool prefix) +{ + struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb); + struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); + + return __build_path_from_dentry_optional_prefix(direntry, page, tcon->tree_name, + MAX_TREE_SIZE, prefix); +} + /* * Don't allow path components longer than the server max. * Don't allow the separator character in a path component.