Merge tag 'stable/for-linus-3.19-rc0b-tag' of git://git.kernel.org/pub/scm/linux...
[cascardo/linux.git] / net / sunrpc / stats.c
index 5453049..9711a15 100644 (file)
@@ -116,7 +116,15 @@ EXPORT_SYMBOL_GPL(svc_seq_show);
  */
 struct rpc_iostats *rpc_alloc_iostats(struct rpc_clnt *clnt)
 {
-       return kcalloc(clnt->cl_maxproc, sizeof(struct rpc_iostats), GFP_KERNEL);
+       struct rpc_iostats *stats;
+       int i;
+
+       stats = kcalloc(clnt->cl_maxproc, sizeof(*stats), GFP_KERNEL);
+       if (stats) {
+               for (i = 0; i < clnt->cl_maxproc; i++)
+                       spin_lock_init(&stats[i].om_lock);
+       }
+       return stats;
 }
 EXPORT_SYMBOL_GPL(rpc_alloc_iostats);
 
@@ -135,20 +143,21 @@ 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(const struct rpc_task *task, struct rpc_iostats *stats)
 {
        struct rpc_rqst *req = task->tk_rqstp;
        struct rpc_iostats *op_metrics;
-       ktime_t delta;
+       ktime_t delta, now;
 
        if (!stats || !req)
                return;
 
+       now = ktime_get();
        op_metrics = &stats[task->tk_msg.rpc_proc->p_statidx];
 
+       spin_lock(&op_metrics->om_lock);
+
        op_metrics->om_ops++;
        op_metrics->om_ntrans += req->rq_ntrans;
        op_metrics->om_timeouts += task->tk_timeouts;
@@ -161,8 +170,10 @@ void rpc_count_iostats(const struct rpc_task *task, struct rpc_iostats *stats)
 
        op_metrics->om_rtt = ktime_add(op_metrics->om_rtt, req->rq_rtt);
 
-       delta = ktime_sub(ktime_get(), task->tk_start);
+       delta = ktime_sub(now, task->tk_start);
        op_metrics->om_execute = ktime_add(op_metrics->om_execute, delta);
+
+       spin_unlock(&op_metrics->om_lock);
 }
 EXPORT_SYMBOL_GPL(rpc_count_iostats);