Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bcc70bb3 authored by Cyrill Gorcunov's avatar Cyrill Gorcunov Committed by David S. Miller
Browse files

net, ppp: Report correct error code if unit allocation failed



Allocating unit from ird might return several error codes
not only -EAGAIN, so it should not be changed and returned
precisely. Same time unit release procedure should be invoked
only if device is unregistering.

Signed-off-by: default avatarCyrill Gorcunov <gorcunov@openvz.org>
CC: Paul Mackerras <paulus@samba.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 3c6f27bf
Loading
Loading
Loading
Loading
+22 −21
Original line number Diff line number Diff line
@@ -2584,16 +2584,16 @@ ppp_create_interface(struct net *net, int unit, int *retp)
	 */
	dev_net_set(dev, net);

	ret = -EEXIST;
	mutex_lock(&pn->all_ppp_mutex);

	if (unit < 0) {
		unit = unit_get(&pn->units_idr, ppp);
		if (unit < 0) {
			*retp = unit;
			ret = unit;
			goto out2;
		}
	} else {
		ret = -EEXIST;
		if (unit_find(&pn->units_idr, unit))
			goto out2; /* unit already exists */
		/*
@@ -2668,10 +2668,10 @@ static void ppp_shutdown_interface(struct ppp *ppp)
		ppp->closing = 1;
		ppp_unlock(ppp);
		unregister_netdev(ppp->dev);
		unit_put(&pn->units_idr, ppp->file.index);
	} else
		ppp_unlock(ppp);

	unit_put(&pn->units_idr, ppp->file.index);
	ppp->file.dead = 1;
	ppp->owner = NULL;
	wake_up_interruptible(&ppp->file.rwait);
@@ -2859,8 +2859,7 @@ static void __exit ppp_cleanup(void)
 * by holding all_ppp_mutex
 */

/* associate pointer with specified number */
static int unit_set(struct idr *p, void *ptr, int n)
static int __unit_alloc(struct idr *p, void *ptr, int n)
{
	int unit, err;

@@ -2871,10 +2870,24 @@ static int unit_set(struct idr *p, void *ptr, int n)
	}

	err = idr_get_new_above(p, ptr, n, &unit);
	if (err < 0) {
		if (err == -EAGAIN)
			goto again;
		return err;
	}

	return unit;
}

/* associate pointer with specified number */
static int unit_set(struct idr *p, void *ptr, int n)
{
	int unit;

	if (unit != n) {
	unit = __unit_alloc(p, ptr, n);
	if (unit < 0)
		return unit;
	else if (unit != n) {
		idr_remove(p, unit);
		return -EINVAL;
	}
@@ -2885,19 +2898,7 @@ static int unit_set(struct idr *p, void *ptr, int n)
/* get new free unit number and associate pointer with it */
static int unit_get(struct idr *p, void *ptr)
{
	int unit, err;

again:
	if (!idr_pre_get(p, GFP_KERNEL)) {
		printk(KERN_ERR "PPP: No free memory for idr\n");
		return -ENOMEM;
	}

	err = idr_get_new_above(p, ptr, 0, &unit);
	if (err == -EAGAIN)
		goto again;

	return unit;
	return __unit_alloc(p, ptr, 0);
}

/* put unit number back to a pool */