From mboxrd@z Thu Jan 1 00:00:00 1970 From: Oleg Babin 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 Message-ID: <1524508866-317485-3-git-send-email-obabin@virtuozzo.com> References: <1524508866-317485-1-git-send-email-obabin@virtuozzo.com> Mime-Version: 1.0 Content-Type: text/plain Cc: "David S. Miller" , Vlad Yasevich , Neil Horman , Xin Long , Marcelo Ricardo Leitner , Andrey Ryabinin To: netdev@vger.kernel.org, linux-sctp@vger.kernel.org Return-path: Received: from mail-eopbgr00116.outbound.protection.outlook.com ([40.107.0.116]:29696 "EHLO EUR02-AM5-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S932085AbeDWSlo (ORCPT ); Mon, 23 Apr 2018 14:41:44 -0400 In-Reply-To: <1524508866-317485-1-git-send-email-obabin@virtuozzo.com> Sender: netdev-owner@vger.kernel.org List-ID: 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 --- 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 /* This gets us atomic counters. */ #include /* We need sk_buff_head. */ #include /* We need tq_struct. */ +#include /* We need flex_array. */ #include /* We need sctp* header structs. */ #include /* We need auth specific structs */ #include /* 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 From mboxrd@z Thu Jan 1 00:00:00 1970 From: Oleg Babin Date: Mon, 23 Apr 2018 18:41:06 +0000 Subject: [PATCH net-next 2/2] net/sctp: Replace in/out stream arrays with flex_array Message-Id: <1524508866-317485-3-git-send-email-obabin@virtuozzo.com> List-Id: References: <1524508866-317485-1-git-send-email-obabin@virtuozzo.com> In-Reply-To: <1524508866-317485-1-git-send-email-obabin@virtuozzo.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: netdev@vger.kernel.org, linux-sctp@vger.kernel.org Cc: "David S. Miller" , Vlad Yasevich , Neil Horman , Xin Long , Marcelo Ricardo Leitner , Andrey Ryabinin 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 --- 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 /* This gets us atomic counters. */ #include /* We need sk_buff_head. */ #include /* We need tq_struct. */ +#include /* We need flex_array. */ #include /* We need sctp* header structs. */ #include /* We need auth specific structs */ #include /* 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