From: Jesse Gross Date: Tue, 27 Jul 2010 01:46:27 +0000 (-0700) Subject: datapath: Move flow allocation into a function. X-Git-Tag: v1.1.0~1101 X-Git-Url: http://git.onelab.eu/?a=commitdiff_plain;h=560e802229f3028c02273435dd1c6efba33e0949;hp=02892690e6866781a0a6c84e25a2c1d277822788;p=sliver-openvswitch.git datapath: Move flow allocation into a function. As the process to allocate a flow becomes more involved it becomes more cumbersome for the code to be mixed in with the general datapath so split it out into a new function. Signed-off-by: Jesse Gross Reviewed-by: Ben Pfaff --- diff --git a/datapath/datapath.c b/datapath/datapath.c index b3f77b36a..1677927ff 100644 --- a/datapath/datapath.c +++ b/datapath/datapath.c @@ -1049,12 +1049,12 @@ static int do_put_flow(struct datapath *dp, struct odp_flow_put *uf, } /* Allocate flow. */ - error = -ENOMEM; - flow = kmem_cache_alloc(flow_cache, GFP_KERNEL); - if (flow == NULL) + flow = flow_alloc(); + if (IS_ERR(flow)) { + error = PTR_ERR(flow); goto error; + } flow->key = uf->flow.key; - spin_lock_init(&flow->lock); clear_stats(flow); /* Obtain actions. */ @@ -1109,7 +1109,7 @@ static int do_put_flow(struct datapath *dp, struct odp_flow_put *uf, error_free_flow_acts: kfree(flow->sf_acts); error_free_flow: - kmem_cache_free(flow_cache, flow); + flow_free(flow); error: return error; } diff --git a/datapath/flow.c b/datapath/flow.c index 7684c061a..1f01166c5 100644 --- a/datapath/flow.c +++ b/datapath/flow.c @@ -123,27 +123,45 @@ struct sw_flow_actions *flow_actions_alloc(size_t n_actions) return sfa; } +struct sw_flow *flow_alloc(void) +{ + struct sw_flow *flow; + + flow = kmem_cache_alloc(flow_cache, GFP_KERNEL); + if (!flow) + return ERR_PTR(-ENOMEM); + + spin_lock_init(&flow->lock); -/* Frees 'flow' immediately. */ -static void flow_free(struct sw_flow *flow) + return flow; +} + +void flow_free(struct sw_flow *flow) { if (unlikely(!flow)) return; - kfree(flow->sf_acts); + kmem_cache_free(flow_cache, flow); } +/* Frees the entire 'flow' (both base and actions) immediately. */ +static void flow_free_full(struct sw_flow *flow) +{ + kfree(flow->sf_acts); + flow_free(flow); +} + void flow_free_tbl(struct tbl_node *node) { struct sw_flow *flow = flow_cast(node); - flow_free(flow); + flow_free_full(flow); } /* RCU callback used by flow_deferred_free. */ static void rcu_free_flow_callback(struct rcu_head *rcu) { struct sw_flow *flow = container_of(rcu, struct sw_flow, rcu); - flow_free(flow); + flow_free_full(flow); } /* Schedules 'flow' to be freed after the next RCU grace period. diff --git a/datapath/flow.h b/datapath/flow.h index 80a5b66b1..484ca1207 100644 --- a/datapath/flow.h +++ b/datapath/flow.h @@ -58,20 +58,22 @@ struct arp_eth_header unsigned char ar_tip[4]; /* target IP address */ } __attribute__((packed)); -extern struct kmem_cache *flow_cache; +int flow_init(void); +void flow_exit(void); -struct sw_flow_actions *flow_actions_alloc(size_t n_actions); +struct sw_flow *flow_alloc(void); +void flow_free(struct sw_flow *flow); void flow_deferred_free(struct sw_flow *); +void flow_free_tbl(struct tbl_node *); + +struct sw_flow_actions *flow_actions_alloc(size_t n_actions); void flow_deferred_free_acts(struct sw_flow_actions *); + int flow_extract(struct sk_buff *, u16 in_port, struct odp_flow_key *); void flow_used(struct sw_flow *, struct sk_buff *); u32 flow_hash(const struct odp_flow_key *key); int flow_cmp(const struct tbl_node *, void *target); -void flow_free_tbl(struct tbl_node *); - -int flow_init(void); -void flow_exit(void); static inline struct sw_flow *flow_cast(const struct tbl_node *node) {