summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEnzo Matsumiya <ematsumiya@suse.de>2025-05-16 17:59:05 -0300
committerEnzo Matsumiya <ematsumiya@suse.de>2025-05-16 18:27:03 -0300
commit5222a1aa127b92acc0381a399e504a88762ebee4 (patch)
treec8dffada19af2e0e15c380ff40ff849aa013e9b0
parent8ae792457970d5d2c3271e3c1a9daf316349f061 (diff)
downloadlinux-5222a1aa127b92acc0381a399e504a88762ebee4.tar.gz
linux-5222a1aa127b92acc0381a399e504a88762ebee4.tar.bz2
linux-5222a1aa127b92acc0381a399e504a88762ebee4.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.c80
1 files changed, 41 insertions, 39 deletions
diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c
index ed858f5ce1da..d9f8c29c09e9 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"
@@ -575,40 +576,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
@@ -623,7 +629,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;
@@ -646,6 +652,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);
/*
@@ -713,15 +720,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);
@@ -739,18 +742,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:
@@ -778,7 +777,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,
@@ -789,6 +788,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;