Synopsis of kprobe_events
 -------------------------
   p[:[GRP/]EVENT] [MOD:]SYM[+offs]|MEMADDR [FETCHARGS] : Set a probe
-  r[:[GRP/]EVENT] [MOD:]SYM[+0] [FETCHARGS]            : Set a return probe
+  r[MAXACTIVE][:[GRP/]EVENT] [MOD:]SYM[+0] [FETCHARGS] : Set a return probe
   -:[GRP/]EVENT                                                : Clear a probe
 
  GRP           : Group name. If omitted, use "kprobes" for it.
  MOD           : Module name which has given SYM.
  SYM[+offs]    : Symbol+offset where the probe is inserted.
  MEMADDR       : Address where the probe is inserted.
+ MAXACTIVE     : Maximum number of instances of the specified function that
+                 can be probed simultaneously, or 0 for the default value
+                 as defined in Documentation/kprobes.txt section 1.3.1.
 
  FETCHARGS     : Arguments. Each probe can have up to 128 args.
   %REG         : Fetch register REG
 
 #include "trace_probe.h"
 
 #define KPROBE_EVENT_SYSTEM "kprobes"
+#define KRETPROBE_MAXACTIVE_MAX 4096
 
 /**
  * Kprobe event core functions
                                             void *addr,
                                             const char *symbol,
                                             unsigned long offs,
+                                            int maxactive,
                                             int nargs, bool is_return)
 {
        struct trace_kprobe *tk;
        else
                tk->rp.kp.pre_handler = kprobe_dispatcher;
 
+       tk->rp.maxactive = maxactive;
+
        if (!event || !is_good_name(event)) {
                ret = -EINVAL;
                goto error;
 {
        /*
         * Argument syntax:
-        *  - Add kprobe: p[:[GRP/]EVENT] [MOD:]KSYM[+OFFS]|KADDR [FETCHARGS]
-        *  - Add kretprobe: r[:[GRP/]EVENT] [MOD:]KSYM[+0] [FETCHARGS]
+        *  - Add kprobe:
+        *      p[:[GRP/]EVENT] [MOD:]KSYM[+OFFS]|KADDR [FETCHARGS]
+        *  - Add kretprobe:
+        *      r[MAXACTIVE][:[GRP/]EVENT] [MOD:]KSYM[+0] [FETCHARGS]
         * Fetch args:
         *  $retval     : fetch return value
         *  $stack      : fetch stack address
        int i, ret = 0;
        bool is_return = false, is_delete = false;
        char *symbol = NULL, *event = NULL, *group = NULL;
+       int maxactive = 0;
        char *arg;
        unsigned long offset = 0;
        void *addr = NULL;
                return -EINVAL;
        }
 
-       if (argv[0][1] == ':') {
-               event = &argv[0][2];
+       event = strchr(&argv[0][1], ':');
+       if (event) {
+               event[0] = '\0';
+               event++;
+       }
+       if (is_return && isdigit(argv[0][1])) {
+               ret = kstrtouint(&argv[0][1], 0, &maxactive);
+               if (ret) {
+                       pr_info("Failed to parse maxactive.\n");
+                       return ret;
+               }
+               /* kretprobes instances are iterated over via a list. The
+                * maximum should stay reasonable.
+                */
+               if (maxactive > KRETPROBE_MAXACTIVE_MAX) {
+                       pr_info("Maxactive is too big (%d > %d).\n",
+                               maxactive, KRETPROBE_MAXACTIVE_MAX);
+                       return -E2BIG;
+               }
+       }
+
+       if (event) {
                if (strchr(event, '/')) {
                        group = event;
                        event = strchr(group, '/') + 1;
                                 is_return ? 'r' : 'p', addr);
                event = buf;
        }
-       tk = alloc_trace_kprobe(group, event, addr, symbol, offset, argc,
-                              is_return);
+       tk = alloc_trace_kprobe(group, event, addr, symbol, offset, maxactive,
+                              argc, is_return);
        if (IS_ERR(tk)) {
                pr_info("Failed to allocate trace_probe.(%d)\n",
                        (int)PTR_ERR(tk));
 
--- /dev/null
+#!/bin/sh
+# description: Kretprobe dynamic event with maxactive
+
+[ -f kprobe_events ] || exit_unsupported # this is configurable
+
+echo > kprobe_events
+
+# Test if we successfully reject unknown messages
+if echo 'a:myprobeaccept inet_csk_accept' > kprobe_events; then false; else true; fi
+
+# Test if we successfully reject too big maxactive
+if echo 'r1000000:myprobeaccept inet_csk_accept' > kprobe_events; then false; else true; fi
+
+# Test if we successfully reject unparsable numbers for maxactive
+if echo 'r10fuzz:myprobeaccept inet_csk_accept' > kprobe_events; then false; else true; fi
+
+# Test for kretprobe with event name without maxactive
+echo 'r:myprobeaccept inet_csk_accept' > kprobe_events
+grep myprobeaccept kprobe_events
+test -d events/kprobes/myprobeaccept
+echo '-:myprobeaccept' >> kprobe_events
+
+# Test for kretprobe with event name with a small maxactive
+echo 'r10:myprobeaccept inet_csk_accept' > kprobe_events
+grep myprobeaccept kprobe_events
+test -d events/kprobes/myprobeaccept
+echo '-:myprobeaccept' >> kprobe_events
+
+# Test for kretprobe without event name without maxactive
+echo 'r inet_csk_accept' > kprobe_events
+grep inet_csk_accept kprobe_events
+echo > kprobe_events
+
+# Test for kretprobe without event name with a small maxactive
+echo 'r10 inet_csk_accept' > kprobe_events
+grep inet_csk_accept kprobe_events
+echo > kprobe_events
+
+clear_trace