fail_futex=
        mmc_core.fail_request=<interval>,<probability>,<space>,<times>
 
+o proc entries
+
+- /proc/self/task/<current-tid>/fail-nth:
+
+       Write to this file of integer N makes N-th call in the current task fail
+       (N is 0-based). Read from this file returns a single char 'Y' or 'N'
+       that says if the fault setup with a previous write to this file was
+       injected or not, and disables the fault if it wasn't yet injected.
+       Note that this file enables all types of faults (slab, futex, etc).
+       This setting takes precedence over all other generic debugfs settings
+       like probability, interval, times, etc. But per-capability settings
+       (e.g. fail_futex/ignore-private) take precedence over it.
+
+       This feature is intended for systematic testing of faults in a single
+       system call. See an example below.
+
 How to add new fault injection capability
 -----------------------------------------
 
        # env FAILCMD_TYPE=fail_page_alloc \
                ./tools/testing/fault-injection/failcmd.sh --times=100 \
                 -- make -C tools/testing/selftests/ run_tests
+
+Systematic faults using fail-nth
+---------------------------------
+
+The following code systematically faults 0-th, 1-st, 2-nd and so on
+capabilities in the socketpair() system call.
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/syscall.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+
+int main()
+{
+       int i, err, res, fail_nth, fds[2];
+       char buf[128];
+
+       system("echo N > /sys/kernel/debug/failslab/ignore-gfp-wait");
+       sprintf(buf, "/proc/self/task/%ld/fail-nth", syscall(SYS_gettid));
+       fail_nth = open(buf, O_RDWR);
+       for (i = 0;; i++) {
+               sprintf(buf, "%d", i);
+               write(fail_nth, buf, strlen(buf));
+               res = socketpair(AF_LOCAL, SOCK_STREAM, 0, fds);
+               err = errno;
+               read(fail_nth, buf, 1);
+               if (res == 0) {
+                       close(fds[0]);
+                       close(fds[1]);
+               }
+               printf("%d-th fault %c: res=%d/%d\n", i, buf[0], res, err);
+               if (buf[0] != 'Y')
+                       break;
+       }
+       return 0;
+}
+
+An example output:
+
+0-th fault Y: res=-1/23
+1-th fault Y: res=-1/23
+2-th fault Y: res=-1/23
+3-th fault Y: res=-1/12
+4-th fault Y: res=-1/12
+5-th fault Y: res=-1/23
+6-th fault Y: res=-1/23
+7-th fault Y: res=-1/23
+8-th fault Y: res=-1/12
+9-th fault Y: res=-1/12
+10-th fault Y: res=-1/12
+11-th fault Y: res=-1/12
+12-th fault Y: res=-1/12
+13-th fault Y: res=-1/12
+14-th fault Y: res=-1/12
+15-th fault Y: res=-1/12
+16-th fault N: res=0/12
 
        .write          = proc_fault_inject_write,
        .llseek         = generic_file_llseek,
 };
+
+static ssize_t proc_fail_nth_write(struct file *file, const char __user *buf,
+                                  size_t count, loff_t *ppos)
+{
+       struct task_struct *task;
+       int err, n;
+
+       task = get_proc_task(file_inode(file));
+       if (!task)
+               return -ESRCH;
+       put_task_struct(task);
+       if (task != current)
+               return -EPERM;
+       err = kstrtoint_from_user(buf, count, 10, &n);
+       if (err)
+               return err;
+       if (n < 0 || n == INT_MAX)
+               return -EINVAL;
+       current->fail_nth = n + 1;
+       return count;
+}
+
+static ssize_t proc_fail_nth_read(struct file *file, char __user *buf,
+                                 size_t count, loff_t *ppos)
+{
+       struct task_struct *task;
+       int err;
+
+       task = get_proc_task(file_inode(file));
+       if (!task)
+               return -ESRCH;
+       put_task_struct(task);
+       if (task != current)
+               return -EPERM;
+       if (count < 1)
+               return -EINVAL;
+       err = put_user((char)(current->fail_nth ? 'N' : 'Y'), buf);
+       if (err)
+               return err;
+       current->fail_nth = 0;
+       return 1;
+}
+
+static const struct file_operations proc_fail_nth_operations = {
+       .read           = proc_fail_nth_read,
+       .write          = proc_fail_nth_write,
+};
 #endif
 
 
 #endif
 #ifdef CONFIG_FAULT_INJECTION
        REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),
+       /*
+        * Operations on the file check that the task is current,
+        * so we create it with 0666 to support testing under unprivileged user.
+        */
+       REG("fail-nth", 0666, proc_fail_nth_operations),
 #endif
 #ifdef CONFIG_TASK_IO_ACCOUNTING
        ONE("io",       S_IRUSR, proc_tid_io_accounting),