Commit 6c108d9b authored by Florian Westphal's avatar Florian Westphal Committed by Pablo Neira Ayuso

netfilter: nft_set_pipapo: prepare walk function for on-demand clone

The existing code uses iter->type to figure out what data is needed, the
live copy (READ) or clone (UPDATE).

Without pending updates, priv->clone and priv->match will point to
different memory locations, but they have identical content.

Future patch will make priv->clone == NULL if there are no pending changes,
in this case we must copy the live data for the UPDATE case.

Currently this would require GFP_ATOMIC allocation.  Split the walk
function in two parts: one that does the walk and one that decides which
data is needed.

In the UPDATE case, callers hold the transaction mutex so we do not need
the rcu read lock.  This allows to use GFP_KERNEL allocation while
cloning.
Signed-off-by: default avatarFlorian Westphal <fw@strlen.de>
Reviewed-by: default avatarStefano Brivio <sbrivio@redhat.com>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent 8b8a2417
...@@ -2106,35 +2106,23 @@ static void nft_pipapo_remove(const struct net *net, const struct nft_set *set, ...@@ -2106,35 +2106,23 @@ static void nft_pipapo_remove(const struct net *net, const struct nft_set *set,
} }
/** /**
* nft_pipapo_walk() - Walk over elements * nft_pipapo_do_walk() - Walk over elements in m
* @ctx: nftables API context * @ctx: nftables API context
* @set: nftables API set representation * @set: nftables API set representation
* @m: matching data pointing to key mapping array
* @iter: Iterator * @iter: Iterator
* *
* As elements are referenced in the mapping array for the last field, directly * As elements are referenced in the mapping array for the last field, directly
* scan that array: there's no need to follow rule mappings from the first * scan that array: there's no need to follow rule mappings from the first
* field. * field. @m is protected either by RCU read lock or by transaction mutex.
*/ */
static void nft_pipapo_walk(const struct nft_ctx *ctx, struct nft_set *set, static void nft_pipapo_do_walk(const struct nft_ctx *ctx, struct nft_set *set,
struct nft_set_iter *iter) const struct nft_pipapo_match *m,
struct nft_set_iter *iter)
{ {
struct nft_pipapo *priv = nft_set_priv(set);
const struct nft_pipapo_match *m;
const struct nft_pipapo_field *f; const struct nft_pipapo_field *f;
unsigned int i, r; unsigned int i, r;
WARN_ON_ONCE(iter->type != NFT_ITER_READ &&
iter->type != NFT_ITER_UPDATE);
rcu_read_lock();
if (iter->type == NFT_ITER_READ)
m = rcu_dereference(priv->match);
else
m = priv->clone;
if (unlikely(!m))
goto out;
for (i = 0, f = m->f; i < m->field_count - 1; i++, f++) for (i = 0, f = m->f; i < m->field_count - 1; i++, f++)
; ;
...@@ -2151,14 +2139,44 @@ static void nft_pipapo_walk(const struct nft_ctx *ctx, struct nft_set *set, ...@@ -2151,14 +2139,44 @@ static void nft_pipapo_walk(const struct nft_ctx *ctx, struct nft_set *set,
iter->err = iter->fn(ctx, set, iter, &e->priv); iter->err = iter->fn(ctx, set, iter, &e->priv);
if (iter->err < 0) if (iter->err < 0)
goto out; return;
cont: cont:
iter->count++; iter->count++;
} }
}
out: /**
rcu_read_unlock(); * nft_pipapo_walk() - Walk over elements
* @ctx: nftables API context
* @set: nftables API set representation
* @iter: Iterator
*
* Test if destructive action is needed or not, clone active backend if needed
* and call the real function to work on the data.
*/
static void nft_pipapo_walk(const struct nft_ctx *ctx, struct nft_set *set,
struct nft_set_iter *iter)
{
struct nft_pipapo *priv = nft_set_priv(set);
const struct nft_pipapo_match *m;
switch (iter->type) {
case NFT_ITER_UPDATE:
m = priv->clone;
nft_pipapo_do_walk(ctx, set, m, iter);
break;
case NFT_ITER_READ:
rcu_read_lock();
m = rcu_dereference(priv->match);
nft_pipapo_do_walk(ctx, set, m, iter);
rcu_read_unlock();
break;
default:
iter->err = -EINVAL;
WARN_ON_ONCE(1);
break;
}
} }
/** /**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment