From 214ca8ed9aefb048068834a6e8bc95971991e269 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Wed, 16 Nov 2011 11:09:09 +0000 Subject: [PATCH] --- yaml --- r: 277567 b: refs/heads/master c: 358b838291f618278080bbed435b755f9b46748e h: refs/heads/master i: 277565: 8c74bb5b4fcf663e86ce406a1602f41b2967c995 277563: f85561dac32cd1484d457d3c54c674e91baf7a16 277559: ed6c97fda43d7f5f3772f787612540e6794f56e0 277551: 1d2052010d6e2a71fdc48c488ba0dca4f92fb7fd 277535: 55b98b4d1a6794fc30903c6b069e3ec3aa9699f5 277503: 3d6add57f2c8a23818d70a1d170e3506250746f9 v: v3 --- [refs] | 2 +- trunk/drivers/net/team/team.c | 76 ++++++++++++++++--- .../drivers/net/team/team_mode_activebackup.c | 5 +- trunk/include/linux/if_team.h | 8 +- 4 files changed, 73 insertions(+), 18 deletions(-) diff --git a/[refs] b/[refs] index 4391cff2bf8a..c3b4c6e5f69c 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 61dc3461b9549bc10a2f16d254250680cadafcce +refs/heads/master: 358b838291f618278080bbed435b755f9b46748e diff --git a/trunk/drivers/net/team/team.c b/trunk/drivers/net/team/team.c index 7db219cd3153..f3092749b072 100644 --- a/trunk/drivers/net/team/team.c +++ b/trunk/drivers/net/team/team.c @@ -80,30 +80,78 @@ EXPORT_SYMBOL(team_port_set_team_mac); * Options handling *******************/ -void team_options_register(struct team *team, struct team_option *option, - size_t option_count) +struct team_option *__team_find_option(struct team *team, const char *opt_name) +{ + struct team_option *option; + + list_for_each_entry(option, &team->option_list, list) { + if (strcmp(option->name, opt_name) == 0) + return option; + } + return NULL; +} + +int team_options_register(struct team *team, + const struct team_option *option, + size_t option_count) { int i; + struct team_option *dst_opts[option_count]; + int err; + + memset(dst_opts, 0, sizeof(dst_opts)); + for (i = 0; i < option_count; i++, option++) { + struct team_option *dst_opt; + + if (__team_find_option(team, option->name)) { + err = -EEXIST; + goto rollback; + } + dst_opt = kmalloc(sizeof(*option), GFP_KERNEL); + if (!dst_opt) { + err = -ENOMEM; + goto rollback; + } + memcpy(dst_opt, option, sizeof(*option)); + dst_opts[i] = dst_opt; + } + + for (i = 0; i < option_count; i++) + list_add_tail(&dst_opts[i]->list, &team->option_list); - for (i = 0; i < option_count; i++, option++) - list_add_tail(&option->list, &team->option_list); + return 0; + +rollback: + for (i = 0; i < option_count; i++) + kfree(dst_opts[i]); + + return err; } + EXPORT_SYMBOL(team_options_register); static void __team_options_change_check(struct team *team, struct team_option *changed_option); static void __team_options_unregister(struct team *team, - struct team_option *option, + const struct team_option *option, size_t option_count) { int i; - for (i = 0; i < option_count; i++, option++) - list_del(&option->list); + for (i = 0; i < option_count; i++, option++) { + struct team_option *del_opt; + + del_opt = __team_find_option(team, option->name); + if (del_opt) { + list_del(&del_opt->list); + kfree(del_opt); + } + } } -void team_options_unregister(struct team *team, struct team_option *option, +void team_options_unregister(struct team *team, + const struct team_option *option, size_t option_count) { __team_options_unregister(team, option, option_count); @@ -632,7 +680,7 @@ static int team_mode_option_set(struct team *team, void *arg) return team_change_mode(team, *str); } -static struct team_option team_options[] = { +static const struct team_option team_options[] = { { .name = "mode", .type = TEAM_OPTION_TYPE_STRING, @@ -645,6 +693,7 @@ static int team_init(struct net_device *dev) { struct team *team = netdev_priv(dev); int i; + int err; team->dev = dev; mutex_init(&team->lock); @@ -660,10 +709,17 @@ static int team_init(struct net_device *dev) team_adjust_ops(team); INIT_LIST_HEAD(&team->option_list); - team_options_register(team, team_options, ARRAY_SIZE(team_options)); + err = team_options_register(team, team_options, ARRAY_SIZE(team_options)); + if (err) + goto err_options_register; netif_carrier_off(dev); return 0; + +err_options_register: + free_percpu(team->pcpu_stats); + + return err; } static void team_uninit(struct net_device *dev) diff --git a/trunk/drivers/net/team/team_mode_activebackup.c b/trunk/drivers/net/team/team_mode_activebackup.c index 6fe920c440b3..b34427502b54 100644 --- a/trunk/drivers/net/team/team_mode_activebackup.c +++ b/trunk/drivers/net/team/team_mode_activebackup.c @@ -83,7 +83,7 @@ static int ab_active_port_set(struct team *team, void *arg) return -ENOENT; } -static struct team_option ab_options[] = { +static const struct team_option ab_options[] = { { .name = "activeport", .type = TEAM_OPTION_TYPE_U32, @@ -94,8 +94,7 @@ static struct team_option ab_options[] = { int ab_init(struct team *team) { - team_options_register(team, ab_options, ARRAY_SIZE(ab_options)); - return 0; + return team_options_register(team, ab_options, ARRAY_SIZE(ab_options)); } void ab_exit(struct team *team) diff --git a/trunk/include/linux/if_team.h b/trunk/include/linux/if_team.h index a6eac126a99a..828181fbad5d 100644 --- a/trunk/include/linux/if_team.h +++ b/trunk/include/linux/if_team.h @@ -140,11 +140,11 @@ static inline struct team_port *team_get_port_by_index_rcu(struct team *team, } extern int team_port_set_team_mac(struct team_port *port); -extern void team_options_register(struct team *team, - struct team_option *option, - size_t option_count); +extern int team_options_register(struct team *team, + const struct team_option *option, + size_t option_count); extern void team_options_unregister(struct team *team, - struct team_option *option, + const struct team_option *option, size_t option_count); extern int team_mode_register(struct team_mode *mode); extern int team_mode_unregister(struct team_mode *mode);