Skip to content

Commit

Permalink
net: ppp_generic - fix regressions caused by IDR conversion
Browse files Browse the repository at this point in the history
The commits:

	7a95d26
	("net: ppp_generic - use idr technique instead of cardmaps")

	ab5024a
	("net: ppp_generic - use DEFINE_IDR for static initialization")

introduced usage of IDR functionality but broke userspace side.

Before this commits it was possible to allocate new ppp interface with
specified number. Now it fails with EINVAL.  Fix it by trying to
allocate interface with specified unit number and return EEXIST if
fail which allow pppd to ask us to allocate new unit number.

And fix messages on memory allocation fails - add details that it's
PPP module who is complaining.

Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Cyrill Gorcunov authored and David S. Miller committed Jan 13, 2009
1 parent a6d0b91 commit 8599757
Showing 1 changed file with 37 additions and 6 deletions.
43 changes: 37 additions & 6 deletions drivers/net/ppp_generic.c
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ static int ppp_connect_channel(struct channel *pch, int unit);
static int ppp_disconnect_channel(struct channel *pch);
static void ppp_destroy_channel(struct channel *pch);
static int unit_get(struct idr *p, void *ptr);
static int unit_set(struct idr *p, void *ptr, int n);
static void unit_put(struct idr *p, int n);
static void *unit_find(struct idr *p, int n);

Expand Down Expand Up @@ -2432,11 +2433,18 @@ ppp_create_interface(int unit, int *retp)
} else {
if (unit_find(&ppp_units_idr, unit))
goto out2; /* unit already exists */
else {
/* darn, someone is cheating us? */
*retp = -EINVAL;
/*
* if caller need a specified unit number
* lets try to satisfy him, otherwise --
* he should better ask us for new unit number
*
* NOTE: yes I know that returning EEXIST it's not
* fair but at least pppd will ask us to allocate
* new unit in this case so user is happy :)
*/
unit = unit_set(&ppp_units_idr, ppp, unit);
if (unit < 0)
goto out2;
}
}

/* Initialize the new ppp unit */
Expand Down Expand Up @@ -2677,14 +2685,37 @@ 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)
{
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, n, &unit);
if (err == -EAGAIN)
goto again;

if (unit != n) {
idr_remove(p, unit);
return -EINVAL;
}

return unit;
}

/* 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) == 0) {
printk(KERN_ERR "Out of memory expanding drawable idr\n");
if (!idr_pre_get(p, GFP_KERNEL)) {
printk(KERN_ERR "PPP: No free memory for idr\n");
return -ENOMEM;
}

Expand Down

0 comments on commit 8599757

Please sign in to comment.