diff options
Diffstat (limited to 'fs/nfs/filelayout/filelayout.c')
-rw-r--r-- | fs/nfs/filelayout/filelayout.c | 315 |
1 files changed, 28 insertions, 287 deletions
diff --git a/fs/nfs/filelayout/filelayout.c b/fs/nfs/filelayout/filelayout.c index 7afb52f6a25a..3c9769441f36 100644 --- a/fs/nfs/filelayout/filelayout.c +++ b/fs/nfs/filelayout/filelayout.c | |||
@@ -118,13 +118,6 @@ static void filelayout_reset_read(struct nfs_pgio_header *hdr) | |||
118 | } | 118 | } |
119 | } | 119 | } |
120 | 120 | ||
121 | static void filelayout_fenceme(struct inode *inode, struct pnfs_layout_hdr *lo) | ||
122 | { | ||
123 | if (!test_and_clear_bit(NFS_LAYOUT_RETURN, &lo->plh_flags)) | ||
124 | return; | ||
125 | pnfs_return_layout(inode); | ||
126 | } | ||
127 | |||
128 | static int filelayout_async_handle_error(struct rpc_task *task, | 121 | static int filelayout_async_handle_error(struct rpc_task *task, |
129 | struct nfs4_state *state, | 122 | struct nfs4_state *state, |
130 | struct nfs_client *clp, | 123 | struct nfs_client *clp, |
@@ -207,7 +200,7 @@ static int filelayout_async_handle_error(struct rpc_task *task, | |||
207 | dprintk("%s DS connection error %d\n", __func__, | 200 | dprintk("%s DS connection error %d\n", __func__, |
208 | task->tk_status); | 201 | task->tk_status); |
209 | nfs4_mark_deviceid_unavailable(devid); | 202 | nfs4_mark_deviceid_unavailable(devid); |
210 | set_bit(NFS_LAYOUT_RETURN, &lo->plh_flags); | 203 | pnfs_error_mark_layout_for_return(inode, lseg); |
211 | rpc_wake_up(&tbl->slot_tbl_waitq); | 204 | rpc_wake_up(&tbl->slot_tbl_waitq); |
212 | /* fall through */ | 205 | /* fall through */ |
213 | default: | 206 | default: |
@@ -339,16 +332,6 @@ static void filelayout_read_count_stats(struct rpc_task *task, void *data) | |||
339 | rpc_count_iostats(task, NFS_SERVER(hdr->inode)->client->cl_metrics); | 332 | rpc_count_iostats(task, NFS_SERVER(hdr->inode)->client->cl_metrics); |
340 | } | 333 | } |
341 | 334 | ||
342 | static void filelayout_read_release(void *data) | ||
343 | { | ||
344 | struct nfs_pgio_header *hdr = data; | ||
345 | struct pnfs_layout_hdr *lo = hdr->lseg->pls_layout; | ||
346 | |||
347 | filelayout_fenceme(lo->plh_inode, lo); | ||
348 | nfs_put_client(hdr->ds_clp); | ||
349 | hdr->mds_ops->rpc_release(data); | ||
350 | } | ||
351 | |||
352 | static int filelayout_write_done_cb(struct rpc_task *task, | 335 | static int filelayout_write_done_cb(struct rpc_task *task, |
353 | struct nfs_pgio_header *hdr) | 336 | struct nfs_pgio_header *hdr) |
354 | { | 337 | { |
@@ -371,17 +354,6 @@ static int filelayout_write_done_cb(struct rpc_task *task, | |||
371 | return 0; | 354 | return 0; |
372 | } | 355 | } |
373 | 356 | ||
374 | /* Fake up some data that will cause nfs_commit_release to retry the writes. */ | ||
375 | static void prepare_to_resend_writes(struct nfs_commit_data *data) | ||
376 | { | ||
377 | struct nfs_page *first = nfs_list_entry(data->pages.next); | ||
378 | |||
379 | data->task.tk_status = 0; | ||
380 | memcpy(&data->verf.verifier, &first->wb_verf, | ||
381 | sizeof(data->verf.verifier)); | ||
382 | data->verf.verifier.data[0]++; /* ensure verifier mismatch */ | ||
383 | } | ||
384 | |||
385 | static int filelayout_commit_done_cb(struct rpc_task *task, | 357 | static int filelayout_commit_done_cb(struct rpc_task *task, |
386 | struct nfs_commit_data *data) | 358 | struct nfs_commit_data *data) |
387 | { | 359 | { |
@@ -393,7 +365,7 @@ static int filelayout_commit_done_cb(struct rpc_task *task, | |||
393 | 365 | ||
394 | switch (err) { | 366 | switch (err) { |
395 | case -NFS4ERR_RESET_TO_MDS: | 367 | case -NFS4ERR_RESET_TO_MDS: |
396 | prepare_to_resend_writes(data); | 368 | pnfs_generic_prepare_to_resend_writes(data); |
397 | return -EAGAIN; | 369 | return -EAGAIN; |
398 | case -EAGAIN: | 370 | case -EAGAIN: |
399 | rpc_restart_call_prepare(task); | 371 | rpc_restart_call_prepare(task); |
@@ -451,16 +423,6 @@ static void filelayout_write_count_stats(struct rpc_task *task, void *data) | |||
451 | rpc_count_iostats(task, NFS_SERVER(hdr->inode)->client->cl_metrics); | 423 | rpc_count_iostats(task, NFS_SERVER(hdr->inode)->client->cl_metrics); |
452 | } | 424 | } |
453 | 425 | ||
454 | static void filelayout_write_release(void *data) | ||
455 | { | ||
456 | struct nfs_pgio_header *hdr = data; | ||
457 | struct pnfs_layout_hdr *lo = hdr->lseg->pls_layout; | ||
458 | |||
459 | filelayout_fenceme(lo->plh_inode, lo); | ||
460 | nfs_put_client(hdr->ds_clp); | ||
461 | hdr->mds_ops->rpc_release(data); | ||
462 | } | ||
463 | |||
464 | static void filelayout_commit_prepare(struct rpc_task *task, void *data) | 426 | static void filelayout_commit_prepare(struct rpc_task *task, void *data) |
465 | { | 427 | { |
466 | struct nfs_commit_data *wdata = data; | 428 | struct nfs_commit_data *wdata = data; |
@@ -471,14 +433,6 @@ static void filelayout_commit_prepare(struct rpc_task *task, void *data) | |||
471 | task); | 433 | task); |
472 | } | 434 | } |
473 | 435 | ||
474 | static void filelayout_write_commit_done(struct rpc_task *task, void *data) | ||
475 | { | ||
476 | struct nfs_commit_data *wdata = data; | ||
477 | |||
478 | /* Note this may cause RPC to be resent */ | ||
479 | wdata->mds_ops->rpc_call_done(task, data); | ||
480 | } | ||
481 | |||
482 | static void filelayout_commit_count_stats(struct rpc_task *task, void *data) | 436 | static void filelayout_commit_count_stats(struct rpc_task *task, void *data) |
483 | { | 437 | { |
484 | struct nfs_commit_data *cdata = data; | 438 | struct nfs_commit_data *cdata = data; |
@@ -486,35 +440,25 @@ static void filelayout_commit_count_stats(struct rpc_task *task, void *data) | |||
486 | rpc_count_iostats(task, NFS_SERVER(cdata->inode)->client->cl_metrics); | 440 | rpc_count_iostats(task, NFS_SERVER(cdata->inode)->client->cl_metrics); |
487 | } | 441 | } |
488 | 442 | ||
489 | static void filelayout_commit_release(void *calldata) | ||
490 | { | ||
491 | struct nfs_commit_data *data = calldata; | ||
492 | |||
493 | data->completion_ops->completion(data); | ||
494 | pnfs_put_lseg(data->lseg); | ||
495 | nfs_put_client(data->ds_clp); | ||
496 | nfs_commitdata_release(data); | ||
497 | } | ||
498 | |||
499 | static const struct rpc_call_ops filelayout_read_call_ops = { | 443 | static const struct rpc_call_ops filelayout_read_call_ops = { |
500 | .rpc_call_prepare = filelayout_read_prepare, | 444 | .rpc_call_prepare = filelayout_read_prepare, |
501 | .rpc_call_done = filelayout_read_call_done, | 445 | .rpc_call_done = filelayout_read_call_done, |
502 | .rpc_count_stats = filelayout_read_count_stats, | 446 | .rpc_count_stats = filelayout_read_count_stats, |
503 | .rpc_release = filelayout_read_release, | 447 | .rpc_release = pnfs_generic_rw_release, |
504 | }; | 448 | }; |
505 | 449 | ||
506 | static const struct rpc_call_ops filelayout_write_call_ops = { | 450 | static const struct rpc_call_ops filelayout_write_call_ops = { |
507 | .rpc_call_prepare = filelayout_write_prepare, | 451 | .rpc_call_prepare = filelayout_write_prepare, |
508 | .rpc_call_done = filelayout_write_call_done, | 452 | .rpc_call_done = filelayout_write_call_done, |
509 | .rpc_count_stats = filelayout_write_count_stats, | 453 | .rpc_count_stats = filelayout_write_count_stats, |
510 | .rpc_release = filelayout_write_release, | 454 | .rpc_release = pnfs_generic_rw_release, |
511 | }; | 455 | }; |
512 | 456 | ||
513 | static const struct rpc_call_ops filelayout_commit_call_ops = { | 457 | static const struct rpc_call_ops filelayout_commit_call_ops = { |
514 | .rpc_call_prepare = filelayout_commit_prepare, | 458 | .rpc_call_prepare = filelayout_commit_prepare, |
515 | .rpc_call_done = filelayout_write_commit_done, | 459 | .rpc_call_done = pnfs_generic_write_commit_done, |
516 | .rpc_count_stats = filelayout_commit_count_stats, | 460 | .rpc_count_stats = filelayout_commit_count_stats, |
517 | .rpc_release = filelayout_commit_release, | 461 | .rpc_release = pnfs_generic_commit_release, |
518 | }; | 462 | }; |
519 | 463 | ||
520 | static enum pnfs_try_status | 464 | static enum pnfs_try_status |
@@ -548,7 +492,7 @@ filelayout_read_pagelist(struct nfs_pgio_header *hdr) | |||
548 | /* No multipath support. Use first DS */ | 492 | /* No multipath support. Use first DS */ |
549 | atomic_inc(&ds->ds_clp->cl_count); | 493 | atomic_inc(&ds->ds_clp->cl_count); |
550 | hdr->ds_clp = ds->ds_clp; | 494 | hdr->ds_clp = ds->ds_clp; |
551 | hdr->ds_idx = idx; | 495 | hdr->ds_commit_idx = idx; |
552 | fh = nfs4_fl_select_ds_fh(lseg, j); | 496 | fh = nfs4_fl_select_ds_fh(lseg, j); |
553 | if (fh) | 497 | if (fh) |
554 | hdr->args.fh = fh; | 498 | hdr->args.fh = fh; |
@@ -557,8 +501,9 @@ filelayout_read_pagelist(struct nfs_pgio_header *hdr) | |||
557 | hdr->mds_offset = offset; | 501 | hdr->mds_offset = offset; |
558 | 502 | ||
559 | /* Perform an asynchronous read to ds */ | 503 | /* Perform an asynchronous read to ds */ |
560 | nfs_initiate_pgio(ds_clnt, hdr, | 504 | nfs_initiate_pgio(ds_clnt, hdr, hdr->cred, |
561 | &filelayout_read_call_ops, 0, RPC_TASK_SOFTCONN); | 505 | NFS_PROTO(hdr->inode), &filelayout_read_call_ops, |
506 | 0, RPC_TASK_SOFTCONN); | ||
562 | return PNFS_ATTEMPTED; | 507 | return PNFS_ATTEMPTED; |
563 | } | 508 | } |
564 | 509 | ||
@@ -591,16 +536,16 @@ filelayout_write_pagelist(struct nfs_pgio_header *hdr, int sync) | |||
591 | hdr->pgio_done_cb = filelayout_write_done_cb; | 536 | hdr->pgio_done_cb = filelayout_write_done_cb; |
592 | atomic_inc(&ds->ds_clp->cl_count); | 537 | atomic_inc(&ds->ds_clp->cl_count); |
593 | hdr->ds_clp = ds->ds_clp; | 538 | hdr->ds_clp = ds->ds_clp; |
594 | hdr->ds_idx = idx; | 539 | hdr->ds_commit_idx = idx; |
595 | fh = nfs4_fl_select_ds_fh(lseg, j); | 540 | fh = nfs4_fl_select_ds_fh(lseg, j); |
596 | if (fh) | 541 | if (fh) |
597 | hdr->args.fh = fh; | 542 | hdr->args.fh = fh; |
598 | hdr->args.offset = filelayout_get_dserver_offset(lseg, offset); | 543 | hdr->args.offset = filelayout_get_dserver_offset(lseg, offset); |
599 | 544 | ||
600 | /* Perform an asynchronous write */ | 545 | /* Perform an asynchronous write */ |
601 | nfs_initiate_pgio(ds_clnt, hdr, | 546 | nfs_initiate_pgio(ds_clnt, hdr, hdr->cred, |
602 | &filelayout_write_call_ops, sync, | 547 | NFS_PROTO(hdr->inode), &filelayout_write_call_ops, |
603 | RPC_TASK_SOFTCONN); | 548 | sync, RPC_TASK_SOFTCONN); |
604 | return PNFS_ATTEMPTED; | 549 | return PNFS_ATTEMPTED; |
605 | } | 550 | } |
606 | 551 | ||
@@ -988,12 +933,14 @@ static const struct nfs_pageio_ops filelayout_pg_read_ops = { | |||
988 | .pg_init = filelayout_pg_init_read, | 933 | .pg_init = filelayout_pg_init_read, |
989 | .pg_test = filelayout_pg_test, | 934 | .pg_test = filelayout_pg_test, |
990 | .pg_doio = pnfs_generic_pg_readpages, | 935 | .pg_doio = pnfs_generic_pg_readpages, |
936 | .pg_cleanup = pnfs_generic_pg_cleanup, | ||
991 | }; | 937 | }; |
992 | 938 | ||
993 | static const struct nfs_pageio_ops filelayout_pg_write_ops = { | 939 | static const struct nfs_pageio_ops filelayout_pg_write_ops = { |
994 | .pg_init = filelayout_pg_init_write, | 940 | .pg_init = filelayout_pg_init_write, |
995 | .pg_test = filelayout_pg_test, | 941 | .pg_test = filelayout_pg_test, |
996 | .pg_doio = pnfs_generic_pg_writepages, | 942 | .pg_doio = pnfs_generic_pg_writepages, |
943 | .pg_cleanup = pnfs_generic_pg_cleanup, | ||
997 | }; | 944 | }; |
998 | 945 | ||
999 | static u32 select_bucket_index(struct nfs4_filelayout_segment *fl, u32 j) | 946 | static u32 select_bucket_index(struct nfs4_filelayout_segment *fl, u32 j) |
@@ -1004,37 +951,11 @@ static u32 select_bucket_index(struct nfs4_filelayout_segment *fl, u32 j) | |||
1004 | return j; | 951 | return j; |
1005 | } | 952 | } |
1006 | 953 | ||
1007 | /* The generic layer is about to remove the req from the commit list. | ||
1008 | * If this will make the bucket empty, it will need to put the lseg reference. | ||
1009 | * Note this is must be called holding the inode (/cinfo) lock | ||
1010 | */ | ||
1011 | static void | ||
1012 | filelayout_clear_request_commit(struct nfs_page *req, | ||
1013 | struct nfs_commit_info *cinfo) | ||
1014 | { | ||
1015 | struct pnfs_layout_segment *freeme = NULL; | ||
1016 | |||
1017 | if (!test_and_clear_bit(PG_COMMIT_TO_DS, &req->wb_flags)) | ||
1018 | goto out; | ||
1019 | cinfo->ds->nwritten--; | ||
1020 | if (list_is_singular(&req->wb_list)) { | ||
1021 | struct pnfs_commit_bucket *bucket; | ||
1022 | |||
1023 | bucket = list_first_entry(&req->wb_list, | ||
1024 | struct pnfs_commit_bucket, | ||
1025 | written); | ||
1026 | freeme = bucket->wlseg; | ||
1027 | bucket->wlseg = NULL; | ||
1028 | } | ||
1029 | out: | ||
1030 | nfs_request_remove_commit_list(req, cinfo); | ||
1031 | pnfs_put_lseg_locked(freeme); | ||
1032 | } | ||
1033 | |||
1034 | static void | 954 | static void |
1035 | filelayout_mark_request_commit(struct nfs_page *req, | 955 | filelayout_mark_request_commit(struct nfs_page *req, |
1036 | struct pnfs_layout_segment *lseg, | 956 | struct pnfs_layout_segment *lseg, |
1037 | struct nfs_commit_info *cinfo) | 957 | struct nfs_commit_info *cinfo, |
958 | u32 ds_commit_idx) | ||
1038 | 959 | ||
1039 | { | 960 | { |
1040 | struct nfs4_filelayout_segment *fl = FILELAYOUT_LSEG(lseg); | 961 | struct nfs4_filelayout_segment *fl = FILELAYOUT_LSEG(lseg); |
@@ -1064,7 +985,7 @@ filelayout_mark_request_commit(struct nfs_page *req, | |||
1064 | * is normally transferred to the COMMIT call and released | 985 | * is normally transferred to the COMMIT call and released |
1065 | * there. It could also be released if the last req is pulled | 986 | * there. It could also be released if the last req is pulled |
1066 | * off due to a rewrite, in which case it will be done in | 987 | * off due to a rewrite, in which case it will be done in |
1067 | * filelayout_clear_request_commit | 988 | * pnfs_generic_clear_request_commit |
1068 | */ | 989 | */ |
1069 | buckets[i].wlseg = pnfs_get_lseg(lseg); | 990 | buckets[i].wlseg = pnfs_get_lseg(lseg); |
1070 | } | 991 | } |
@@ -1138,101 +1059,15 @@ static int filelayout_initiate_commit(struct nfs_commit_data *data, int how) | |||
1138 | fh = select_ds_fh_from_commit(lseg, data->ds_commit_index); | 1059 | fh = select_ds_fh_from_commit(lseg, data->ds_commit_index); |
1139 | if (fh) | 1060 | if (fh) |
1140 | data->args.fh = fh; | 1061 | data->args.fh = fh; |
1141 | return nfs_initiate_commit(ds_clnt, data, | 1062 | return nfs_initiate_commit(ds_clnt, data, NFS_PROTO(data->inode), |
1142 | &filelayout_commit_call_ops, how, | 1063 | &filelayout_commit_call_ops, how, |
1143 | RPC_TASK_SOFTCONN); | 1064 | RPC_TASK_SOFTCONN); |
1144 | out_err: | 1065 | out_err: |
1145 | prepare_to_resend_writes(data); | 1066 | pnfs_generic_prepare_to_resend_writes(data); |
1146 | filelayout_commit_release(data); | 1067 | pnfs_generic_commit_release(data); |
1147 | return -EAGAIN; | 1068 | return -EAGAIN; |
1148 | } | 1069 | } |
1149 | 1070 | ||
1150 | static int | ||
1151 | transfer_commit_list(struct list_head *src, struct list_head *dst, | ||
1152 | struct nfs_commit_info *cinfo, int max) | ||
1153 | { | ||
1154 | struct nfs_page *req, *tmp; | ||
1155 | int ret = 0; | ||
1156 | |||
1157 | list_for_each_entry_safe(req, tmp, src, wb_list) { | ||
1158 | if (!nfs_lock_request(req)) | ||
1159 | continue; | ||
1160 | kref_get(&req->wb_kref); | ||
1161 | if (cond_resched_lock(cinfo->lock)) | ||
1162 | list_safe_reset_next(req, tmp, wb_list); | ||
1163 | nfs_request_remove_commit_list(req, cinfo); | ||
1164 | clear_bit(PG_COMMIT_TO_DS, &req->wb_flags); | ||
1165 | nfs_list_add_request(req, dst); | ||
1166 | ret++; | ||
1167 | if ((ret == max) && !cinfo->dreq) | ||
1168 | break; | ||
1169 | } | ||
1170 | return ret; | ||
1171 | } | ||
1172 | |||
1173 | /* Note called with cinfo->lock held. */ | ||
1174 | static int | ||
1175 | filelayout_scan_ds_commit_list(struct pnfs_commit_bucket *bucket, | ||
1176 | struct nfs_commit_info *cinfo, | ||
1177 | int max) | ||
1178 | { | ||
1179 | struct list_head *src = &bucket->written; | ||
1180 | struct list_head *dst = &bucket->committing; | ||
1181 | int ret; | ||
1182 | |||
1183 | ret = transfer_commit_list(src, dst, cinfo, max); | ||
1184 | if (ret) { | ||
1185 | cinfo->ds->nwritten -= ret; | ||
1186 | cinfo->ds->ncommitting += ret; | ||
1187 | bucket->clseg = bucket->wlseg; | ||
1188 | if (list_empty(src)) | ||
1189 | bucket->wlseg = NULL; | ||
1190 | else | ||
1191 | pnfs_get_lseg(bucket->clseg); | ||
1192 | } | ||
1193 | return ret; | ||
1194 | } | ||
1195 | |||
1196 | /* Move reqs from written to committing lists, returning count of number moved. | ||
1197 | * Note called with cinfo->lock held. | ||
1198 | */ | ||
1199 | static int filelayout_scan_commit_lists(struct nfs_commit_info *cinfo, | ||
1200 | int max) | ||
1201 | { | ||
1202 | int i, rv = 0, cnt; | ||
1203 | |||
1204 | for (i = 0; i < cinfo->ds->nbuckets && max != 0; i++) { | ||
1205 | cnt = filelayout_scan_ds_commit_list(&cinfo->ds->buckets[i], | ||
1206 | cinfo, max); | ||
1207 | max -= cnt; | ||
1208 | rv += cnt; | ||
1209 | } | ||
1210 | return rv; | ||
1211 | } | ||
1212 | |||
1213 | /* Pull everything off the committing lists and dump into @dst */ | ||
1214 | static void filelayout_recover_commit_reqs(struct list_head *dst, | ||
1215 | struct nfs_commit_info *cinfo) | ||
1216 | { | ||
1217 | struct pnfs_commit_bucket *b; | ||
1218 | struct pnfs_layout_segment *freeme; | ||
1219 | int i; | ||
1220 | |||
1221 | restart: | ||
1222 | spin_lock(cinfo->lock); | ||
1223 | for (i = 0, b = cinfo->ds->buckets; i < cinfo->ds->nbuckets; i++, b++) { | ||
1224 | if (transfer_commit_list(&b->written, dst, cinfo, 0)) { | ||
1225 | freeme = b->wlseg; | ||
1226 | b->wlseg = NULL; | ||
1227 | spin_unlock(cinfo->lock); | ||
1228 | pnfs_put_lseg(freeme); | ||
1229 | goto restart; | ||
1230 | } | ||
1231 | } | ||
1232 | cinfo->ds->nwritten = 0; | ||
1233 | spin_unlock(cinfo->lock); | ||
1234 | } | ||
1235 | |||
1236 | /* filelayout_search_commit_reqs - Search lists in @cinfo for the head reqest | 1071 | /* filelayout_search_commit_reqs - Search lists in @cinfo for the head reqest |
1237 | * for @page | 1072 | * for @page |
1238 | * @cinfo - commit info for current inode | 1073 | * @cinfo - commit info for current inode |
@@ -1263,108 +1098,14 @@ filelayout_search_commit_reqs(struct nfs_commit_info *cinfo, struct page *page) | |||
1263 | return NULL; | 1098 | return NULL; |
1264 | } | 1099 | } |
1265 | 1100 | ||
1266 | static void filelayout_retry_commit(struct nfs_commit_info *cinfo, int idx) | ||
1267 | { | ||
1268 | struct pnfs_ds_commit_info *fl_cinfo = cinfo->ds; | ||
1269 | struct pnfs_commit_bucket *bucket; | ||
1270 | struct pnfs_layout_segment *freeme; | ||
1271 | int i; | ||
1272 | |||
1273 | for (i = idx; i < fl_cinfo->nbuckets; i++) { | ||
1274 | bucket = &fl_cinfo->buckets[i]; | ||
1275 | if (list_empty(&bucket->committing)) | ||
1276 | continue; | ||
1277 | nfs_retry_commit(&bucket->committing, bucket->clseg, cinfo); | ||
1278 | spin_lock(cinfo->lock); | ||
1279 | freeme = bucket->clseg; | ||
1280 | bucket->clseg = NULL; | ||
1281 | spin_unlock(cinfo->lock); | ||
1282 | pnfs_put_lseg(freeme); | ||
1283 | } | ||
1284 | } | ||
1285 | |||
1286 | static unsigned int | ||
1287 | alloc_ds_commits(struct nfs_commit_info *cinfo, struct list_head *list) | ||
1288 | { | ||
1289 | struct pnfs_ds_commit_info *fl_cinfo; | ||
1290 | struct pnfs_commit_bucket *bucket; | ||
1291 | struct nfs_commit_data *data; | ||
1292 | int i; | ||
1293 | unsigned int nreq = 0; | ||
1294 | |||
1295 | fl_cinfo = cinfo->ds; | ||
1296 | bucket = fl_cinfo->buckets; | ||
1297 | for (i = 0; i < fl_cinfo->nbuckets; i++, bucket++) { | ||
1298 | if (list_empty(&bucket->committing)) | ||
1299 | continue; | ||
1300 | data = nfs_commitdata_alloc(); | ||
1301 | if (!data) | ||
1302 | break; | ||
1303 | data->ds_commit_index = i; | ||
1304 | spin_lock(cinfo->lock); | ||
1305 | data->lseg = bucket->clseg; | ||
1306 | bucket->clseg = NULL; | ||
1307 | spin_unlock(cinfo->lock); | ||
1308 | list_add(&data->pages, list); | ||
1309 | nreq++; | ||
1310 | } | ||
1311 | |||
1312 | /* Clean up on error */ | ||
1313 | filelayout_retry_commit(cinfo, i); | ||
1314 | /* Caller will clean up entries put on list */ | ||
1315 | return nreq; | ||
1316 | } | ||
1317 | |||
1318 | /* This follows nfs_commit_list pretty closely */ | ||
1319 | static int | 1101 | static int |
1320 | filelayout_commit_pagelist(struct inode *inode, struct list_head *mds_pages, | 1102 | filelayout_commit_pagelist(struct inode *inode, struct list_head *mds_pages, |
1321 | int how, struct nfs_commit_info *cinfo) | 1103 | int how, struct nfs_commit_info *cinfo) |
1322 | { | 1104 | { |
1323 | struct nfs_commit_data *data, *tmp; | 1105 | return pnfs_generic_commit_pagelist(inode, mds_pages, how, cinfo, |
1324 | LIST_HEAD(list); | 1106 | filelayout_initiate_commit); |
1325 | unsigned int nreq = 0; | ||
1326 | |||
1327 | if (!list_empty(mds_pages)) { | ||
1328 | data = nfs_commitdata_alloc(); | ||
1329 | if (data != NULL) { | ||
1330 | data->lseg = NULL; | ||
1331 | list_add(&data->pages, &list); | ||
1332 | nreq++; | ||
1333 | } else { | ||
1334 | nfs_retry_commit(mds_pages, NULL, cinfo); | ||
1335 | filelayout_retry_commit(cinfo, 0); | ||
1336 | cinfo->completion_ops->error_cleanup(NFS_I(inode)); | ||
1337 | return -ENOMEM; | ||
1338 | } | ||
1339 | } | ||
1340 | |||
1341 | nreq += alloc_ds_commits(cinfo, &list); | ||
1342 | |||
1343 | if (nreq == 0) { | ||
1344 | cinfo->completion_ops->error_cleanup(NFS_I(inode)); | ||
1345 | goto out; | ||
1346 | } | ||
1347 | |||
1348 | atomic_add(nreq, &cinfo->mds->rpcs_out); | ||
1349 | |||
1350 | list_for_each_entry_safe(data, tmp, &list, pages) { | ||
1351 | list_del_init(&data->pages); | ||
1352 | if (!data->lseg) { | ||
1353 | nfs_init_commit(data, mds_pages, NULL, cinfo); | ||
1354 | nfs_initiate_commit(NFS_CLIENT(inode), data, | ||
1355 | data->mds_ops, how, 0); | ||
1356 | } else { | ||
1357 | struct pnfs_commit_bucket *buckets; | ||
1358 | |||
1359 | buckets = cinfo->ds->buckets; | ||
1360 | nfs_init_commit(data, &buckets[data->ds_commit_index].committing, data->lseg, cinfo); | ||
1361 | filelayout_initiate_commit(data, how); | ||
1362 | } | ||
1363 | } | ||
1364 | out: | ||
1365 | cinfo->ds->ncommitting = 0; | ||
1366 | return PNFS_ATTEMPTED; | ||
1367 | } | 1107 | } |
1108 | |||
1368 | static struct nfs4_deviceid_node * | 1109 | static struct nfs4_deviceid_node * |
1369 | filelayout_alloc_deviceid_node(struct nfs_server *server, | 1110 | filelayout_alloc_deviceid_node(struct nfs_server *server, |
1370 | struct pnfs_device *pdev, gfp_t gfp_flags) | 1111 | struct pnfs_device *pdev, gfp_t gfp_flags) |
@@ -1421,9 +1162,9 @@ static struct pnfs_layoutdriver_type filelayout_type = { | |||
1421 | .pg_write_ops = &filelayout_pg_write_ops, | 1162 | .pg_write_ops = &filelayout_pg_write_ops, |
1422 | .get_ds_info = &filelayout_get_ds_info, | 1163 | .get_ds_info = &filelayout_get_ds_info, |
1423 | .mark_request_commit = filelayout_mark_request_commit, | 1164 | .mark_request_commit = filelayout_mark_request_commit, |
1424 | .clear_request_commit = filelayout_clear_request_commit, | 1165 | .clear_request_commit = pnfs_generic_clear_request_commit, |
1425 | .scan_commit_lists = filelayout_scan_commit_lists, | 1166 | .scan_commit_lists = pnfs_generic_scan_commit_lists, |
1426 | .recover_commit_reqs = filelayout_recover_commit_reqs, | 1167 | .recover_commit_reqs = pnfs_generic_recover_commit_reqs, |
1427 | .search_commit_reqs = filelayout_search_commit_reqs, | 1168 | .search_commit_reqs = filelayout_search_commit_reqs, |
1428 | .commit_pagelist = filelayout_commit_pagelist, | 1169 | .commit_pagelist = filelayout_commit_pagelist, |
1429 | .read_pagelist = filelayout_read_pagelist, | 1170 | .read_pagelist = filelayout_read_pagelist, |