diff options
| author | Enzo Matsumiya <ematsumiya@suse.de> | 2025-05-16 17:59:05 -0300 |
|---|---|---|
| committer | Enzo Matsumiya <ematsumiya@suse.de> | 2025-06-16 15:41:34 -0300 |
| commit | 28a98e793dd908a0384daee0318784f23cde1c24 (patch) | |
| tree | 963e5baa92e67ba30aaef6fb72268e3b29514f09 | |
| parent | 75bc5f078b48b423890baa625ad498670c3ed8df (diff) | |
| download | linux-28a98e793dd908a0384daee0318784f23cde1c24.tar.gz linux-28a98e793dd908a0384daee0318784f23cde1c24.tar.bz2 linux-28a98e793dd908a0384daee0318784f23cde1c24.zip | |
smb: client: use list_sort for iface_list
Adapt iface_cmp to return (-1, 0, 1).
Sort iface_list after parsing+adding all received.
Signed-off-by: Enzo Matsumiya <ematsumiya@suse.de>
| -rw-r--r-- | fs/smb/client/smb2ops.c | 80 |
1 files changed, 41 insertions, 39 deletions
diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c index 6e09205b53bb..f6df9c2d1117 100644 --- a/fs/smb/client/smb2ops.c +++ b/fs/smb/client/smb2ops.c @@ -15,6 +15,7 @@ #include <linux/fiemap.h> #include <linux/folio_queue.h> #include <uapi/linux/magic.h> +#include <linux/list_sort.h> #include "cifsfs.h" #include "cifsglob.h" #include "smb2pdu.h" @@ -581,40 +582,45 @@ smb3_negotiate_rsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx) } /* - * compare two interfaces a and b - * return 0 if everything matches. - * return 1 if a is rdma capable, or rss capable, or has higher link speed - * return -1 otherwise. + * Compare two interfaces @a and @b. + * + * Return: + * -1: @a is preferred + * 0: exact match + * 1: @b is preferred + * + * "preferred": rdma capable, or rss capable, or has higher link speed */ -static int -iface_cmp(struct cifs_server_iface *a, struct cifs_server_iface *b) +static int __iface_cmp(struct cifs_server_iface *a, struct cifs_server_iface *b) { - int cmp_ret = 0; - - WARN_ON(!a || !b); + if (unlikely(!a)) + return 1; + if (unlikely(!b)) + return -1; if (a->rdma_capable == b->rdma_capable) { if (a->rss_capable == b->rss_capable) { - if (a->speed == b->speed) { - cmp_ret = cifs_ipaddr_cmp((struct sockaddr *) &a->sockaddr, - (struct sockaddr *) &b->sockaddr); - if (!cmp_ret) - return 0; - else if (cmp_ret > 0) - return 1; - else - return -1; - } else if (a->speed > b->speed) - return 1; - else + if (a->speed == b->speed) + return cifs_ipaddr_cmp((struct sockaddr *)&a->sockaddr, + (struct sockaddr *)&b->sockaddr); + if (a->speed > b->speed) return -1; - } else if (a->rss_capable > b->rss_capable) return 1; - else + } + if (a->rss_capable > b->rss_capable) return -1; - } else if (a->rdma_capable > b->rdma_capable) return 1; - else + } + if (a->rdma_capable > b->rdma_capable) return -1; + return 1; +} + +static int iface_cmp(void *unused, const struct list_head *a, const struct list_head *b) +{ + struct cifs_server_iface *ifa = container_of(a, struct cifs_server_iface, iface_head); + struct cifs_server_iface *ifb = container_of(b, struct cifs_server_iface, iface_head); + + return __iface_cmp(ifa, ifb); } static int @@ -629,7 +635,7 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf, struct cifs_server_iface *info = NULL, *iface = NULL, *niface = NULL; struct cifs_server_iface tmp_iface; ssize_t bytes_left; - size_t next = 0; + size_t next = 0, old_count; int nb_iface = 0; int rc = 0, ret = 0; @@ -652,6 +658,7 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf, iface_head) iface->is_active = 0; + old_count = ses->iface_count; spin_unlock(&ses->iface_lock); /* @@ -719,15 +726,11 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf, spin_lock(&ses->iface_lock); list_for_each_entry_safe(iface, niface, &ses->iface_list, iface_head) { - ret = iface_cmp(iface, &tmp_iface); + ret = __iface_cmp(iface, &tmp_iface); if (!ret) { iface->is_active = 1; spin_unlock(&ses->iface_lock); goto next_iface; - } else if (ret < 0) { - /* all remaining ifaces are slower */ - kref_get(&iface->refcount); - break; } } spin_unlock(&ses->iface_lock); @@ -745,18 +748,14 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf, kref_init(&info->refcount); info->is_active = 1; - cifs_dbg(FYI, "%s: adding iface %zu\n", __func__, ses->iface_count); + cifs_dbg(FYI, "%s: adding iface[%zu]: %pIS\n", __func__, ses->iface_count, + &info->sockaddr); cifs_dbg(FYI, "%s: speed %zu bps\n", __func__, info->speed); cifs_dbg(FYI, "%s: capabilities 0x%08x\n", __func__, le32_to_cpu(p->Capability)); spin_lock(&ses->iface_lock); - if (!list_entry_is_head(iface, &ses->iface_list, iface_head)) { - list_add_tail(&info->iface_head, &iface->iface_head); - kref_put(&iface->refcount, release_iface); - } else - list_add_tail(&info->iface_head, &ses->iface_list); - + list_add_tail(&info->iface_head, &ses->iface_list); ses->iface_count++; spin_unlock(&ses->iface_lock); next_iface: @@ -784,7 +783,7 @@ next_iface: out: /* - * Go through the list again and put the inactive entries + * Put inactive entries, then sort the list (only if new ifaces added, to save some cycles). */ spin_lock(&ses->iface_lock); list_for_each_entry_safe(iface, niface, &ses->iface_list, @@ -795,6 +794,9 @@ out: ses->iface_count--; } } + + if (old_count != ses->iface_count) + list_sort(NULL, &ses->iface_list, iface_cmp); spin_unlock(&ses->iface_lock); return rc; |
