]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - net/sctp/stream.c
Merge branch 'timers-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[linux.git] / net / sctp / stream.c
index 80e0ae5534ecb0e134d609097271967d87f6ba4f..b6bb68adac6e294b1d4caee5efaab8f93e6a683a 100644 (file)
 #include <net/sctp/sm.h>
 #include <net/sctp/stream_sched.h>
 
-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,
  * but not across associations. Also, removes those chunks to streams
  * higher than the new max.
@@ -131,53 +84,41 @@ static void sctp_stream_outq_migrate(struct sctp_stream *stream,
                }
        }
 
-       for (i = outcnt; i < stream->outcnt; i++)
+       for (i = outcnt; i < stream->outcnt; i++) {
                kfree(SCTP_SO(stream, i)->ext);
+               SCTP_SO(stream, i)->ext = NULL;
+       }
 }
 
 static int sctp_stream_alloc_out(struct sctp_stream *stream, __u16 outcnt,
                                 gfp_t gfp)
 {
-       struct flex_array *out;
-       size_t elem_size = sizeof(struct sctp_stream_out);
-
-       out = fa_alloc(elem_size, outcnt, gfp);
-       if (!out)
-               return -ENOMEM;
-
-       if (stream->out) {
-               fa_copy(out, stream->out, 0, min(outcnt, stream->outcnt));
-               fa_free(stream->out);
-       }
+       int ret;
 
-       if (outcnt > stream->outcnt)
-               fa_zero(out, stream->outcnt, (outcnt - stream->outcnt));
+       if (outcnt <= stream->outcnt)
+               return 0;
 
-       stream->out = out;
+       ret = genradix_prealloc(&stream->out, outcnt, gfp);
+       if (ret)
+               return ret;
 
+       stream->outcnt = outcnt;
        return 0;
 }
 
 static int sctp_stream_alloc_in(struct sctp_stream *stream, __u16 incnt,
                                gfp_t gfp)
 {
-       struct flex_array *in;
-       size_t elem_size = sizeof(struct sctp_stream_in);
-
-       in = fa_alloc(elem_size, incnt, gfp);
-       if (!in)
-               return -ENOMEM;
-
-       if (stream->in) {
-               fa_copy(in, stream->in, 0, min(incnt, stream->incnt));
-               fa_free(stream->in);
-       }
+       int ret;
 
-       if (incnt > stream->incnt)
-               fa_zero(in, stream->incnt, (incnt - stream->incnt));
+       if (incnt <= stream->incnt)
+               return 0;
 
-       stream->in = in;
+       ret = genradix_prealloc(&stream->in, incnt, gfp);
+       if (ret)
+               return ret;
 
+       stream->incnt = incnt;
        return 0;
 }
 
@@ -204,12 +145,9 @@ int sctp_stream_init(struct sctp_stream *stream, __u16 outcnt, __u16 incnt,
        if (ret)
                goto out;
 
-       stream->outcnt = outcnt;
        for (i = 0; i < stream->outcnt; i++)
                SCTP_SO(stream, i)->state = SCTP_STREAM_OPEN;
 
-       sched->init(stream);
-
 in:
        sctp_stream_interleave_init(stream);
        if (!incnt)
@@ -218,14 +156,11 @@ 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);
-               fa_free(stream->out);
-               stream->out = NULL;
+               genradix_free(&stream->out);
                stream->outcnt = 0;
                goto out;
        }
 
-       stream->incnt = incnt;
-
 out:
        return ret;
 }
@@ -250,8 +185,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);
-       fa_free(stream->out);
-       fa_free(stream->in);
+       genradix_free(&stream->out);
+       genradix_free(&stream->in);
 }
 
 void sctp_stream_clear(struct sctp_stream *stream)
@@ -282,8 +217,8 @@ void sctp_stream_update(struct sctp_stream *stream, struct sctp_stream *new)
 
        sched->sched_all(stream);
 
-       new->out = NULL;
-       new->in  = NULL;
+       new->out.tree.root = NULL;
+       new->in.tree.root  = NULL;
        new->outcnt = 0;
        new->incnt  = 0;
 }
@@ -535,8 +470,6 @@ int sctp_send_add_streams(struct sctp_association *asoc,
                goto out;
        }
 
-       stream->outcnt = outcnt;
-
        asoc->strreset_outstanding = !!out + !!in;
 
 out: