All of lore.kernel.org
 help / color / mirror / Atom feed
From: Oleg Babin <obabin@virtuozzo.com>
To: netdev@vger.kernel.org, linux-sctp@vger.kernel.org
Cc: "David S. Miller" <davem@davemloft.net>,
	Vlad Yasevich <vyasevich@gmail.com>,
	Neil Horman <nhorman@tuxdriver.com>,
	Xin Long <lucien.xin@gmail.com>,
	Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>,
	Andrey Ryabinin <aryabinin@virtuozzo.com>
Subject: [PATCH net-next 2/2] net/sctp: Replace in/out stream arrays with flex_array
Date: Mon, 23 Apr 2018 21:41:06 +0300	[thread overview]
Message-ID: <1524508866-317485-3-git-send-email-obabin@virtuozzo.com> (raw)
In-Reply-To: <1524508866-317485-1-git-send-email-obabin@virtuozzo.com>

This path replaces physically contiguous memory arrays
allocated using kmalloc_array() with flexible arrays.
This enables to avoid memory allocation failures on the
systems under a memory stress.

Signed-off-by: Oleg Babin <obabin@virtuozzo.com>
---
 include/net/sctp/structs.h |  1 +
 net/sctp/stream.c          | 78 +++++++++++++++++++++++++++++++++++-----------
 2 files changed, 61 insertions(+), 18 deletions(-)

diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 578bb40..c7f42b4 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -57,6 +57,7 @@
 #include <linux/atomic.h>		/* This gets us atomic counters.  */
 #include <linux/skbuff.h>	/* We need sk_buff_head. */
 #include <linux/workqueue.h>	/* We need tq_struct.	 */
+#include <linux/flex_array.h>	/* We need flex_array.   */
 #include <linux/sctp.h>		/* We need sctp* header structs.  */
 #include <net/sctp/auth.h>	/* We need auth specific structs */
 #include <net/ip.h>		/* For inet_skb_parm */
diff --git a/net/sctp/stream.c b/net/sctp/stream.c
index 16e36c0..be372b0 100644
--- a/net/sctp/stream.c
+++ b/net/sctp/stream.c
@@ -40,13 +40,60 @@
 struct sctp_stream_out *sctp_stream_out_ptr(const struct sctp_stream *stream,
 					    __u16 sid)
 {
-	return ((struct sctp_stream_out *)(stream->out)) + sid;
+	return flex_array_get(stream->out, sid);
 }
 
 struct sctp_stream_in *sctp_stream_in_ptr(const struct sctp_stream *stream,
 					  __u16 sid)
 {
-	return ((struct sctp_stream_in *)(stream->in)) + sid;
+	return flex_array_get(stream->in, sid);
+}
+
+static struct flex_array *fa_alloc(size_t elem_size, size_t elem_count,
+				   gfp_t gfp)
+{
+	struct flex_array *result;
+	int err;
+
+	result = flex_array_alloc(elem_size, elem_count, gfp);
+	if (result) {
+		err = flex_array_prealloc(result, 0, elem_count, gfp);
+		if (err) {
+			flex_array_free(result);
+			result = NULL;
+		}
+	}
+
+	return result;
+}
+
+static void fa_free(struct flex_array *fa)
+{
+	if (fa)
+		flex_array_free(fa);
+}
+
+static void fa_copy(struct flex_array *fa, struct flex_array *from,
+		    size_t index, size_t count)
+{
+	void *elem;
+
+	while (count--) {
+		elem = flex_array_get(from, index);
+		flex_array_put(fa, index, elem, 0);
+		index++;
+	}
+}
+
+static void fa_zero(struct flex_array *fa, size_t index, size_t count)
+{
+	void *elem;
+
+	while (count--) {
+		elem = flex_array_get(fa, index);
+		memset(elem, 0, fa->element_size);
+		index++;
+	}
 }
 
 /* Migrates chunks from stream queues to new stream queues if needed,
@@ -106,19 +153,17 @@ static int sctp_stream_alloc_out(struct sctp_stream *stream, __u16 outcnt,
 	struct flex_array *out;
 	size_t elem_size = sizeof(struct sctp_stream_out);
 
-	out = kmalloc_array(outcnt, elem_size, gfp);
+	out = fa_alloc(elem_size, outcnt, gfp);
 	if (!out)
 		return -ENOMEM;
 
 	if (stream->out) {
-		memcpy(out, stream->out, min(outcnt, stream->outcnt) *
-					 elem_size);
-		kfree(stream->out);
+		fa_copy(out, stream->out, 0, min(outcnt, stream->outcnt));
+		fa_free(stream->out);
 	}
 
 	if (outcnt > stream->outcnt)
-		memset(((struct sctp_stream_out *)out) + stream->outcnt, 0,
-		       (outcnt - stream->outcnt) * elem_size);
+		fa_zero(out, stream->outcnt, (outcnt - stream->outcnt));
 
 	stream->out = out;
 
@@ -131,20 +176,17 @@ static int sctp_stream_alloc_in(struct sctp_stream *stream, __u16 incnt,
 	struct flex_array *in;
 	size_t elem_size = sizeof(struct sctp_stream_in);
 
-	in = kmalloc_array(incnt, elem_size, gfp);
-
+	in = fa_alloc(elem_size, incnt, gfp);
 	if (!in)
 		return -ENOMEM;
 
 	if (stream->in) {
-		memcpy(in, stream->in, min(incnt, stream->incnt) *
-				       elem_size);
-		kfree(stream->in);
+		fa_copy(in, stream->in, 0, min(incnt, stream->incnt));
+		fa_free(stream->in);
 	}
 
 	if (incnt > stream->incnt)
-		memset(((struct sctp_stream_in *)in) + stream->incnt, 0,
-		       (incnt - stream->incnt) * elem_size);
+		fa_zero(in, stream->incnt, (incnt - stream->incnt));
 
 	stream->in = in;
 
@@ -188,7 +230,7 @@ int sctp_stream_init(struct sctp_stream *stream, __u16 outcnt, __u16 incnt,
 	ret = sctp_stream_alloc_in(stream, incnt, gfp);
 	if (ret) {
 		sched->free(stream);
-		kfree(stream->out);
+		fa_free(stream->out);
 		stream->out = NULL;
 		stream->outcnt = 0;
 		goto out;
@@ -220,8 +262,8 @@ void sctp_stream_free(struct sctp_stream *stream)
 	sched->free(stream);
 	for (i = 0; i < stream->outcnt; i++)
 		kfree(SCTP_SO(stream, i)->ext);
-	kfree(stream->out);
-	kfree(stream->in);
+	fa_free(stream->out);
+	fa_free(stream->in);
 }
 
 void sctp_stream_clear(struct sctp_stream *stream)
-- 
1.8.3.1

WARNING: multiple messages have this Message-ID (diff)
From: Oleg Babin <obabin@virtuozzo.com>
To: netdev@vger.kernel.org, linux-sctp@vger.kernel.org
Cc: "David S. Miller" <davem@davemloft.net>,
	Vlad Yasevich <vyasevich@gmail.com>,
	Neil Horman <nhorman@tuxdriver.com>,
	Xin Long <lucien.xin@gmail.com>,
	Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>,
	Andrey Ryabinin <aryabinin@virtuozzo.com>
Subject: [PATCH net-next 2/2] net/sctp: Replace in/out stream arrays with flex_array
Date: Mon, 23 Apr 2018 18:41:06 +0000	[thread overview]
Message-ID: <1524508866-317485-3-git-send-email-obabin@virtuozzo.com> (raw)
In-Reply-To: <1524508866-317485-1-git-send-email-obabin@virtuozzo.com>

This path replaces physically contiguous memory arrays
allocated using kmalloc_array() with flexible arrays.
This enables to avoid memory allocation failures on the
systems under a memory stress.

Signed-off-by: Oleg Babin <obabin@virtuozzo.com>
---
 include/net/sctp/structs.h |  1 +
 net/sctp/stream.c          | 78 +++++++++++++++++++++++++++++++++++-----------
 2 files changed, 61 insertions(+), 18 deletions(-)

diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 578bb40..c7f42b4 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -57,6 +57,7 @@
 #include <linux/atomic.h>		/* This gets us atomic counters.  */
 #include <linux/skbuff.h>	/* We need sk_buff_head. */
 #include <linux/workqueue.h>	/* We need tq_struct.	 */
+#include <linux/flex_array.h>	/* We need flex_array.   */
 #include <linux/sctp.h>		/* We need sctp* header structs.  */
 #include <net/sctp/auth.h>	/* We need auth specific structs */
 #include <net/ip.h>		/* For inet_skb_parm */
diff --git a/net/sctp/stream.c b/net/sctp/stream.c
index 16e36c0..be372b0 100644
--- a/net/sctp/stream.c
+++ b/net/sctp/stream.c
@@ -40,13 +40,60 @@
 struct sctp_stream_out *sctp_stream_out_ptr(const struct sctp_stream *stream,
 					    __u16 sid)
 {
-	return ((struct sctp_stream_out *)(stream->out)) + sid;
+	return flex_array_get(stream->out, sid);
 }
 
 struct sctp_stream_in *sctp_stream_in_ptr(const struct sctp_stream *stream,
 					  __u16 sid)
 {
-	return ((struct sctp_stream_in *)(stream->in)) + sid;
+	return flex_array_get(stream->in, sid);
+}
+
+static struct flex_array *fa_alloc(size_t elem_size, size_t elem_count,
+				   gfp_t gfp)
+{
+	struct flex_array *result;
+	int err;
+
+	result = flex_array_alloc(elem_size, elem_count, gfp);
+	if (result) {
+		err = flex_array_prealloc(result, 0, elem_count, gfp);
+		if (err) {
+			flex_array_free(result);
+			result = NULL;
+		}
+	}
+
+	return result;
+}
+
+static void fa_free(struct flex_array *fa)
+{
+	if (fa)
+		flex_array_free(fa);
+}
+
+static void fa_copy(struct flex_array *fa, struct flex_array *from,
+		    size_t index, size_t count)
+{
+	void *elem;
+
+	while (count--) {
+		elem = flex_array_get(from, index);
+		flex_array_put(fa, index, elem, 0);
+		index++;
+	}
+}
+
+static void fa_zero(struct flex_array *fa, size_t index, size_t count)
+{
+	void *elem;
+
+	while (count--) {
+		elem = flex_array_get(fa, index);
+		memset(elem, 0, fa->element_size);
+		index++;
+	}
 }
 
 /* Migrates chunks from stream queues to new stream queues if needed,
@@ -106,19 +153,17 @@ static int sctp_stream_alloc_out(struct sctp_stream *stream, __u16 outcnt,
 	struct flex_array *out;
 	size_t elem_size = sizeof(struct sctp_stream_out);
 
-	out = kmalloc_array(outcnt, elem_size, gfp);
+	out = fa_alloc(elem_size, outcnt, gfp);
 	if (!out)
 		return -ENOMEM;
 
 	if (stream->out) {
-		memcpy(out, stream->out, min(outcnt, stream->outcnt) *
-					 elem_size);
-		kfree(stream->out);
+		fa_copy(out, stream->out, 0, min(outcnt, stream->outcnt));
+		fa_free(stream->out);
 	}
 
 	if (outcnt > stream->outcnt)
-		memset(((struct sctp_stream_out *)out) + stream->outcnt, 0,
-		       (outcnt - stream->outcnt) * elem_size);
+		fa_zero(out, stream->outcnt, (outcnt - stream->outcnt));
 
 	stream->out = out;
 
@@ -131,20 +176,17 @@ static int sctp_stream_alloc_in(struct sctp_stream *stream, __u16 incnt,
 	struct flex_array *in;
 	size_t elem_size = sizeof(struct sctp_stream_in);
 
-	in = kmalloc_array(incnt, elem_size, gfp);
-
+	in = fa_alloc(elem_size, incnt, gfp);
 	if (!in)
 		return -ENOMEM;
 
 	if (stream->in) {
-		memcpy(in, stream->in, min(incnt, stream->incnt) *
-				       elem_size);
-		kfree(stream->in);
+		fa_copy(in, stream->in, 0, min(incnt, stream->incnt));
+		fa_free(stream->in);
 	}
 
 	if (incnt > stream->incnt)
-		memset(((struct sctp_stream_in *)in) + stream->incnt, 0,
-		       (incnt - stream->incnt) * elem_size);
+		fa_zero(in, stream->incnt, (incnt - stream->incnt));
 
 	stream->in = in;
 
@@ -188,7 +230,7 @@ int sctp_stream_init(struct sctp_stream *stream, __u16 outcnt, __u16 incnt,
 	ret = sctp_stream_alloc_in(stream, incnt, gfp);
 	if (ret) {
 		sched->free(stream);
-		kfree(stream->out);
+		fa_free(stream->out);
 		stream->out = NULL;
 		stream->outcnt = 0;
 		goto out;
@@ -220,8 +262,8 @@ void sctp_stream_free(struct sctp_stream *stream)
 	sched->free(stream);
 	for (i = 0; i < stream->outcnt; i++)
 		kfree(SCTP_SO(stream, i)->ext);
-	kfree(stream->out);
-	kfree(stream->in);
+	fa_free(stream->out);
+	fa_free(stream->in);
 }
 
 void sctp_stream_clear(struct sctp_stream *stream)
-- 
1.8.3.1


  parent reply	other threads:[~2018-04-23 18:41 UTC|newest]

Thread overview: 64+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-04-23 18:41 [PATCH net-next 0/2] net/sctp: Avoid allocating high order memory with kmalloc() Oleg Babin
2018-04-23 18:41 ` Oleg Babin
2018-04-23 18:41 ` [PATCH net-next 1/2] net/sctp: Make wrappers for accessing in/out streams Oleg Babin
2018-04-23 18:41   ` Oleg Babin
2018-04-23 21:33   ` Marcelo Ricardo Leitner
2018-04-23 21:33     ` Marcelo Ricardo Leitner
2018-04-26 22:19     ` Oleg Babin
2018-04-26 22:19       ` Oleg Babin
2018-04-23 18:41 ` Oleg Babin [this message]
2018-04-23 18:41   ` [PATCH net-next 2/2] net/sctp: Replace in/out stream arrays with flex_array Oleg Babin
2018-04-23 21:33 ` [PATCH net-next 0/2] net/sctp: Avoid allocating high order memory with kmalloc() Marcelo Ricardo Leitner
2018-04-23 21:33   ` Marcelo Ricardo Leitner
2018-04-26 22:14   ` Oleg Babin
2018-04-26 22:14     ` Oleg Babin
2018-04-26 22:28     ` Marcelo Ricardo Leitner
2018-04-26 22:28       ` Marcelo Ricardo Leitner
2018-04-26 22:45       ` Oleg Babin
2018-04-26 22:45         ` Oleg Babin
2018-07-24 15:35       ` Konstantin Khorenko
2018-07-24 15:35         ` Konstantin Khorenko
2018-07-24 17:36         ` Marcelo Ricardo Leitner
2018-07-24 17:36           ` Marcelo Ricardo Leitner
2018-08-03 16:21           ` [PATCH v2 " Konstantin Khorenko
2018-08-03 16:21             ` Konstantin Khorenko
2018-08-03 16:21             ` [PATCH v2 1/2] net/sctp: Make wrappers for accessing in/out streams Konstantin Khorenko
2018-08-03 16:21               ` Konstantin Khorenko
2018-08-03 16:41               ` David Laight
2018-08-03 16:41                 ` David Laight
2018-08-03 19:50               ` David Miller
2018-08-03 19:50                 ` David Miller
2018-08-09  8:39                 ` Konstantin Khorenko
2018-08-09  8:39                   ` Konstantin Khorenko
2018-08-03 20:40               ` Marcelo Ricardo Leitner
2018-08-03 20:40                 ` Marcelo Ricardo Leitner
2018-08-09  8:40                 ` Konstantin Khorenko
2018-08-09  8:40                   ` Konstantin Khorenko
2018-08-03 16:21             ` [PATCH v2 2/2] net/sctp: Replace in/out stream arrays with flex_array Konstantin Khorenko
2018-08-03 16:21               ` Konstantin Khorenko
2018-08-03 16:43             ` [PATCH v2 0/2] net/sctp: Avoid allocating high order memory with kmalloc() David Laight
2018-08-03 16:43               ` David Laight
2018-08-03 20:30               ` Marcelo Ricardo Leitner
2018-08-03 20:30                 ` Marcelo Ricardo Leitner
2018-08-03 20:56                 ` Michael Tuexen
2018-08-03 20:56                   ` Michael Tuexen
2018-08-06  9:34                   ` David Laight
2018-08-06  9:34                     ` David Laight
2018-08-08 14:48                     ` Marcelo Ricardo Leitner
2018-08-08 14:48                       ` Marcelo Ricardo Leitner
2018-08-03 23:36             ` Marcelo Ricardo Leitner
2018-08-03 23:36               ` Marcelo Ricardo Leitner
2018-08-09  8:43               ` Konstantin Khorenko
2018-08-09  8:43                 ` Konstantin Khorenko
2018-08-10 17:03                 ` Konstantin Khorenko
2018-08-10 17:03                   ` Konstantin Khorenko
2018-08-10 17:11                   ` [PATCH v3 " Konstantin Khorenko
2018-08-10 17:11                     ` Konstantin Khorenko
2018-08-10 17:11                     ` [PATCH v3 1/2] net/sctp: Make wrappers for accessing in/out streams Konstantin Khorenko
2018-08-10 17:11                       ` Konstantin Khorenko
2018-08-10 17:11                     ` [PATCH v3 2/2] net/sctp: Replace in/out stream arrays with flex_array Konstantin Khorenko
2018-08-10 17:11                       ` Konstantin Khorenko
2018-08-11 19:36                     ` [PATCH v3 0/2] net/sctp: Avoid allocating high order memory with kmalloc() David Miller
2018-08-11 19:36                       ` David Miller
2018-08-10 17:41                   ` [PATCH v2 " Marcelo Ricardo Leitner
2018-08-10 17:41                     ` Marcelo Ricardo Leitner

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1524508866-317485-3-git-send-email-obabin@virtuozzo.com \
    --to=obabin@virtuozzo.com \
    --cc=aryabinin@virtuozzo.com \
    --cc=davem@davemloft.net \
    --cc=linux-sctp@vger.kernel.org \
    --cc=lucien.xin@gmail.com \
    --cc=marcelo.leitner@gmail.com \
    --cc=netdev@vger.kernel.org \
    --cc=nhorman@tuxdriver.com \
    --cc=vyasevich@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.