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

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
...@@ -2584,16 +2584,16 @@ ppp_create_interface(struct net *net, int unit, int *retp) ...@@ -2584,16 +2584,16 @@ ppp_create_interface(struct net *net, int unit, int *retp)
*/ */
dev_net_set(dev, net); dev_net_set(dev, net);
ret = -EEXIST;
mutex_lock(&pn->all_ppp_mutex); mutex_lock(&pn->all_ppp_mutex);
if (unit < 0) { if (unit < 0) {
unit = unit_get(&pn->units_idr, ppp); unit = unit_get(&pn->units_idr, ppp);
if (unit < 0) { if (unit < 0) {
*retp = unit; ret = unit;
goto out2; goto out2;
} }
} else { } else {
ret = -EEXIST;
if (unit_find(&pn->units_idr, unit)) if (unit_find(&pn->units_idr, unit))
goto out2; /* unit already exists */ goto out2; /* unit already exists */
/* /*
...@@ -2668,10 +2668,10 @@ static void ppp_shutdown_interface(struct ppp *ppp) ...@@ -2668,10 +2668,10 @@ static void ppp_shutdown_interface(struct ppp *ppp)
ppp->closing = 1; ppp->closing = 1;
ppp_unlock(ppp); ppp_unlock(ppp);
unregister_netdev(ppp->dev); unregister_netdev(ppp->dev);
unit_put(&pn->units_idr, ppp->file.index);
} else } else
ppp_unlock(ppp); ppp_unlock(ppp);
unit_put(&pn->units_idr, ppp->file.index);
ppp->file.dead = 1; ppp->file.dead = 1;
ppp->owner = NULL; ppp->owner = NULL;
wake_up_interruptible(&ppp->file.rwait); wake_up_interruptible(&ppp->file.rwait);
...@@ -2859,8 +2859,7 @@ static void __exit ppp_cleanup(void) ...@@ -2859,8 +2859,7 @@ static void __exit ppp_cleanup(void)
* by holding all_ppp_mutex * by holding all_ppp_mutex
*/ */
/* associate pointer with specified number */ static int __unit_alloc(struct idr *p, void *ptr, int n)
static int unit_set(struct idr *p, void *ptr, int n)
{ {
int unit, err; int unit, err;
...@@ -2871,10 +2870,24 @@ static int unit_set(struct idr *p, void *ptr, int n) ...@@ -2871,10 +2870,24 @@ static int unit_set(struct idr *p, void *ptr, int n)
} }
err = idr_get_new_above(p, ptr, n, &unit); err = idr_get_new_above(p, ptr, n, &unit);
if (err < 0) {
if (err == -EAGAIN) if (err == -EAGAIN)
goto again; 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); idr_remove(p, unit);
return -EINVAL; return -EINVAL;
} }
...@@ -2885,19 +2898,7 @@ static int unit_set(struct idr *p, void *ptr, int n) ...@@ -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 */ /* get new free unit number and associate pointer with it */
static int unit_get(struct idr *p, void *ptr) static int unit_get(struct idr *p, void *ptr)
{ {
int unit, err; return __unit_alloc(p, ptr, 0);
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;
} }
/* put unit number back to a pool */ /* put unit number back to a pool */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment