Message ID | 1380863798.3564.12.camel@edumazet-glaptop.roam.corp.google.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Thu, Oct 3, 2013 at 10:16 PM, Eric Dumazet <eric.dumazet@gmail.com> wrote: > On Thu, 2013-10-03 at 21:11 -0700, Alexei Starovoitov wrote: > > -static inline unsigned int sk_filter_len(const struct sk_filter *fp) > +static inline unsigned int sk_filter_size(const struct sk_filter *fp, > + unsigned int proglen) > { > - return fp->len * sizeof(struct sock_filter) + sizeof(*fp); > + return max(sizeof(*fp), > + offsetof(struct sk_filter, insns[proglen])); > } indeed that's cleaner. Like this then: -static inline unsigned int sk_filter_len(const struct sk_filter *fp) +static inline unsigned int sk_filter_size(unsigned int proglen) { - return fp->len * sizeof(struct sock_filter) + sizeof(*fp); + return max(sizeof(struct sk_filter), + offsetof(struct sk_filter, insns[proglen])); } testing it... will send v4 shortly
diff --git a/include/linux/filter.h b/include/linux/filter.h index a6ac848..281b05c 100644 --- a/include/linux/filter.h +++ b/include/linux/filter.h @@ -6,6 +6,7 @@ #include <linux/atomic.h> #include <linux/compat.h> +#include <linux/workqueue.h> #include <uapi/linux/filter.h> #ifdef CONFIG_COMPAT @@ -25,15 +26,20 @@ struct sk_filter { atomic_t refcnt; unsigned int len; /* Number of filter blocks */ + struct rcu_head rcu; unsigned int (*bpf_func)(const struct sk_buff *skb, const struct sock_filter *filter); - struct rcu_head rcu; - struct sock_filter insns[0]; + union { + struct work_struct work; + struct sock_filter insns[0]; + }; }; -static inline unsigned int sk_filter_len(const struct sk_filter *fp) +static inline unsigned int sk_filter_size(const struct sk_filter *fp, + unsigned int proglen) { - return fp->len * sizeof(struct sock_filter) + sizeof(*fp); + return max(sizeof(*fp), + offsetof(struct sk_filter, insns[proglen])); } extern int sk_filter(struct sock *sk, struct sk_buff *skb);