nfsd: abstract out the get and set routines into the fault injection ops
authorJeff Layton <jlayton@primarydata.com>
Wed, 30 Jul 2014 12:27:16 +0000 (08:27 -0400)
committerJ. Bruce Fields <bfields@redhat.com>
Tue, 5 Aug 2014 14:55:02 +0000 (10:55 -0400)
Now that we've added more granular locking in other places, it's time
to address the fault injection code. This code is currently quite
reliant on the client_mutex for protection. Start to change this by
adding a new set of fault injection op vectors.

For now they all use the legacy ones. In later patches we'll add new
routines that can deal with more granular locking.

Also, move some of the printk routines into the callers to make the
results of the operations more uniform.

Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
fs/nfsd/fault_inject.c

index f1333fc..b115990 100644 (file)
 
 struct nfsd_fault_inject_op {
        char *file;
+       u64 (*get)(struct nfsd_fault_inject_op *);
+       u64 (*set_val)(struct nfsd_fault_inject_op *, u64);
+       u64 (*set_clnt)(struct nfsd_fault_inject_op *,
+                       struct sockaddr_storage *, size_t);
        u64 (*forget)(struct nfs4_client *, u64);
        u64 (*print)(struct nfs4_client *, u64);
 };
 
-static struct nfsd_fault_inject_op inject_ops[] = {
-       {
-               .file   = "forget_clients",
-               .forget = nfsd_forget_client,
-               .print  = nfsd_print_client,
-       },
-       {
-               .file   = "forget_locks",
-               .forget = nfsd_forget_client_locks,
-               .print  = nfsd_print_client_locks,
-       },
-       {
-               .file   = "forget_openowners",
-               .forget = nfsd_forget_client_openowners,
-               .print  = nfsd_print_client_openowners,
-       },
-       {
-               .file   = "forget_delegations",
-               .forget = nfsd_forget_client_delegations,
-               .print  = nfsd_print_client_delegations,
-       },
-       {
-               .file   = "recall_delegations",
-               .forget = nfsd_recall_client_delegations,
-               .print  = nfsd_print_client_delegations,
-       },
-};
-
-static long int NUM_INJECT_OPS = sizeof(inject_ops) / sizeof(struct nfsd_fault_inject_op);
 static struct dentry *debug_dir;
 
-static void nfsd_inject_set(struct nfsd_fault_inject_op *op, u64 val)
+static u64 nfsd_inject_set(struct nfsd_fault_inject_op *op, u64 val)
 {
-       u64 count = 0;
-
-       if (val == 0)
-               printk(KERN_INFO "NFSD Fault Injection: %s (all)", op->file);
-       else
-               printk(KERN_INFO "NFSD Fault Injection: %s (n = %llu)", op->file, val);
+       u64 count;
 
        nfs4_lock_state();
        count = nfsd_for_n_state(val, op->forget);
        nfs4_unlock_state();
-       printk(KERN_INFO "NFSD: %s: found %llu", op->file, count);
+       return count;
 }
 
-static void nfsd_inject_set_client(struct nfsd_fault_inject_op *op,
+static u64 nfsd_inject_set_client(struct nfsd_fault_inject_op *op,
                                   struct sockaddr_storage *addr,
                                   size_t addr_size)
 {
-       char buf[INET6_ADDRSTRLEN];
        struct nfs4_client *clp;
-       u64 count;
+       u64 count = 0;
 
        nfs4_lock_state();
        clp = nfsd_find_client(addr, addr_size);
-       if (clp) {
+       if (clp)
                count = op->forget(clp, 0);
-               rpc_ntop((struct sockaddr *)&clp->cl_addr, buf, sizeof(buf));
-               printk(KERN_INFO "NFSD [%s]: Client %s had %llu state object(s)\n", op->file, buf, count);
-       }
        nfs4_unlock_state();
+       return count;
 }
 
-static void nfsd_inject_get(struct nfsd_fault_inject_op *op, u64 *val)
+static u64 nfsd_inject_get(struct nfsd_fault_inject_op *op)
 {
+       u64 count;
+
        nfs4_lock_state();
-       *val = nfsd_for_n_state(0, op->print);
+       count = nfsd_for_n_state(0, op->print);
        nfs4_unlock_state();
+
+       return count;
 }
 
 static ssize_t fault_inject_read(struct file *file, char __user *buf,
@@ -99,9 +70,10 @@ static ssize_t fault_inject_read(struct file *file, char __user *buf,
        char read_buf[25];
        size_t size;
        loff_t pos = *ppos;
+       struct nfsd_fault_inject_op *op = file_inode(file)->i_private;
 
        if (!pos)
-               nfsd_inject_get(file_inode(file)->i_private, &val);
+               val = op->get(op);
        size = scnprintf(read_buf, sizeof(read_buf), "%llu\n", val);
 
        return simple_read_from_buffer(buf, len, ppos, read_buf, size);
@@ -114,6 +86,7 @@ static ssize_t fault_inject_write(struct file *file, const char __user *buf,
        size_t size = min(sizeof(write_buf) - 1, len);
        struct net *net = current->nsproxy->net_ns;
        struct sockaddr_storage sa;
+       struct nfsd_fault_inject_op *op = file_inode(file)->i_private;
        u64 val;
        char *nl;
 
@@ -129,11 +102,20 @@ static ssize_t fault_inject_write(struct file *file, const char __user *buf,
        }
 
        size = rpc_pton(net, write_buf, size, (struct sockaddr *)&sa, sizeof(sa));
-       if (size > 0)
-               nfsd_inject_set_client(file_inode(file)->i_private, &sa, size);
-       else {
+       if (size > 0) {
+               val = op->set_clnt(op, &sa, size);
+               if (val)
+                       pr_info("NFSD [%s]: Client %s had %llu state object(s)\n",
+                               op->file, write_buf, val);
+       } else {
                val = simple_strtoll(write_buf, NULL, 0);
-               nfsd_inject_set(file_inode(file)->i_private, val);
+               if (val == 0)
+                       pr_info("NFSD Fault Injection: %s (all)", op->file);
+               else
+                       pr_info("NFSD Fault Injection: %s (n = %llu)",
+                               op->file, val);
+               val = op->set_val(op, val);
+               pr_info("NFSD: %s: found %llu", op->file, val);
        }
        return len; /* on success, claim we got the whole input */
 }
@@ -149,6 +131,51 @@ void nfsd_fault_inject_cleanup(void)
        debugfs_remove_recursive(debug_dir);
 }
 
+static struct nfsd_fault_inject_op inject_ops[] = {
+       {
+               .file     = "forget_clients",
+               .get      = nfsd_inject_get,
+               .set_val  = nfsd_inject_set,
+               .set_clnt = nfsd_inject_set_client,
+               .forget   = nfsd_forget_client,
+               .print    = nfsd_print_client,
+       },
+       {
+               .file     = "forget_locks",
+               .get      = nfsd_inject_get,
+               .set_val  = nfsd_inject_set,
+               .set_clnt = nfsd_inject_set_client,
+               .forget   = nfsd_forget_client_locks,
+               .print    = nfsd_print_client_locks,
+       },
+       {
+               .file     = "forget_openowners",
+               .get      = nfsd_inject_get,
+               .set_val  = nfsd_inject_set,
+               .set_clnt = nfsd_inject_set_client,
+               .forget   = nfsd_forget_client_openowners,
+               .print    = nfsd_print_client_openowners,
+       },
+       {
+               .file     = "forget_delegations",
+               .get      = nfsd_inject_get,
+               .set_val  = nfsd_inject_set,
+               .set_clnt = nfsd_inject_set_client,
+               .forget   = nfsd_forget_client_delegations,
+               .print    = nfsd_print_client_delegations,
+       },
+       {
+               .file     = "recall_delegations",
+               .get      = nfsd_inject_get,
+               .set_val  = nfsd_inject_set,
+               .set_clnt = nfsd_inject_set_client,
+               .forget   = nfsd_recall_client_delegations,
+               .print    = nfsd_print_client_delegations,
+       },
+};
+
+#define NUM_INJECT_OPS (sizeof(inject_ops)/sizeof(struct nfsd_fault_inject_op))
+
 int nfsd_fault_inject_init(void)
 {
        unsigned int i;