Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6ddc0822 authored by Pavel Emelyanov's avatar Pavel Emelyanov Committed by David S. Miller
Browse files

[NETNS][FRAGS]: Make the mem counter per-namespace.



This is also simple, but introduces more changes, since
then mem counter is altered in more places.

Signed-off-by: default avatarPavel Emelyanov <xemul@openvz.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e5a2bb84
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@

struct netns_frags {
	int			nqueues;
	atomic_t		mem;
};

struct inet_frag_queue {
@@ -38,7 +39,6 @@ struct inet_frags {
	rwlock_t		lock;
	u32			rnd;
	int			qsize;
	atomic_t		mem;
	struct timer_list	secret_timer;
	struct inet_frags_ctl	*ctl;

@@ -60,7 +60,7 @@ void inet_frags_init_net(struct netns_frags *nf);
void inet_frag_kill(struct inet_frag_queue *q, struct inet_frags *f);
void inet_frag_destroy(struct inet_frag_queue *q,
				struct inet_frags *f, int *work);
int inet_frag_evictor(struct inet_frags *f);
int inet_frag_evictor(struct netns_frags *nf, struct inet_frags *f);
struct inet_frag_queue *inet_frag_find(struct netns_frags *nf,
		struct inet_frags *f, void *key, unsigned int hash);

+1 −1
Original line number Diff line number Diff line
@@ -331,7 +331,7 @@ enum ip_defrag_users
};

int ip_defrag(struct sk_buff *skb, u32 user);
int ip_frag_mem(void);
int ip_frag_mem(struct net *net);
int ip_frag_nqueues(struct net *net);

/*
+1 −1
Original line number Diff line number Diff line
@@ -246,7 +246,7 @@ struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space,
extern int ipv6_opt_accepted(struct sock *sk, struct sk_buff *skb);

int ip6_frag_nqueues(struct net *net);
int ip6_frag_mem(void);
int ip6_frag_mem(struct net *net);

#define IPV6_FRAG_TIMEOUT	(60*HZ)		/* 60 seconds */

+11 −10
Original line number Diff line number Diff line
@@ -63,8 +63,6 @@ void inet_frags_init(struct inet_frags *f)
	f->rnd = (u32) ((num_physpages ^ (num_physpages>>7)) ^
				   (jiffies ^ (jiffies >> 6)));

	atomic_set(&f->mem, 0);

	setup_timer(&f->secret_timer, inet_frag_secret_rebuild,
			(unsigned long)f);
	f->secret_timer.expires = jiffies + f->ctl->secret_interval;
@@ -75,6 +73,7 @@ EXPORT_SYMBOL(inet_frags_init);
void inet_frags_init_net(struct netns_frags *nf)
{
	nf->nqueues = 0;
	atomic_set(&nf->mem, 0);
}
EXPORT_SYMBOL(inet_frags_init_net);

@@ -107,13 +106,13 @@ void inet_frag_kill(struct inet_frag_queue *fq, struct inet_frags *f)

EXPORT_SYMBOL(inet_frag_kill);

static inline void frag_kfree_skb(struct inet_frags *f, struct sk_buff *skb,
						int *work)
static inline void frag_kfree_skb(struct netns_frags *nf, struct inet_frags *f,
		struct sk_buff *skb, int *work)
{
	if (work)
		*work -= skb->truesize;

	atomic_sub(skb->truesize, &f->mem);
	atomic_sub(skb->truesize, &nf->mem);
	if (f->skb_free)
		f->skb_free(skb);
	kfree_skb(skb);
@@ -123,22 +122,24 @@ void inet_frag_destroy(struct inet_frag_queue *q, struct inet_frags *f,
					int *work)
{
	struct sk_buff *fp;
	struct netns_frags *nf;

	BUG_TRAP(q->last_in & COMPLETE);
	BUG_TRAP(del_timer(&q->timer) == 0);

	/* Release all fragment data. */
	fp = q->fragments;
	nf = q->net;
	while (fp) {
		struct sk_buff *xp = fp->next;

		frag_kfree_skb(f, fp, work);
		frag_kfree_skb(nf, f, fp, work);
		fp = xp;
	}

	if (work)
		*work -= f->qsize;
	atomic_sub(f->qsize, &f->mem);
	atomic_sub(f->qsize, &nf->mem);

	if (f->destructor)
		f->destructor(q);
@@ -147,12 +148,12 @@ void inet_frag_destroy(struct inet_frag_queue *q, struct inet_frags *f,
}
EXPORT_SYMBOL(inet_frag_destroy);

int inet_frag_evictor(struct inet_frags *f)
int inet_frag_evictor(struct netns_frags *nf, struct inet_frags *f)
{
	struct inet_frag_queue *q;
	int work, evicted = 0;

	work = atomic_read(&f->mem) - f->ctl->low_thresh;
	work = atomic_read(&nf->mem) - f->ctl->low_thresh;
	while (work > 0) {
		read_lock(&f->lock);
		if (list_empty(&f->lru_list)) {
@@ -226,7 +227,7 @@ static struct inet_frag_queue *inet_frag_alloc(struct netns_frags *nf,
		return NULL;

	f->constructor(q, arg);
	atomic_add(f->qsize, &f->mem);
	atomic_add(f->qsize, &nf->mem);
	setup_timer(&q->timer, f->frag_expire, (unsigned long)q);
	spin_lock_init(&q->lock);
	atomic_set(&q->refcnt, 1);
+15 −14
Original line number Diff line number Diff line
@@ -100,9 +100,9 @@ int ip_frag_nqueues(struct net *net)
	return net->ipv4.frags.nqueues;
}

int ip_frag_mem(void)
int ip_frag_mem(struct net *net)
{
	return atomic_read(&ip4_frags.mem);
	return atomic_read(&net->ipv4.frags.mem);
}

static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev,
@@ -142,11 +142,12 @@ static int ip4_frag_match(struct inet_frag_queue *q, void *a)
}

/* Memory Tracking Functions. */
static __inline__ void frag_kfree_skb(struct sk_buff *skb, int *work)
static __inline__ void frag_kfree_skb(struct netns_frags *nf,
		struct sk_buff *skb, int *work)
{
	if (work)
		*work -= skb->truesize;
	atomic_sub(skb->truesize, &ip4_frags.mem);
	atomic_sub(skb->truesize, &nf->mem);
	kfree_skb(skb);
}

@@ -192,11 +193,11 @@ static void ipq_kill(struct ipq *ipq)
/* Memory limiting on fragments.  Evictor trashes the oldest
 * fragment queue until we are back under the threshold.
 */
static void ip_evictor(void)
static void ip_evictor(struct net *net)
{
	int evicted;

	evicted = inet_frag_evictor(&ip4_frags);
	evicted = inet_frag_evictor(&net->ipv4.frags, &ip4_frags);
	if (evicted)
		IP_ADD_STATS_BH(IPSTATS_MIB_REASMFAILS, evicted);
}
@@ -294,7 +295,7 @@ static int ip_frag_reinit(struct ipq *qp)
	fp = qp->q.fragments;
	do {
		struct sk_buff *xp = fp->next;
		frag_kfree_skb(fp, NULL);
		frag_kfree_skb(qp->q.net, fp, NULL);
		fp = xp;
	} while (fp);

@@ -431,7 +432,7 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
				qp->q.fragments = next;

			qp->q.meat -= free_it->len;
			frag_kfree_skb(free_it, NULL);
			frag_kfree_skb(qp->q.net, free_it, NULL);
		}
	}

@@ -451,7 +452,7 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
	}
	qp->q.stamp = skb->tstamp;
	qp->q.meat += skb->len;
	atomic_add(skb->truesize, &ip4_frags.mem);
	atomic_add(skb->truesize, &qp->q.net->mem);
	if (offset == 0)
		qp->q.last_in |= FIRST_IN;

@@ -534,12 +535,12 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev,
		head->len -= clone->len;
		clone->csum = 0;
		clone->ip_summed = head->ip_summed;
		atomic_add(clone->truesize, &ip4_frags.mem);
		atomic_add(clone->truesize, &qp->q.net->mem);
	}

	skb_shinfo(head)->frag_list = head->next;
	skb_push(head, head->data - skb_network_header(head));
	atomic_sub(head->truesize, &ip4_frags.mem);
	atomic_sub(head->truesize, &qp->q.net->mem);

	for (fp=head->next; fp; fp = fp->next) {
		head->data_len += fp->len;
@@ -549,7 +550,7 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev,
		else if (head->ip_summed == CHECKSUM_COMPLETE)
			head->csum = csum_add(head->csum, fp->csum);
		head->truesize += fp->truesize;
		atomic_sub(fp->truesize, &ip4_frags.mem);
		atomic_sub(fp->truesize, &qp->q.net->mem);
	}

	head->next = NULL;
@@ -588,8 +589,8 @@ int ip_defrag(struct sk_buff *skb, u32 user)

	net = skb->dev->nd_net;
	/* Start by cleaning up the memory. */
	if (atomic_read(&ip4_frags.mem) > ip4_frags_ctl.high_thresh)
		ip_evictor();
	if (atomic_read(&net->ipv4.frags.mem) > ip4_frags_ctl.high_thresh)
		ip_evictor(net);

	/* Lookup (or create) queue header */
	if ((qp = ip_find(net, ip_hdr(skb), user)) != NULL) {
Loading