diff options
author | Cyrill Gorcunov <gorcunov@gmail.com> | 2010-11-23 06:43:44 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-11-28 14:33:49 -0500 |
commit | bcc70bb3aeae7c3d035881d41055685f08a2b745 (patch) | |
tree | d315f22c30a9356f8294669bb9c9cf31f844ff12 /drivers | |
parent | 3c6f27bf33052ea6ba9d82369fb460726fb779c0 (diff) |
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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/ppp_generic.c | 43 |
1 files changed, 22 insertions, 21 deletions
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index 09cf56d0416a..39659976a1ac 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c | |||
@@ -2584,16 +2584,16 @@ ppp_create_interface(struct net *net, int unit, int *retp) | |||
2584 | */ | 2584 | */ |
2585 | dev_net_set(dev, net); | 2585 | dev_net_set(dev, net); |
2586 | 2586 | ||
2587 | ret = -EEXIST; | ||
2588 | mutex_lock(&pn->all_ppp_mutex); | 2587 | mutex_lock(&pn->all_ppp_mutex); |
2589 | 2588 | ||
2590 | if (unit < 0) { | 2589 | if (unit < 0) { |
2591 | unit = unit_get(&pn->units_idr, ppp); | 2590 | unit = unit_get(&pn->units_idr, ppp); |
2592 | if (unit < 0) { | 2591 | if (unit < 0) { |
2593 | *retp = unit; | 2592 | ret = unit; |
2594 | goto out2; | 2593 | goto out2; |
2595 | } | 2594 | } |
2596 | } else { | 2595 | } else { |
2596 | ret = -EEXIST; | ||
2597 | if (unit_find(&pn->units_idr, unit)) | 2597 | if (unit_find(&pn->units_idr, unit)) |
2598 | goto out2; /* unit already exists */ | 2598 | goto out2; /* unit already exists */ |
2599 | /* | 2599 | /* |
@@ -2668,10 +2668,10 @@ static void ppp_shutdown_interface(struct ppp *ppp) | |||
2668 | ppp->closing = 1; | 2668 | ppp->closing = 1; |
2669 | ppp_unlock(ppp); | 2669 | ppp_unlock(ppp); |
2670 | unregister_netdev(ppp->dev); | 2670 | unregister_netdev(ppp->dev); |
2671 | unit_put(&pn->units_idr, ppp->file.index); | ||
2671 | } else | 2672 | } else |
2672 | ppp_unlock(ppp); | 2673 | ppp_unlock(ppp); |
2673 | 2674 | ||
2674 | unit_put(&pn->units_idr, ppp->file.index); | ||
2675 | ppp->file.dead = 1; | 2675 | ppp->file.dead = 1; |
2676 | ppp->owner = NULL; | 2676 | ppp->owner = NULL; |
2677 | wake_up_interruptible(&ppp->file.rwait); | 2677 | wake_up_interruptible(&ppp->file.rwait); |
@@ -2859,8 +2859,7 @@ static void __exit ppp_cleanup(void) | |||
2859 | * by holding all_ppp_mutex | 2859 | * by holding all_ppp_mutex |
2860 | */ | 2860 | */ |
2861 | 2861 | ||
2862 | /* associate pointer with specified number */ | 2862 | static int __unit_alloc(struct idr *p, void *ptr, int n) |
2863 | static int unit_set(struct idr *p, void *ptr, int n) | ||
2864 | { | 2863 | { |
2865 | int unit, err; | 2864 | int unit, err; |
2866 | 2865 | ||
@@ -2871,10 +2870,24 @@ again: | |||
2871 | } | 2870 | } |
2872 | 2871 | ||
2873 | err = idr_get_new_above(p, ptr, n, &unit); | 2872 | err = idr_get_new_above(p, ptr, n, &unit); |
2874 | if (err == -EAGAIN) | 2873 | if (err < 0) { |
2875 | goto again; | 2874 | if (err == -EAGAIN) |
2875 | goto again; | ||
2876 | return err; | ||
2877 | } | ||
2878 | |||
2879 | return unit; | ||
2880 | } | ||
2881 | |||
2882 | /* associate pointer with specified number */ | ||
2883 | static int unit_set(struct idr *p, void *ptr, int n) | ||
2884 | { | ||
2885 | int unit; | ||
2876 | 2886 | ||
2877 | if (unit != n) { | 2887 | unit = __unit_alloc(p, ptr, n); |
2888 | if (unit < 0) | ||
2889 | return unit; | ||
2890 | else if (unit != n) { | ||
2878 | idr_remove(p, unit); | 2891 | idr_remove(p, unit); |
2879 | return -EINVAL; | 2892 | return -EINVAL; |
2880 | } | 2893 | } |
@@ -2885,19 +2898,7 @@ again: | |||
2885 | /* get new free unit number and associate pointer with it */ | 2898 | /* get new free unit number and associate pointer with it */ |
2886 | static int unit_get(struct idr *p, void *ptr) | 2899 | static int unit_get(struct idr *p, void *ptr) |
2887 | { | 2900 | { |
2888 | int unit, err; | 2901 | return __unit_alloc(p, ptr, 0); |
2889 | |||
2890 | again: | ||
2891 | if (!idr_pre_get(p, GFP_KERNEL)) { | ||
2892 | printk(KERN_ERR "PPP: No free memory for idr\n"); | ||
2893 | return -ENOMEM; | ||
2894 | } | ||
2895 | |||
2896 | err = idr_get_new_above(p, ptr, 0, &unit); | ||
2897 | if (err == -EAGAIN) | ||
2898 | goto again; | ||
2899 | |||
2900 | return unit; | ||
2901 | } | 2902 | } |
2902 | 2903 | ||
2903 | /* put unit number back to a pool */ | 2904 | /* put unit number back to a pool */ |