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 <neilb@suse.de>
Change-Id: Ib807ca4ce5235b28e7ae11d90e1942aff4454cfc
Reviewed-on: https://review.whamcloud.com/38644
Tested-by: jenkins <devops@whamcloud.com>
Reviewed-by: Shaun Tancheff <shaun.tancheff@hpe.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Chris Horn <chris.horn@hpe.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
- int max_intf = lnet_interfaces_max;
if (n_ids <= 0 ||
id.nid == LNET_NID_ANY)
if (n_ids <= 0 ||
id.nid == LNET_NID_ANY)
id.pid = LNET_PID_LUSTRE;
/*
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)
CFS_ALLOC_PTR_ARRAY(buf, n_ids);
if (!buf)
- /* 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) {
i = 0;
p = NULL;
while ((p = lnet_get_next_peer_ni_locked(lp, NULL, p)) != NULL) {
if (++i >= n_ids)
break;
}
if (++i >= n_ids)
break;
}
- 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);
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;
CFS_FREE_PTR_ARRAY(buf, n_ids);
return rc;