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: Cyrill Gorcunov <gorcunov@openvz.org> CC: Paul Mackerras <paulus@samba.org> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
3c6f27bf33
commit
bcc70bb3ae
|
@ -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)
|
||||||
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)
|
||||||
* 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 @@ again:
|
||||||
}
|
}
|
||||||
|
|
||||||
err = idr_get_new_above(p, ptr, n, &unit);
|
err = idr_get_new_above(p, ptr, n, &unit);
|
||||||
if (err == -EAGAIN)
|
if (err < 0) {
|
||||||
goto again;
|
if (err == -EAGAIN)
|
||||||
|
goto again;
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
if (unit != n) {
|
return unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* associate pointer with specified number */
|
||||||
|
static int unit_set(struct idr *p, void *ptr, int n)
|
||||||
|
{
|
||||||
|
int unit;
|
||||||
|
|
||||||
|
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 @@ again:
|
||||||
/* 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 */
|
||||||
|
|
Loading…
Reference in New Issue