NFS: include filelayout DS rpc stats in mountstats
authorWeston Andros Adamson <dros@netapp.com>
Fri, 17 Feb 2012 18:15:24 +0000 (13:15 -0500)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Fri, 17 Feb 2012 18:39:47 +0000 (13:39 -0500)
Include RPC statistics from all data servers in /proc/self/mountstats for pNFS
filelayout mounts.

Signed-off-by: Weston Andros Adamson <dros@netapp.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
fs/nfs/nfs4filelayout.c
include/linux/sunrpc/metrics.h
include/linux/sunrpc/sched.h
net/sunrpc/stats.c
net/sunrpc/xprt.c

index 79be7acc9bae4ff03b59b269ac7e2a86c725a163..47e8f3435d3811591dedfacefcf5cd1070c22241 100644 (file)
@@ -33,6 +33,8 @@
 #include <linux/nfs_page.h>
 #include <linux/module.h>
 
+#include <linux/sunrpc/metrics.h>
+
 #include "internal.h"
 #include "nfs4filelayout.h"
 
@@ -189,6 +191,13 @@ static void filelayout_read_call_done(struct rpc_task *task, void *data)
        rdata->mds_ops->rpc_call_done(task, data);
 }
 
+static void filelayout_read_count_stats(struct rpc_task *task, void *data)
+{
+       struct nfs_read_data *rdata = (struct nfs_read_data *)data;
+
+       rpc_count_iostats(task, NFS_SERVER(rdata->inode)->client->cl_metrics);
+}
+
 static void filelayout_read_release(void *data)
 {
        struct nfs_read_data *rdata = (struct nfs_read_data *)data;
@@ -268,6 +277,13 @@ static void filelayout_write_call_done(struct rpc_task *task, void *data)
        wdata->mds_ops->rpc_call_done(task, data);
 }
 
+static void filelayout_write_count_stats(struct rpc_task *task, void *data)
+{
+       struct nfs_write_data *wdata = (struct nfs_write_data *)data;
+
+       rpc_count_iostats(task, NFS_SERVER(wdata->inode)->client->cl_metrics);
+}
+
 static void filelayout_write_release(void *data)
 {
        struct nfs_write_data *wdata = (struct nfs_write_data *)data;
@@ -288,18 +304,21 @@ static void filelayout_commit_release(void *data)
 struct rpc_call_ops filelayout_read_call_ops = {
        .rpc_call_prepare = filelayout_read_prepare,
        .rpc_call_done = filelayout_read_call_done,
+       .rpc_count_stats = filelayout_read_count_stats,
        .rpc_release = filelayout_read_release,
 };
 
 struct rpc_call_ops filelayout_write_call_ops = {
        .rpc_call_prepare = filelayout_write_prepare,
        .rpc_call_done = filelayout_write_call_done,
+       .rpc_count_stats = filelayout_write_count_stats,
        .rpc_release = filelayout_write_release,
 };
 
 struct rpc_call_ops filelayout_commit_call_ops = {
        .rpc_call_prepare = filelayout_write_prepare,
        .rpc_call_done = filelayout_write_call_done,
+       .rpc_count_stats = filelayout_write_count_stats,
        .rpc_release = filelayout_commit_release,
 };
 
index b6edbc0ea83dddcdc450fa05a06cc6face7d69b5..1565bbe86d51e77c2323ca26a04bbad8a35b9f22 100644 (file)
@@ -74,14 +74,16 @@ struct rpc_clnt;
 #ifdef CONFIG_PROC_FS
 
 struct rpc_iostats *   rpc_alloc_iostats(struct rpc_clnt *);
-void                   rpc_count_iostats(struct rpc_task *);
+void                   rpc_count_iostats(const struct rpc_task *,
+                                         struct rpc_iostats *);
 void                   rpc_print_iostats(struct seq_file *, struct rpc_clnt *);
 void                   rpc_free_iostats(struct rpc_iostats *);
 
 #else  /*  CONFIG_PROC_FS  */
 
 static inline struct rpc_iostats *rpc_alloc_iostats(struct rpc_clnt *clnt) { return NULL; }
-static inline void rpc_count_iostats(struct rpc_task *task) {}
+static inline void rpc_count_iostats(const struct rpc_task *task,
+                                    struct rpc_iostats *stats) {}
 static inline void rpc_print_iostats(struct seq_file *seq, struct rpc_clnt *clnt) {}
 static inline void rpc_free_iostats(struct rpc_iostats *stats) {}
 
index 22dfc24013b6daa5155d93982f73a7675de8f87b..dc0c3cc3ada3f8ced03b7fb00b2b1772bb722034 100644 (file)
@@ -103,6 +103,7 @@ typedef void                        (*rpc_action)(struct rpc_task *);
 struct rpc_call_ops {
        void (*rpc_call_prepare)(struct rpc_task *, void *);
        void (*rpc_call_done)(struct rpc_task *, void *);
+       void (*rpc_count_stats)(struct rpc_task *, void *);
        void (*rpc_release)(void *);
 };
 
index 3c4f6888c89144b06b30c1e4c53c1a0085a3d4c9..1eb3304bc1055549513f3d1d842f634c8f9cd464 100644 (file)
@@ -133,20 +133,19 @@ EXPORT_SYMBOL_GPL(rpc_free_iostats);
 /**
  * rpc_count_iostats - tally up per-task stats
  * @task: completed rpc_task
+ * @stats: array of stat structures
  *
  * Relies on the caller for serialization.
  */
-void rpc_count_iostats(struct rpc_task *task)
+void rpc_count_iostats(const struct rpc_task *task, struct rpc_iostats *stats)
 {
        struct rpc_rqst *req = task->tk_rqstp;
-       struct rpc_iostats *stats;
        struct rpc_iostats *op_metrics;
        ktime_t delta;
 
-       if (!task->tk_client || !task->tk_client->cl_metrics || !req)
+       if (!stats || !req)
                return;
 
-       stats = task->tk_client->cl_metrics;
        op_metrics = &stats[task->tk_msg.rpc_proc->p_statidx];
 
        op_metrics->om_ops++;
@@ -164,6 +163,7 @@ void rpc_count_iostats(struct rpc_task *task)
        delta = ktime_sub(ktime_get(), task->tk_start);
        op_metrics->om_execute = ktime_add(op_metrics->om_execute, delta);
 }
+EXPORT_SYMBOL_GPL(rpc_count_iostats);
 
 static void _print_name(struct seq_file *seq, unsigned int op,
                        struct rpc_procinfo *procs)
index 739df8a113824e42ee7040908efa3a042a24688d..32e37945a8403157b875443556448d84c3ef7af5 100644 (file)
@@ -1137,7 +1137,10 @@ void xprt_release(struct rpc_task *task)
                return;
 
        xprt = req->rq_xprt;
-       rpc_count_iostats(task);
+       if (task->tk_ops->rpc_count_stats != NULL)
+               task->tk_ops->rpc_count_stats(task, task->tk_calldata);
+       else if (task->tk_client)
+               rpc_count_iostats(task, task->tk_client->cl_metrics);
        spin_lock_bh(&xprt->transport_lock);
        xprt->ops->release_xprt(xprt, task);
        if (xprt->ops->release_request)