aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@primarydata.com>2015-06-23 07:51:59 -0400
committerTrond Myklebust <trond.myklebust@primarydata.com>2015-06-24 10:53:10 -0400
commitabcb7bfc9fdecd1550b98a5e13d40bfba6c0649b (patch)
treedd654d03298b6c51fabb6d3cba42ff608512ab55
parent27797d1bb36bf9e21fa14094f23ab785b442bd76 (diff)
pNFS/flexfiles: add layoutstats tracking
Reviewed-by: Jeff Layton <jeff.layton@primarydata.com> Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
-rw-r--r--fs/nfs/flexfilelayout/flexfilelayout.c192
-rw-r--r--fs/nfs/flexfilelayout/flexfilelayout.h22
2 files changed, 203 insertions, 11 deletions
diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c
index 0f1410c94827..8ac31fbf040a 100644
--- a/fs/nfs/flexfilelayout/flexfilelayout.c
+++ b/fs/nfs/flexfilelayout/flexfilelayout.c
@@ -412,6 +412,130 @@ ff_layout_get_lseg_count(struct nfs4_ff_layout_segment *fls)
412 return 1; 412 return 1;
413} 413}
414 414
415static void
416nfs4_ff_start_busy_timer(struct nfs4_ff_busy_timer *timer)
417{
418 ktime_t old, new;
419
420 /*
421 * Note: careful here!
422 * If the counter is zero, then we must not increment it until after
423 * we've set the start_time.
424 * If we were instead to use atomic_inc_return(), then another
425 * request might come in, bump, and then call end_busy_timer()
426 * before we've set the timer->start_time.
427 */
428 old = timer->start_time;
429 if (atomic_inc_not_zero(&timer->n_ops) == 0) {
430 new = ktime_get();
431 cmpxchg(&timer->start_time.tv64, old.tv64, new.tv64);
432 atomic_inc(&timer->n_ops);
433 }
434}
435
436static ktime_t
437nfs4_ff_end_busy_timer(struct nfs4_ff_busy_timer *timer)
438{
439 ktime_t start, now;
440
441 now = ktime_get();
442 start.tv64 = xchg(&timer->start_time.tv64, now.tv64);
443 atomic_dec(&timer->n_ops);
444 return ktime_sub(now, start);
445}
446
447static ktime_t
448nfs4_ff_layout_calc_completion_time(struct rpc_task *task)
449{
450 return ktime_sub(ktime_get(), task->tk_start);
451}
452
453static void
454nfs4_ff_layoutstat_start_io(struct nfs4_ff_layoutstat *layoutstat)
455{
456 nfs4_ff_start_busy_timer(&layoutstat->busy_timer);
457}
458
459static void
460nfs4_ff_layout_stat_io_update_requested(struct nfs4_ff_layoutstat *layoutstat,
461 __u64 requested)
462{
463 struct nfs4_ff_io_stat *iostat = &layoutstat->io_stat;
464
465 iostat->ops_requested++;
466 iostat->bytes_requested += requested;
467}
468
469static void
470nfs4_ff_layout_stat_io_update_completed(struct nfs4_ff_layoutstat *layoutstat,
471 __u64 requested,
472 __u64 completed,
473 ktime_t time_completed)
474{
475 struct nfs4_ff_io_stat *iostat = &layoutstat->io_stat;
476 ktime_t timer;
477
478 iostat->ops_completed++;
479 iostat->bytes_completed += completed;
480 iostat->bytes_not_delivered += requested - completed;
481
482 timer = nfs4_ff_end_busy_timer(&layoutstat->busy_timer);
483 iostat->total_busy_time =
484 ktime_add(iostat->total_busy_time, timer);
485 iostat->aggregate_completion_time =
486 ktime_add(iostat->aggregate_completion_time, time_completed);
487}
488
489static void
490nfs4_ff_layout_stat_io_start_read(struct nfs4_ff_layout_mirror *mirror,
491 __u64 requested)
492{
493 spin_lock(&mirror->lock);
494 nfs4_ff_layoutstat_start_io(&mirror->read_stat);
495 nfs4_ff_layout_stat_io_update_requested(&mirror->read_stat, requested);
496 spin_unlock(&mirror->lock);
497}
498
499static void
500nfs4_ff_layout_stat_io_end_read(struct rpc_task *task,
501 struct nfs4_ff_layout_mirror *mirror,
502 __u64 requested,
503 __u64 completed)
504{
505 spin_lock(&mirror->lock);
506 nfs4_ff_layout_stat_io_update_completed(&mirror->read_stat,
507 requested, completed,
508 nfs4_ff_layout_calc_completion_time(task));
509 spin_unlock(&mirror->lock);
510}
511
512static void
513nfs4_ff_layout_stat_io_start_write(struct nfs4_ff_layout_mirror *mirror,
514 __u64 requested)
515{
516 spin_lock(&mirror->lock);
517 nfs4_ff_layoutstat_start_io(&mirror->write_stat);
518 nfs4_ff_layout_stat_io_update_requested(&mirror->write_stat, requested);
519 spin_unlock(&mirror->lock);
520}
521
522static void
523nfs4_ff_layout_stat_io_end_write(struct rpc_task *task,
524 struct nfs4_ff_layout_mirror *mirror,
525 __u64 requested,
526 __u64 completed,
527 enum nfs3_stable_how committed)
528{
529 if (committed == NFS_UNSTABLE)
530 requested = completed = 0;
531
532 spin_lock(&mirror->lock);
533 nfs4_ff_layout_stat_io_update_completed(&mirror->write_stat,
534 requested, completed,
535 nfs4_ff_layout_calc_completion_time(task));
536 spin_unlock(&mirror->lock);
537}
538
415static int 539static int
416ff_layout_alloc_commit_info(struct pnfs_layout_segment *lseg, 540ff_layout_alloc_commit_info(struct pnfs_layout_segment *lseg,
417 struct nfs_commit_info *cinfo, 541 struct nfs_commit_info *cinfo,
@@ -906,6 +1030,10 @@ ff_layout_reset_to_mds(struct pnfs_layout_segment *lseg, int idx)
906static int ff_layout_read_prepare_common(struct rpc_task *task, 1030static int ff_layout_read_prepare_common(struct rpc_task *task,
907 struct nfs_pgio_header *hdr) 1031 struct nfs_pgio_header *hdr)
908{ 1032{
1033 nfs4_ff_layout_stat_io_start_read(
1034 FF_LAYOUT_COMP(hdr->lseg, hdr->pgio_mirror_idx),
1035 hdr->args.count);
1036
909 if (unlikely(test_bit(NFS_CONTEXT_BAD, &hdr->args.context->flags))) { 1037 if (unlikely(test_bit(NFS_CONTEXT_BAD, &hdr->args.context->flags))) {
910 rpc_exit(task, -EIO); 1038 rpc_exit(task, -EIO);
911 return -EIO; 1039 return -EIO;
@@ -959,15 +1087,15 @@ static void ff_layout_read_prepare_v4(struct rpc_task *task, void *data)
959{ 1087{
960 struct nfs_pgio_header *hdr = data; 1088 struct nfs_pgio_header *hdr = data;
961 1089
962 if (ff_layout_read_prepare_common(task, hdr))
963 return;
964
965 if (ff_layout_setup_sequence(hdr->ds_clp, 1090 if (ff_layout_setup_sequence(hdr->ds_clp,
966 &hdr->args.seq_args, 1091 &hdr->args.seq_args,
967 &hdr->res.seq_res, 1092 &hdr->res.seq_res,
968 task)) 1093 task))
969 return; 1094 return;
970 1095
1096 if (ff_layout_read_prepare_common(task, hdr))
1097 return;
1098
971 if (nfs4_set_rw_stateid(&hdr->args.stateid, hdr->args.context, 1099 if (nfs4_set_rw_stateid(&hdr->args.stateid, hdr->args.context,
972 hdr->args.lock_context, FMODE_READ) == -EIO) 1100 hdr->args.lock_context, FMODE_READ) == -EIO)
973 rpc_exit(task, -EIO); /* lost lock, terminate I/O */ 1101 rpc_exit(task, -EIO); /* lost lock, terminate I/O */
@@ -979,6 +1107,10 @@ static void ff_layout_read_call_done(struct rpc_task *task, void *data)
979 1107
980 dprintk("--> %s task->tk_status %d\n", __func__, task->tk_status); 1108 dprintk("--> %s task->tk_status %d\n", __func__, task->tk_status);
981 1109
1110 nfs4_ff_layout_stat_io_end_read(task,
1111 FF_LAYOUT_COMP(hdr->lseg, hdr->pgio_mirror_idx),
1112 hdr->args.count, hdr->res.count);
1113
982 if (test_bit(NFS_IOHDR_REDO, &hdr->flags) && 1114 if (test_bit(NFS_IOHDR_REDO, &hdr->flags) &&
983 task->tk_status == 0) { 1115 task->tk_status == 0) {
984 nfs4_sequence_done(task, &hdr->res.seq_res); 1116 nfs4_sequence_done(task, &hdr->res.seq_res);
@@ -1080,6 +1212,10 @@ static int ff_layout_commit_done_cb(struct rpc_task *task,
1080static int ff_layout_write_prepare_common(struct rpc_task *task, 1212static int ff_layout_write_prepare_common(struct rpc_task *task,
1081 struct nfs_pgio_header *hdr) 1213 struct nfs_pgio_header *hdr)
1082{ 1214{
1215 nfs4_ff_layout_stat_io_start_write(
1216 FF_LAYOUT_COMP(hdr->lseg, hdr->pgio_mirror_idx),
1217 hdr->args.count);
1218
1083 if (unlikely(test_bit(NFS_CONTEXT_BAD, &hdr->args.context->flags))) { 1219 if (unlikely(test_bit(NFS_CONTEXT_BAD, &hdr->args.context->flags))) {
1084 rpc_exit(task, -EIO); 1220 rpc_exit(task, -EIO);
1085 return -EIO; 1221 return -EIO;
@@ -1113,15 +1249,15 @@ static void ff_layout_write_prepare_v4(struct rpc_task *task, void *data)
1113{ 1249{
1114 struct nfs_pgio_header *hdr = data; 1250 struct nfs_pgio_header *hdr = data;
1115 1251
1116 if (ff_layout_write_prepare_common(task, hdr))
1117 return;
1118
1119 if (ff_layout_setup_sequence(hdr->ds_clp, 1252 if (ff_layout_setup_sequence(hdr->ds_clp,
1120 &hdr->args.seq_args, 1253 &hdr->args.seq_args,
1121 &hdr->res.seq_res, 1254 &hdr->res.seq_res,
1122 task)) 1255 task))
1123 return; 1256 return;
1124 1257
1258 if (ff_layout_write_prepare_common(task, hdr))
1259 return;
1260
1125 if (nfs4_set_rw_stateid(&hdr->args.stateid, hdr->args.context, 1261 if (nfs4_set_rw_stateid(&hdr->args.stateid, hdr->args.context,
1126 hdr->args.lock_context, FMODE_WRITE) == -EIO) 1262 hdr->args.lock_context, FMODE_WRITE) == -EIO)
1127 rpc_exit(task, -EIO); /* lost lock, terminate I/O */ 1263 rpc_exit(task, -EIO); /* lost lock, terminate I/O */
@@ -1131,6 +1267,11 @@ static void ff_layout_write_call_done(struct rpc_task *task, void *data)
1131{ 1267{
1132 struct nfs_pgio_header *hdr = data; 1268 struct nfs_pgio_header *hdr = data;
1133 1269
1270 nfs4_ff_layout_stat_io_end_write(task,
1271 FF_LAYOUT_COMP(hdr->lseg, hdr->pgio_mirror_idx),
1272 hdr->args.count, hdr->res.count,
1273 hdr->res.verf->committed);
1274
1134 if (test_bit(NFS_IOHDR_REDO, &hdr->flags) && 1275 if (test_bit(NFS_IOHDR_REDO, &hdr->flags) &&
1135 task->tk_status == 0) { 1276 task->tk_status == 0) {
1136 nfs4_sequence_done(task, &hdr->res.seq_res); 1277 nfs4_sequence_done(task, &hdr->res.seq_res);
@@ -1149,8 +1290,17 @@ static void ff_layout_write_count_stats(struct rpc_task *task, void *data)
1149 &NFS_CLIENT(hdr->inode)->cl_metrics[NFSPROC4_CLNT_WRITE]); 1290 &NFS_CLIENT(hdr->inode)->cl_metrics[NFSPROC4_CLNT_WRITE]);
1150} 1291}
1151 1292
1293static void ff_layout_commit_prepare_common(struct rpc_task *task,
1294 struct nfs_commit_data *cdata)
1295{
1296 nfs4_ff_layout_stat_io_start_write(
1297 FF_LAYOUT_COMP(cdata->lseg, cdata->ds_commit_index),
1298 0);
1299}
1300
1152static void ff_layout_commit_prepare_v3(struct rpc_task *task, void *data) 1301static void ff_layout_commit_prepare_v3(struct rpc_task *task, void *data)
1153{ 1302{
1303 ff_layout_commit_prepare_common(task, data);
1154 rpc_call_start(task); 1304 rpc_call_start(task);
1155} 1305}
1156 1306
@@ -1158,10 +1308,30 @@ static void ff_layout_commit_prepare_v4(struct rpc_task *task, void *data)
1158{ 1308{
1159 struct nfs_commit_data *wdata = data; 1309 struct nfs_commit_data *wdata = data;
1160 1310
1161 ff_layout_setup_sequence(wdata->ds_clp, 1311 if (ff_layout_setup_sequence(wdata->ds_clp,
1162 &wdata->args.seq_args, 1312 &wdata->args.seq_args,
1163 &wdata->res.seq_res, 1313 &wdata->res.seq_res,
1164 task); 1314 task))
1315 return;
1316 ff_layout_commit_prepare_common(task, data);
1317}
1318
1319static void ff_layout_commit_done(struct rpc_task *task, void *data)
1320{
1321 struct nfs_commit_data *cdata = data;
1322 struct nfs_page *req;
1323 __u64 count = 0;
1324
1325 if (task->tk_status == 0) {
1326 list_for_each_entry(req, &cdata->pages, wb_list)
1327 count += req->wb_bytes;
1328 }
1329
1330 nfs4_ff_layout_stat_io_end_write(task,
1331 FF_LAYOUT_COMP(cdata->lseg, cdata->ds_commit_index),
1332 count, count, NFS_FILE_SYNC);
1333
1334 pnfs_generic_write_commit_done(task, data);
1165} 1335}
1166 1336
1167static void ff_layout_commit_count_stats(struct rpc_task *task, void *data) 1337static void ff_layout_commit_count_stats(struct rpc_task *task, void *data)
@@ -1202,14 +1372,14 @@ static const struct rpc_call_ops ff_layout_write_call_ops_v4 = {
1202 1372
1203static const struct rpc_call_ops ff_layout_commit_call_ops_v3 = { 1373static const struct rpc_call_ops ff_layout_commit_call_ops_v3 = {
1204 .rpc_call_prepare = ff_layout_commit_prepare_v3, 1374 .rpc_call_prepare = ff_layout_commit_prepare_v3,
1205 .rpc_call_done = pnfs_generic_write_commit_done, 1375 .rpc_call_done = ff_layout_commit_done,
1206 .rpc_count_stats = ff_layout_commit_count_stats, 1376 .rpc_count_stats = ff_layout_commit_count_stats,
1207 .rpc_release = pnfs_generic_commit_release, 1377 .rpc_release = pnfs_generic_commit_release,
1208}; 1378};
1209 1379
1210static const struct rpc_call_ops ff_layout_commit_call_ops_v4 = { 1380static const struct rpc_call_ops ff_layout_commit_call_ops_v4 = {
1211 .rpc_call_prepare = ff_layout_commit_prepare_v4, 1381 .rpc_call_prepare = ff_layout_commit_prepare_v4,
1212 .rpc_call_done = pnfs_generic_write_commit_done, 1382 .rpc_call_done = ff_layout_commit_done,
1213 .rpc_count_stats = ff_layout_commit_count_stats, 1383 .rpc_count_stats = ff_layout_commit_count_stats,
1214 .rpc_release = pnfs_generic_commit_release, 1384 .rpc_release = pnfs_generic_commit_release,
1215}; 1385};
@@ -1253,7 +1423,6 @@ ff_layout_read_pagelist(struct nfs_pgio_header *hdr)
1253 fh = nfs4_ff_layout_select_ds_fh(lseg, idx); 1423 fh = nfs4_ff_layout_select_ds_fh(lseg, idx);
1254 if (fh) 1424 if (fh)
1255 hdr->args.fh = fh; 1425 hdr->args.fh = fh;
1256
1257 /* 1426 /*
1258 * Note that if we ever decide to split across DSes, 1427 * Note that if we ever decide to split across DSes,
1259 * then we may need to handle dense-like offsets. 1428 * then we may need to handle dense-like offsets.
@@ -1382,6 +1551,7 @@ static int ff_layout_initiate_commit(struct nfs_commit_data *data, int how)
1382 fh = select_ds_fh_from_commit(lseg, data->ds_commit_index); 1551 fh = select_ds_fh_from_commit(lseg, data->ds_commit_index);
1383 if (fh) 1552 if (fh)
1384 data->args.fh = fh; 1553 data->args.fh = fh;
1554
1385 return nfs_initiate_commit(ds_clnt, data, ds->ds_clp->rpc_ops, 1555 return nfs_initiate_commit(ds_clnt, data, ds->ds_clp->rpc_ops,
1386 vers == 3 ? &ff_layout_commit_call_ops_v3 : 1556 vers == 3 ? &ff_layout_commit_call_ops_v3 :
1387 &ff_layout_commit_call_ops_v4, 1557 &ff_layout_commit_call_ops_v4,
diff --git a/fs/nfs/flexfilelayout/flexfilelayout.h b/fs/nfs/flexfilelayout/flexfilelayout.h
index 275e4b735247..f7493f7cf13c 100644
--- a/fs/nfs/flexfilelayout/flexfilelayout.h
+++ b/fs/nfs/flexfilelayout/flexfilelayout.h
@@ -41,6 +41,26 @@ struct nfs4_ff_layout_ds_err {
41 struct nfs4_deviceid deviceid; 41 struct nfs4_deviceid deviceid;
42}; 42};
43 43
44struct nfs4_ff_io_stat {
45 __u64 ops_requested;
46 __u64 bytes_requested;
47 __u64 ops_completed;
48 __u64 bytes_completed;
49 __u64 bytes_not_delivered;
50 ktime_t total_busy_time;
51 ktime_t aggregate_completion_time;
52};
53
54struct nfs4_ff_busy_timer {
55 ktime_t start_time;
56 atomic_t n_ops;
57};
58
59struct nfs4_ff_layoutstat {
60 struct nfs4_ff_io_stat io_stat;
61 struct nfs4_ff_busy_timer busy_timer;
62};
63
44struct nfs4_ff_layout_mirror { 64struct nfs4_ff_layout_mirror {
45 u32 ds_count; 65 u32 ds_count;
46 u32 efficiency; 66 u32 efficiency;
@@ -52,6 +72,8 @@ struct nfs4_ff_layout_mirror {
52 u32 gid; 72 u32 gid;
53 struct rpc_cred *cred; 73 struct rpc_cred *cred;
54 spinlock_t lock; 74 spinlock_t lock;
75 struct nfs4_ff_layoutstat read_stat;
76 struct nfs4_ff_layoutstat write_stat;
55}; 77};
56 78
57struct nfs4_ff_layout_segment { 79struct nfs4_ff_layout_segment {