You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
netfilter: ipset: Prepare the ipset core to use RCU at set level
Replace rwlock_t with spinlock_t in "struct ip_set" and change the locking accordingly. Convert the comment extension into an rcu-avare object. Also, simplify the timeout routines. Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
This commit is contained in:
@@ -108,8 +108,13 @@ struct ip_set_counter {
|
||||
atomic64_t packets;
|
||||
};
|
||||
|
||||
struct ip_set_comment_rcu {
|
||||
struct rcu_head rcu;
|
||||
char str[0];
|
||||
};
|
||||
|
||||
struct ip_set_comment {
|
||||
char *str;
|
||||
struct ip_set_comment_rcu __rcu *c;
|
||||
};
|
||||
|
||||
struct ip_set_skbinfo {
|
||||
@@ -226,7 +231,7 @@ struct ip_set {
|
||||
/* The name of the set */
|
||||
char name[IPSET_MAXNAMELEN];
|
||||
/* Lock protecting the set data */
|
||||
rwlock_t lock;
|
||||
spinlock_t lock;
|
||||
/* References to the set */
|
||||
u32 ref;
|
||||
/* The core set type */
|
||||
|
||||
@@ -16,41 +16,57 @@ ip_set_comment_uget(struct nlattr *tb)
|
||||
return nla_data(tb);
|
||||
}
|
||||
|
||||
/* Called from uadd only, protected by the set spinlock.
|
||||
* The kadt functions don't use the comment extensions in any way.
|
||||
*/
|
||||
static inline void
|
||||
ip_set_init_comment(struct ip_set_comment *comment,
|
||||
const struct ip_set_ext *ext)
|
||||
{
|
||||
struct ip_set_comment_rcu *c = rcu_dereference_protected(comment->c, 1);
|
||||
size_t len = ext->comment ? strlen(ext->comment) : 0;
|
||||
|
||||
if (unlikely(comment->str)) {
|
||||
kfree(comment->str);
|
||||
comment->str = NULL;
|
||||
if (unlikely(c)) {
|
||||
kfree_rcu(c, rcu);
|
||||
rcu_assign_pointer(comment->c, NULL);
|
||||
}
|
||||
if (!len)
|
||||
return;
|
||||
if (unlikely(len > IPSET_MAX_COMMENT_SIZE))
|
||||
len = IPSET_MAX_COMMENT_SIZE;
|
||||
comment->str = kzalloc(len + 1, GFP_ATOMIC);
|
||||
if (unlikely(!comment->str))
|
||||
c = kzalloc(sizeof(*c) + len + 1, GFP_ATOMIC);
|
||||
if (unlikely(!c))
|
||||
return;
|
||||
strlcpy(comment->str, ext->comment, len + 1);
|
||||
strlcpy(c->str, ext->comment, len + 1);
|
||||
rcu_assign_pointer(comment->c, c);
|
||||
}
|
||||
|
||||
/* Used only when dumping a set, protected by rcu_read_lock_bh() */
|
||||
static inline int
|
||||
ip_set_put_comment(struct sk_buff *skb, struct ip_set_comment *comment)
|
||||
{
|
||||
if (!comment->str)
|
||||
struct ip_set_comment_rcu *c = rcu_dereference_bh(comment->c);
|
||||
|
||||
if (!c)
|
||||
return 0;
|
||||
return nla_put_string(skb, IPSET_ATTR_COMMENT, comment->str);
|
||||
return nla_put_string(skb, IPSET_ATTR_COMMENT, c->str);
|
||||
}
|
||||
|
||||
/* Called from uadd/udel, flush or the garbage collectors protected
|
||||
* by the set spinlock.
|
||||
* Called when the set is destroyed and when there can't be any user
|
||||
* of the set data anymore.
|
||||
*/
|
||||
static inline void
|
||||
ip_set_comment_free(struct ip_set_comment *comment)
|
||||
{
|
||||
if (unlikely(!comment->str))
|
||||
struct ip_set_comment_rcu *c;
|
||||
|
||||
c = rcu_dereference_protected(comment->c, 1);
|
||||
if (unlikely(!c))
|
||||
return;
|
||||
kfree(comment->str);
|
||||
comment->str = NULL;
|
||||
kfree_rcu(c, rcu);
|
||||
rcu_assign_pointer(comment->c, NULL);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -40,31 +40,26 @@ ip_set_timeout_uget(struct nlattr *tb)
|
||||
}
|
||||
|
||||
static inline bool
|
||||
ip_set_timeout_test(unsigned long timeout)
|
||||
ip_set_timeout_expired(unsigned long *t)
|
||||
{
|
||||
return timeout == IPSET_ELEM_PERMANENT ||
|
||||
time_is_after_jiffies(timeout);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
ip_set_timeout_expired(unsigned long *timeout)
|
||||
{
|
||||
return *timeout != IPSET_ELEM_PERMANENT &&
|
||||
time_is_before_jiffies(*timeout);
|
||||
return *t != IPSET_ELEM_PERMANENT && time_is_before_jiffies(*t);
|
||||
}
|
||||
|
||||
static inline void
|
||||
ip_set_timeout_set(unsigned long *timeout, u32 t)
|
||||
ip_set_timeout_set(unsigned long *timeout, u32 value)
|
||||
{
|
||||
if (!t) {
|
||||
unsigned long t;
|
||||
|
||||
if (!value) {
|
||||
*timeout = IPSET_ELEM_PERMANENT;
|
||||
return;
|
||||
}
|
||||
|
||||
*timeout = msecs_to_jiffies(t * MSEC_PER_SEC) + jiffies;
|
||||
if (*timeout == IPSET_ELEM_PERMANENT)
|
||||
t = msecs_to_jiffies(value * MSEC_PER_SEC) + jiffies;
|
||||
if (t == IPSET_ELEM_PERMANENT)
|
||||
/* Bingo! :-) */
|
||||
(*timeout)--;
|
||||
t--;
|
||||
*timeout = t;
|
||||
}
|
||||
|
||||
static inline u32
|
||||
|
||||
Reference in New Issue
Block a user