From 45722de60a8fb5fee86a07ce5e3861b31dcedf59 Mon Sep 17 00:00:00 2001 From: Mr NeilBrown Date: Mon, 18 May 2020 09:21:27 +1000 Subject: [PATCH] LU-9679 lnet: tidy lnet_discover and fix mem accounting bug. A recent patch introduce a memory accounting bug because "n_ids" can change between the ALLOC call and the FREE call. With this patch we fix that by ensuring n_ids doesn't change - the current change is not needed. Also: - discard 'max_intf' var. It is always exactly lnet_interfaces_max, so just use that directly. - only copy back the number of interfaces found - report the number of interfaces actually copied. - Move the copy_to_user until after all locks and references are dropped so there is no need to re-take any locks. Test-Parameters: trivial Fixes: b1f6f3becedc ("LU-9679 libcfs: Add CFS_ALLOC_PTR_ARRAY and free") Signed-off-by: Mr NeilBrown Change-Id: Ib807ca4ce5235b28e7ae11d90e1942aff4454cfc Reviewed-on: https://review.whamcloud.com/38644 Tested-by: jenkins Reviewed-by: Shaun Tancheff Tested-by: Maloo Reviewed-by: Chris Horn Reviewed-by: Oleg Drokin --- lnet/lnet/api-ni.c | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/lnet/lnet/api-ni.c b/lnet/lnet/api-ni.c index 41b14f24..05c0cb3 100644 --- a/lnet/lnet/api-ni.c +++ b/lnet/lnet/api-ni.c @@ -4257,7 +4257,6 @@ lnet_discover(struct lnet_process_id id, __u32 force, int cpt; int i; int rc; - int max_intf = lnet_interfaces_max; if (n_ids <= 0 || id.nid == LNET_NID_ANY) @@ -4267,11 +4266,11 @@ lnet_discover(struct lnet_process_id id, __u32 force, id.pid = LNET_PID_LUSTRE; /* - * if the user buffer has more space than the max_intf - * then only fill it up to max_intf + * If the user buffer has more space than the lnet_interfaces_max, + * then only fill it up to lnet_interfaces_max. */ - if (n_ids > max_intf) - n_ids = max_intf; + if (n_ids > lnet_interfaces_max) + n_ids = lnet_interfaces_max; CFS_ALLOC_PTR_ARRAY(buf, n_ids); if (!buf) @@ -4299,11 +4298,6 @@ lnet_discover(struct lnet_process_id id, __u32 force, if (rc) goto out_decref; - /* Peer may have changed. */ - lp = lpni->lpni_peer_net->lpn_peer; - if (lp->lp_nnis < n_ids) - n_ids = lp->lp_nnis; - i = 0; p = NULL; while ((p = lnet_get_next_peer_ni_locked(lp, NULL, p)) != NULL) { @@ -4312,20 +4306,16 @@ lnet_discover(struct lnet_process_id id, __u32 force, if (++i >= n_ids) break; } + rc = i; - lnet_net_unlock(cpt); - - rc = -EFAULT; - if (copy_to_user(ids, buf, n_ids * sizeof(*buf))) - goto out_relock; - rc = n_ids; -out_relock: - lnet_net_lock(cpt); out_decref: lnet_peer_ni_decref_locked(lpni); out: lnet_net_unlock(cpt); + if (rc >= 0) + if (copy_to_user(ids, buf, rc * sizeof(*buf))) + rc = -EFAULT; CFS_FREE_PTR_ARRAY(buf, n_ids); return rc; -- 1.8.3.1