linux/fs/nfsd/fault_inject.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2011 Bryan Schumaker <bjschuma@netapp.com>
   3 *
   4 * Uses debugfs to create fault injection points for client testing
   5 */
   6
   7#include <linux/types.h>
   8#include <linux/fs.h>
   9#include <linux/debugfs.h>
  10#include <linux/module.h>
  11#include <linux/nsproxy.h>
  12#include <linux/sunrpc/addr.h>
  13#include <asm/uaccess.h>
  14
  15#include "state.h"
  16#include "netns.h"
  17
  18struct nfsd_fault_inject_op {
  19        char *file;
  20        u64 (*forget)(struct nfs4_client *, u64);
  21        u64 (*print)(struct nfs4_client *, u64);
  22};
  23
  24static struct nfsd_fault_inject_op inject_ops[] = {
  25        {
  26                .file   = "forget_clients",
  27                .forget = nfsd_forget_client,
  28                .print  = nfsd_print_client,
  29        },
  30        {
  31                .file   = "forget_locks",
  32                .forget = nfsd_forget_client_locks,
  33                .print  = nfsd_print_client_locks,
  34        },
  35        {
  36                .file   = "forget_openowners",
  37                .forget = nfsd_forget_client_openowners,
  38                .print  = nfsd_print_client_openowners,
  39        },
  40        {
  41                .file   = "forget_delegations",
  42                .forget = nfsd_forget_client_delegations,
  43                .print  = nfsd_print_client_delegations,
  44        },
  45        {
  46                .file   = "recall_delegations",
  47                .forget = nfsd_recall_client_delegations,
  48                .print  = nfsd_print_client_delegations,
  49        },
  50};
  51
  52static long int NUM_INJECT_OPS = sizeof(inject_ops) / sizeof(struct nfsd_fault_inject_op);
  53static struct dentry *debug_dir;
  54
  55static void nfsd_inject_set(struct nfsd_fault_inject_op *op, u64 val)
  56{
  57        u64 count = 0;
  58
  59        if (val == 0)
  60                printk(KERN_INFO "NFSD Fault Injection: %s (all)", op->file);
  61        else
  62                printk(KERN_INFO "NFSD Fault Injection: %s (n = %llu)", op->file, val);
  63
  64        nfs4_lock_state();
  65        count = nfsd_for_n_state(val, op->forget);
  66        nfs4_unlock_state();
  67        printk(KERN_INFO "NFSD: %s: found %llu", op->file, count);
  68}
  69
  70static void nfsd_inject_set_client(struct nfsd_fault_inject_op *op,
  71                                   struct sockaddr_storage *addr,
  72                                   size_t addr_size)
  73{
  74        char buf[INET6_ADDRSTRLEN];
  75        struct nfs4_client *clp;
  76        u64 count;
  77
  78        nfs4_lock_state();
  79        clp = nfsd_find_client(addr, addr_size);
  80        if (clp) {
  81                count = op->forget(clp, 0);
  82                rpc_ntop((struct sockaddr *)&clp->cl_addr, buf, sizeof(buf));
  83                printk(KERN_INFO "NFSD [%s]: Client %s had %llu state object(s)\n", op->file, buf, count);
  84        }
  85        nfs4_unlock_state();
  86}
  87
  88static void nfsd_inject_get(struct nfsd_fault_inject_op *op, u64 *val)
  89{
  90        nfs4_lock_state();
  91        *val = nfsd_for_n_state(0, op->print);
  92        nfs4_unlock_state();
  93}
  94
  95static ssize_t fault_inject_read(struct file *file, char __user *buf,
  96                                 size_t len, loff_t *ppos)
  97{
  98        static u64 val;
  99        char read_buf[25];
 100        size_t size, ret;
 101        loff_t pos = *ppos;
 102
 103        if (!pos)
 104                nfsd_inject_get(file_inode(file)->i_private, &val);
 105        size = scnprintf(read_buf, sizeof(read_buf), "%llu\n", val);
 106
 107        if (pos < 0)
 108                return -EINVAL;
 109        if (pos >= size || !len)
 110                return 0;
 111        if (len > size - pos)
 112                len = size - pos;
 113        ret = copy_to_user(buf, read_buf + pos, len);
 114        if (ret == len)
 115                return -EFAULT;
 116        len -= ret;
 117        *ppos = pos + len;
 118        return len;
 119}
 120
 121static ssize_t fault_inject_write(struct file *file, const char __user *buf,
 122                                  size_t len, loff_t *ppos)
 123{
 124        char write_buf[INET6_ADDRSTRLEN];
 125        size_t size = min(sizeof(write_buf) - 1, len);
 126        struct net *net = current->nsproxy->net_ns;
 127        struct sockaddr_storage sa;
 128        u64 val;
 129
 130        if (copy_from_user(write_buf, buf, size))
 131                return -EFAULT;
 132        write_buf[size] = '\0';
 133
 134        size = rpc_pton(net, write_buf, size, (struct sockaddr *)&sa, sizeof(sa));
 135        if (size > 0)
 136                nfsd_inject_set_client(file_inode(file)->i_private, &sa, size);
 137        else {
 138                val = simple_strtoll(write_buf, NULL, 0);
 139                nfsd_inject_set(file_inode(file)->i_private, val);
 140        }
 141        return len; /* on success, claim we got the whole input */
 142}
 143
 144static const struct file_operations fops_nfsd = {
 145        .owner   = THIS_MODULE,
 146        .read    = fault_inject_read,
 147        .write   = fault_inject_write,
 148};
 149
 150void nfsd_fault_inject_cleanup(void)
 151{
 152        debugfs_remove_recursive(debug_dir);
 153}
 154
 155int nfsd_fault_inject_init(void)
 156{
 157        unsigned int i;
 158        struct nfsd_fault_inject_op *op;
 159        umode_t mode = S_IFREG | S_IRUSR | S_IWUSR;
 160
 161        debug_dir = debugfs_create_dir("nfsd", NULL);
 162        if (!debug_dir)
 163                goto fail;
 164
 165        for (i = 0; i < NUM_INJECT_OPS; i++) {
 166                op = &inject_ops[i];
 167                if (!debugfs_create_file(op->file, mode, debug_dir, op, &fops_nfsd))
 168                        goto fail;
 169        }
 170        return 0;
 171
 172fail:
 173        nfsd_fault_inject_cleanup();
 174        return -ENOMEM;
 175}
 176
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.