diff options
| author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2014-09-11 08:46:53 -0400 |
|---|---|---|
| committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2014-09-11 08:46:53 -0400 |
| commit | 336879b1da97fffc097f77c6d6f818660f2826f0 (patch) | |
| tree | 4ddb4d1c5d2b67fb096c72e41d2a03b01a605041 /fs/nfs/filelayout | |
| parent | 3d3cbd84300e7be1e53083cac0f6f9c12978ecb4 (diff) | |
| parent | fdcaa1dbb7c6ed419b10fb8cdb5001ab0a00538f (diff) | |
Merge remote-tracking branch 'airlied/drm-next' into topic/vblank-rework
Dave asked me to do the backmerge before sending him the revised pull
request, so here we go. Nothing fancy in the conflicts, just a few
things changed right next to each another.
Conflicts:
drivers/gpu/drm/drm_irq.c
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
Diffstat (limited to 'fs/nfs/filelayout')
| -rw-r--r-- | fs/nfs/filelayout/filelayout.c | 298 | ||||
| -rw-r--r-- | fs/nfs/filelayout/filelayoutdev.c | 6 |
2 files changed, 170 insertions, 134 deletions
diff --git a/fs/nfs/filelayout/filelayout.c b/fs/nfs/filelayout/filelayout.c index d2eba1c13b7e..1359c4a27393 100644 --- a/fs/nfs/filelayout/filelayout.c +++ b/fs/nfs/filelayout/filelayout.c | |||
| @@ -84,45 +84,37 @@ filelayout_get_dserver_offset(struct pnfs_layout_segment *lseg, loff_t offset) | |||
| 84 | BUG(); | 84 | BUG(); |
| 85 | } | 85 | } |
| 86 | 86 | ||
| 87 | static void filelayout_reset_write(struct nfs_pgio_data *data) | 87 | static void filelayout_reset_write(struct nfs_pgio_header *hdr) |
| 88 | { | 88 | { |
| 89 | struct nfs_pgio_header *hdr = data->header; | 89 | struct rpc_task *task = &hdr->task; |
| 90 | struct rpc_task *task = &data->task; | ||
| 91 | 90 | ||
| 92 | if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags)) { | 91 | if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags)) { |
| 93 | dprintk("%s Reset task %5u for i/o through MDS " | 92 | dprintk("%s Reset task %5u for i/o through MDS " |
| 94 | "(req %s/%llu, %u bytes @ offset %llu)\n", __func__, | 93 | "(req %s/%llu, %u bytes @ offset %llu)\n", __func__, |
| 95 | data->task.tk_pid, | 94 | hdr->task.tk_pid, |
| 96 | hdr->inode->i_sb->s_id, | 95 | hdr->inode->i_sb->s_id, |
| 97 | (unsigned long long)NFS_FILEID(hdr->inode), | 96 | (unsigned long long)NFS_FILEID(hdr->inode), |
| 98 | data->args.count, | 97 | hdr->args.count, |
| 99 | (unsigned long long)data->args.offset); | 98 | (unsigned long long)hdr->args.offset); |
| 100 | 99 | ||
| 101 | task->tk_status = pnfs_write_done_resend_to_mds(hdr->inode, | 100 | task->tk_status = pnfs_write_done_resend_to_mds(hdr); |
| 102 | &hdr->pages, | ||
| 103 | hdr->completion_ops, | ||
| 104 | hdr->dreq); | ||
| 105 | } | 101 | } |
| 106 | } | 102 | } |
| 107 | 103 | ||
| 108 | static void filelayout_reset_read(struct nfs_pgio_data *data) | 104 | static void filelayout_reset_read(struct nfs_pgio_header *hdr) |
| 109 | { | 105 | { |
| 110 | struct nfs_pgio_header *hdr = data->header; | 106 | struct rpc_task *task = &hdr->task; |
| 111 | struct rpc_task *task = &data->task; | ||
| 112 | 107 | ||
| 113 | if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags)) { | 108 | if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags)) { |
| 114 | dprintk("%s Reset task %5u for i/o through MDS " | 109 | dprintk("%s Reset task %5u for i/o through MDS " |
| 115 | "(req %s/%llu, %u bytes @ offset %llu)\n", __func__, | 110 | "(req %s/%llu, %u bytes @ offset %llu)\n", __func__, |
| 116 | data->task.tk_pid, | 111 | hdr->task.tk_pid, |
| 117 | hdr->inode->i_sb->s_id, | 112 | hdr->inode->i_sb->s_id, |
| 118 | (unsigned long long)NFS_FILEID(hdr->inode), | 113 | (unsigned long long)NFS_FILEID(hdr->inode), |
| 119 | data->args.count, | 114 | hdr->args.count, |
| 120 | (unsigned long long)data->args.offset); | 115 | (unsigned long long)hdr->args.offset); |
| 121 | 116 | ||
| 122 | task->tk_status = pnfs_read_done_resend_to_mds(hdr->inode, | 117 | task->tk_status = pnfs_read_done_resend_to_mds(hdr); |
| 123 | &hdr->pages, | ||
| 124 | hdr->completion_ops, | ||
| 125 | hdr->dreq); | ||
| 126 | } | 118 | } |
| 127 | } | 119 | } |
| 128 | 120 | ||
| @@ -243,18 +235,17 @@ wait_on_recovery: | |||
| 243 | /* NFS_PROTO call done callback routines */ | 235 | /* NFS_PROTO call done callback routines */ |
| 244 | 236 | ||
| 245 | static int filelayout_read_done_cb(struct rpc_task *task, | 237 | static int filelayout_read_done_cb(struct rpc_task *task, |
| 246 | struct nfs_pgio_data *data) | 238 | struct nfs_pgio_header *hdr) |
| 247 | { | 239 | { |
| 248 | struct nfs_pgio_header *hdr = data->header; | ||
| 249 | int err; | 240 | int err; |
| 250 | 241 | ||
| 251 | trace_nfs4_pnfs_read(data, task->tk_status); | 242 | trace_nfs4_pnfs_read(hdr, task->tk_status); |
| 252 | err = filelayout_async_handle_error(task, data->args.context->state, | 243 | err = filelayout_async_handle_error(task, hdr->args.context->state, |
| 253 | data->ds_clp, hdr->lseg); | 244 | hdr->ds_clp, hdr->lseg); |
| 254 | 245 | ||
| 255 | switch (err) { | 246 | switch (err) { |
| 256 | case -NFS4ERR_RESET_TO_MDS: | 247 | case -NFS4ERR_RESET_TO_MDS: |
| 257 | filelayout_reset_read(data); | 248 | filelayout_reset_read(hdr); |
| 258 | return task->tk_status; | 249 | return task->tk_status; |
| 259 | case -EAGAIN: | 250 | case -EAGAIN: |
| 260 | rpc_restart_call_prepare(task); | 251 | rpc_restart_call_prepare(task); |
| @@ -270,15 +261,14 @@ static int filelayout_read_done_cb(struct rpc_task *task, | |||
| 270 | * rfc5661 is not clear about which credential should be used. | 261 | * rfc5661 is not clear about which credential should be used. |
| 271 | */ | 262 | */ |
| 272 | static void | 263 | static void |
| 273 | filelayout_set_layoutcommit(struct nfs_pgio_data *wdata) | 264 | filelayout_set_layoutcommit(struct nfs_pgio_header *hdr) |
| 274 | { | 265 | { |
| 275 | struct nfs_pgio_header *hdr = wdata->header; | ||
| 276 | 266 | ||
| 277 | if (FILELAYOUT_LSEG(hdr->lseg)->commit_through_mds || | 267 | if (FILELAYOUT_LSEG(hdr->lseg)->commit_through_mds || |
| 278 | wdata->res.verf->committed == NFS_FILE_SYNC) | 268 | hdr->res.verf->committed == NFS_FILE_SYNC) |
| 279 | return; | 269 | return; |
| 280 | 270 | ||
| 281 | pnfs_set_layoutcommit(wdata); | 271 | pnfs_set_layoutcommit(hdr); |
| 282 | dprintk("%s inode %lu pls_end_pos %lu\n", __func__, hdr->inode->i_ino, | 272 | dprintk("%s inode %lu pls_end_pos %lu\n", __func__, hdr->inode->i_ino, |
| 283 | (unsigned long) NFS_I(hdr->inode)->layout->plh_lwb); | 273 | (unsigned long) NFS_I(hdr->inode)->layout->plh_lwb); |
| 284 | } | 274 | } |
| @@ -305,83 +295,82 @@ filelayout_reset_to_mds(struct pnfs_layout_segment *lseg) | |||
| 305 | */ | 295 | */ |
| 306 | static void filelayout_read_prepare(struct rpc_task *task, void *data) | 296 | static void filelayout_read_prepare(struct rpc_task *task, void *data) |
| 307 | { | 297 | { |
| 308 | struct nfs_pgio_data *rdata = data; | 298 | struct nfs_pgio_header *hdr = data; |
| 309 | 299 | ||
| 310 | if (unlikely(test_bit(NFS_CONTEXT_BAD, &rdata->args.context->flags))) { | 300 | if (unlikely(test_bit(NFS_CONTEXT_BAD, &hdr->args.context->flags))) { |
| 311 | rpc_exit(task, -EIO); | 301 | rpc_exit(task, -EIO); |
| 312 | return; | 302 | return; |
| 313 | } | 303 | } |
| 314 | if (filelayout_reset_to_mds(rdata->header->lseg)) { | 304 | if (filelayout_reset_to_mds(hdr->lseg)) { |
| 315 | dprintk("%s task %u reset io to MDS\n", __func__, task->tk_pid); | 305 | dprintk("%s task %u reset io to MDS\n", __func__, task->tk_pid); |
| 316 | filelayout_reset_read(rdata); | 306 | filelayout_reset_read(hdr); |
| 317 | rpc_exit(task, 0); | 307 | rpc_exit(task, 0); |
| 318 | return; | 308 | return; |
| 319 | } | 309 | } |
| 320 | rdata->pgio_done_cb = filelayout_read_done_cb; | 310 | hdr->pgio_done_cb = filelayout_read_done_cb; |
| 321 | 311 | ||
| 322 | if (nfs41_setup_sequence(rdata->ds_clp->cl_session, | 312 | if (nfs41_setup_sequence(hdr->ds_clp->cl_session, |
| 323 | &rdata->args.seq_args, | 313 | &hdr->args.seq_args, |
| 324 | &rdata->res.seq_res, | 314 | &hdr->res.seq_res, |
| 325 | task)) | 315 | task)) |
| 326 | return; | 316 | return; |
| 327 | if (nfs4_set_rw_stateid(&rdata->args.stateid, rdata->args.context, | 317 | if (nfs4_set_rw_stateid(&hdr->args.stateid, hdr->args.context, |
| 328 | rdata->args.lock_context, FMODE_READ) == -EIO) | 318 | hdr->args.lock_context, FMODE_READ) == -EIO) |
| 329 | rpc_exit(task, -EIO); /* lost lock, terminate I/O */ | 319 | rpc_exit(task, -EIO); /* lost lock, terminate I/O */ |
| 330 | } | 320 | } |
| 331 | 321 | ||
| 332 | static void filelayout_read_call_done(struct rpc_task *task, void *data) | 322 | static void filelayout_read_call_done(struct rpc_task *task, void *data) |
| 333 | { | 323 | { |
| 334 | struct nfs_pgio_data *rdata = data; | 324 | struct nfs_pgio_header *hdr = data; |
| 335 | 325 | ||
| 336 | dprintk("--> %s task->tk_status %d\n", __func__, task->tk_status); | 326 | dprintk("--> %s task->tk_status %d\n", __func__, task->tk_status); |
| 337 | 327 | ||
| 338 | if (test_bit(NFS_IOHDR_REDO, &rdata->header->flags) && | 328 | if (test_bit(NFS_IOHDR_REDO, &hdr->flags) && |
| 339 | task->tk_status == 0) { | 329 | task->tk_status == 0) { |
| 340 | nfs41_sequence_done(task, &rdata->res.seq_res); | 330 | nfs41_sequence_done(task, &hdr->res.seq_res); |
| 341 | return; | 331 | return; |
| 342 | } | 332 | } |
| 343 | 333 | ||
| 344 | /* Note this may cause RPC to be resent */ | 334 | /* Note this may cause RPC to be resent */ |
| 345 | rdata->header->mds_ops->rpc_call_done(task, data); | 335 | hdr->mds_ops->rpc_call_done(task, data); |
| 346 | } | 336 | } |
| 347 | 337 | ||
| 348 | static void filelayout_read_count_stats(struct rpc_task *task, void *data) | 338 | static void filelayout_read_count_stats(struct rpc_task *task, void *data) |
| 349 | { | 339 | { |
| 350 | struct nfs_pgio_data *rdata = data; | 340 | struct nfs_pgio_header *hdr = data; |
| 351 | 341 | ||
| 352 | rpc_count_iostats(task, NFS_SERVER(rdata->header->inode)->client->cl_metrics); | 342 | rpc_count_iostats(task, NFS_SERVER(hdr->inode)->client->cl_metrics); |
| 353 | } | 343 | } |
| 354 | 344 | ||
| 355 | static void filelayout_read_release(void *data) | 345 | static void filelayout_read_release(void *data) |
| 356 | { | 346 | { |
| 357 | struct nfs_pgio_data *rdata = data; | 347 | struct nfs_pgio_header *hdr = data; |
| 358 | struct pnfs_layout_hdr *lo = rdata->header->lseg->pls_layout; | 348 | struct pnfs_layout_hdr *lo = hdr->lseg->pls_layout; |
| 359 | 349 | ||
| 360 | filelayout_fenceme(lo->plh_inode, lo); | 350 | filelayout_fenceme(lo->plh_inode, lo); |
| 361 | nfs_put_client(rdata->ds_clp); | 351 | nfs_put_client(hdr->ds_clp); |
| 362 | rdata->header->mds_ops->rpc_release(data); | 352 | hdr->mds_ops->rpc_release(data); |
| 363 | } | 353 | } |
| 364 | 354 | ||
| 365 | static int filelayout_write_done_cb(struct rpc_task *task, | 355 | static int filelayout_write_done_cb(struct rpc_task *task, |
| 366 | struct nfs_pgio_data *data) | 356 | struct nfs_pgio_header *hdr) |
| 367 | { | 357 | { |
| 368 | struct nfs_pgio_header *hdr = data->header; | ||
| 369 | int err; | 358 | int err; |
| 370 | 359 | ||
| 371 | trace_nfs4_pnfs_write(data, task->tk_status); | 360 | trace_nfs4_pnfs_write(hdr, task->tk_status); |
| 372 | err = filelayout_async_handle_error(task, data->args.context->state, | 361 | err = filelayout_async_handle_error(task, hdr->args.context->state, |
| 373 | data->ds_clp, hdr->lseg); | 362 | hdr->ds_clp, hdr->lseg); |
| 374 | 363 | ||
| 375 | switch (err) { | 364 | switch (err) { |
| 376 | case -NFS4ERR_RESET_TO_MDS: | 365 | case -NFS4ERR_RESET_TO_MDS: |
| 377 | filelayout_reset_write(data); | 366 | filelayout_reset_write(hdr); |
| 378 | return task->tk_status; | 367 | return task->tk_status; |
| 379 | case -EAGAIN: | 368 | case -EAGAIN: |
| 380 | rpc_restart_call_prepare(task); | 369 | rpc_restart_call_prepare(task); |
| 381 | return -EAGAIN; | 370 | return -EAGAIN; |
| 382 | } | 371 | } |
| 383 | 372 | ||
| 384 | filelayout_set_layoutcommit(data); | 373 | filelayout_set_layoutcommit(hdr); |
| 385 | return 0; | 374 | return 0; |
| 386 | } | 375 | } |
| 387 | 376 | ||
| @@ -419,57 +408,57 @@ static int filelayout_commit_done_cb(struct rpc_task *task, | |||
| 419 | 408 | ||
| 420 | static void filelayout_write_prepare(struct rpc_task *task, void *data) | 409 | static void filelayout_write_prepare(struct rpc_task *task, void *data) |
| 421 | { | 410 | { |
| 422 | struct nfs_pgio_data *wdata = data; | 411 | struct nfs_pgio_header *hdr = data; |
| 423 | 412 | ||
| 424 | if (unlikely(test_bit(NFS_CONTEXT_BAD, &wdata->args.context->flags))) { | 413 | if (unlikely(test_bit(NFS_CONTEXT_BAD, &hdr->args.context->flags))) { |
| 425 | rpc_exit(task, -EIO); | 414 | rpc_exit(task, -EIO); |
| 426 | return; | 415 | return; |
| 427 | } | 416 | } |
| 428 | if (filelayout_reset_to_mds(wdata->header->lseg)) { | 417 | if (filelayout_reset_to_mds(hdr->lseg)) { |
| 429 | dprintk("%s task %u reset io to MDS\n", __func__, task->tk_pid); | 418 | dprintk("%s task %u reset io to MDS\n", __func__, task->tk_pid); |
| 430 | filelayout_reset_write(wdata); | 419 | filelayout_reset_write(hdr); |
| 431 | rpc_exit(task, 0); | 420 | rpc_exit(task, 0); |
| 432 | return; | 421 | return; |
| 433 | } | 422 | } |
| 434 | if (nfs41_setup_sequence(wdata->ds_clp->cl_session, | 423 | if (nfs41_setup_sequence(hdr->ds_clp->cl_session, |
| 435 | &wdata->args.seq_args, | 424 | &hdr->args.seq_args, |
| 436 | &wdata->res.seq_res, | 425 | &hdr->res.seq_res, |
| 437 | task)) | 426 | task)) |
| 438 | return; | 427 | return; |
| 439 | if (nfs4_set_rw_stateid(&wdata->args.stateid, wdata->args.context, | 428 | if (nfs4_set_rw_stateid(&hdr->args.stateid, hdr->args.context, |
| 440 | wdata->args.lock_context, FMODE_WRITE) == -EIO) | 429 | hdr->args.lock_context, FMODE_WRITE) == -EIO) |
| 441 | rpc_exit(task, -EIO); /* lost lock, terminate I/O */ | 430 | rpc_exit(task, -EIO); /* lost lock, terminate I/O */ |
| 442 | } | 431 | } |
| 443 | 432 | ||
| 444 | static void filelayout_write_call_done(struct rpc_task *task, void *data) | 433 | static void filelayout_write_call_done(struct rpc_task *task, void *data) |
| 445 | { | 434 | { |
| 446 | struct nfs_pgio_data *wdata = data; | 435 | struct nfs_pgio_header *hdr = data; |
| 447 | 436 | ||
| 448 | if (test_bit(NFS_IOHDR_REDO, &wdata->header->flags) && | 437 | if (test_bit(NFS_IOHDR_REDO, &hdr->flags) && |
| 449 | task->tk_status == 0) { | 438 | task->tk_status == 0) { |
| 450 | nfs41_sequence_done(task, &wdata->res.seq_res); | 439 | nfs41_sequence_done(task, &hdr->res.seq_res); |
| 451 | return; | 440 | return; |
| 452 | } | 441 | } |
| 453 | 442 | ||
| 454 | /* Note this may cause RPC to be resent */ | 443 | /* Note this may cause RPC to be resent */ |
| 455 | wdata->header->mds_ops->rpc_call_done(task, data); | 444 | hdr->mds_ops->rpc_call_done(task, data); |
| 456 | } | 445 | } |
| 457 | 446 | ||
| 458 | static void filelayout_write_count_stats(struct rpc_task *task, void *data) | 447 | static void filelayout_write_count_stats(struct rpc_task *task, void *data) |
| 459 | { | 448 | { |
| 460 | struct nfs_pgio_data *wdata = data; | 449 | struct nfs_pgio_header *hdr = data; |
| 461 | 450 | ||
| 462 | rpc_count_iostats(task, NFS_SERVER(wdata->header->inode)->client->cl_metrics); | 451 | rpc_count_iostats(task, NFS_SERVER(hdr->inode)->client->cl_metrics); |
| 463 | } | 452 | } |
| 464 | 453 | ||
| 465 | static void filelayout_write_release(void *data) | 454 | static void filelayout_write_release(void *data) |
| 466 | { | 455 | { |
| 467 | struct nfs_pgio_data *wdata = data; | 456 | struct nfs_pgio_header *hdr = data; |
| 468 | struct pnfs_layout_hdr *lo = wdata->header->lseg->pls_layout; | 457 | struct pnfs_layout_hdr *lo = hdr->lseg->pls_layout; |
| 469 | 458 | ||
| 470 | filelayout_fenceme(lo->plh_inode, lo); | 459 | filelayout_fenceme(lo->plh_inode, lo); |
| 471 | nfs_put_client(wdata->ds_clp); | 460 | nfs_put_client(hdr->ds_clp); |
| 472 | wdata->header->mds_ops->rpc_release(data); | 461 | hdr->mds_ops->rpc_release(data); |
| 473 | } | 462 | } |
| 474 | 463 | ||
| 475 | static void filelayout_commit_prepare(struct rpc_task *task, void *data) | 464 | static void filelayout_commit_prepare(struct rpc_task *task, void *data) |
| @@ -529,19 +518,18 @@ static const struct rpc_call_ops filelayout_commit_call_ops = { | |||
| 529 | }; | 518 | }; |
| 530 | 519 | ||
| 531 | static enum pnfs_try_status | 520 | static enum pnfs_try_status |
| 532 | filelayout_read_pagelist(struct nfs_pgio_data *data) | 521 | filelayout_read_pagelist(struct nfs_pgio_header *hdr) |
| 533 | { | 522 | { |
| 534 | struct nfs_pgio_header *hdr = data->header; | ||
| 535 | struct pnfs_layout_segment *lseg = hdr->lseg; | 523 | struct pnfs_layout_segment *lseg = hdr->lseg; |
| 536 | struct nfs4_pnfs_ds *ds; | 524 | struct nfs4_pnfs_ds *ds; |
| 537 | struct rpc_clnt *ds_clnt; | 525 | struct rpc_clnt *ds_clnt; |
| 538 | loff_t offset = data->args.offset; | 526 | loff_t offset = hdr->args.offset; |
| 539 | u32 j, idx; | 527 | u32 j, idx; |
| 540 | struct nfs_fh *fh; | 528 | struct nfs_fh *fh; |
| 541 | 529 | ||
| 542 | dprintk("--> %s ino %lu pgbase %u req %Zu@%llu\n", | 530 | dprintk("--> %s ino %lu pgbase %u req %Zu@%llu\n", |
| 543 | __func__, hdr->inode->i_ino, | 531 | __func__, hdr->inode->i_ino, |
| 544 | data->args.pgbase, (size_t)data->args.count, offset); | 532 | hdr->args.pgbase, (size_t)hdr->args.count, offset); |
| 545 | 533 | ||
| 546 | /* Retrieve the correct rpc_client for the byte range */ | 534 | /* Retrieve the correct rpc_client for the byte range */ |
| 547 | j = nfs4_fl_calc_j_index(lseg, offset); | 535 | j = nfs4_fl_calc_j_index(lseg, offset); |
| @@ -559,30 +547,29 @@ filelayout_read_pagelist(struct nfs_pgio_data *data) | |||
| 559 | 547 | ||
| 560 | /* No multipath support. Use first DS */ | 548 | /* No multipath support. Use first DS */ |
| 561 | atomic_inc(&ds->ds_clp->cl_count); | 549 | atomic_inc(&ds->ds_clp->cl_count); |
| 562 | data->ds_clp = ds->ds_clp; | 550 | hdr->ds_clp = ds->ds_clp; |
| 563 | data->ds_idx = idx; | 551 | hdr->ds_idx = idx; |
| 564 | fh = nfs4_fl_select_ds_fh(lseg, j); | 552 | fh = nfs4_fl_select_ds_fh(lseg, j); |
| 565 | if (fh) | 553 | if (fh) |
| 566 | data->args.fh = fh; | 554 | hdr->args.fh = fh; |
| 567 | 555 | ||
| 568 | data->args.offset = filelayout_get_dserver_offset(lseg, offset); | 556 | hdr->args.offset = filelayout_get_dserver_offset(lseg, offset); |
| 569 | data->mds_offset = offset; | 557 | hdr->mds_offset = offset; |
| 570 | 558 | ||
| 571 | /* Perform an asynchronous read to ds */ | 559 | /* Perform an asynchronous read to ds */ |
| 572 | nfs_initiate_pgio(ds_clnt, data, | 560 | nfs_initiate_pgio(ds_clnt, hdr, |
| 573 | &filelayout_read_call_ops, 0, RPC_TASK_SOFTCONN); | 561 | &filelayout_read_call_ops, 0, RPC_TASK_SOFTCONN); |
| 574 | return PNFS_ATTEMPTED; | 562 | return PNFS_ATTEMPTED; |
| 575 | } | 563 | } |
| 576 | 564 | ||
| 577 | /* Perform async writes. */ | 565 | /* Perform async writes. */ |
| 578 | static enum pnfs_try_status | 566 | static enum pnfs_try_status |
| 579 | filelayout_write_pagelist(struct nfs_pgio_data *data, int sync) | 567 | filelayout_write_pagelist(struct nfs_pgio_header *hdr, int sync) |
| 580 | { | 568 | { |
| 581 | struct nfs_pgio_header *hdr = data->header; | ||
| 582 | struct pnfs_layout_segment *lseg = hdr->lseg; | 569 | struct pnfs_layout_segment *lseg = hdr->lseg; |
| 583 | struct nfs4_pnfs_ds *ds; | 570 | struct nfs4_pnfs_ds *ds; |
| 584 | struct rpc_clnt *ds_clnt; | 571 | struct rpc_clnt *ds_clnt; |
| 585 | loff_t offset = data->args.offset; | 572 | loff_t offset = hdr->args.offset; |
| 586 | u32 j, idx; | 573 | u32 j, idx; |
| 587 | struct nfs_fh *fh; | 574 | struct nfs_fh *fh; |
| 588 | 575 | ||
| @@ -598,21 +585,20 @@ filelayout_write_pagelist(struct nfs_pgio_data *data, int sync) | |||
| 598 | return PNFS_NOT_ATTEMPTED; | 585 | return PNFS_NOT_ATTEMPTED; |
| 599 | 586 | ||
| 600 | dprintk("%s ino %lu sync %d req %Zu@%llu DS: %s cl_count %d\n", | 587 | dprintk("%s ino %lu sync %d req %Zu@%llu DS: %s cl_count %d\n", |
| 601 | __func__, hdr->inode->i_ino, sync, (size_t) data->args.count, | 588 | __func__, hdr->inode->i_ino, sync, (size_t) hdr->args.count, |
| 602 | offset, ds->ds_remotestr, atomic_read(&ds->ds_clp->cl_count)); | 589 | offset, ds->ds_remotestr, atomic_read(&ds->ds_clp->cl_count)); |
| 603 | 590 | ||
| 604 | data->pgio_done_cb = filelayout_write_done_cb; | 591 | hdr->pgio_done_cb = filelayout_write_done_cb; |
| 605 | atomic_inc(&ds->ds_clp->cl_count); | 592 | atomic_inc(&ds->ds_clp->cl_count); |
| 606 | data->ds_clp = ds->ds_clp; | 593 | hdr->ds_clp = ds->ds_clp; |
| 607 | data->ds_idx = idx; | 594 | hdr->ds_idx = idx; |
| 608 | fh = nfs4_fl_select_ds_fh(lseg, j); | 595 | fh = nfs4_fl_select_ds_fh(lseg, j); |
| 609 | if (fh) | 596 | if (fh) |
| 610 | data->args.fh = fh; | 597 | hdr->args.fh = fh; |
| 611 | 598 | hdr->args.offset = filelayout_get_dserver_offset(lseg, offset); | |
| 612 | data->args.offset = filelayout_get_dserver_offset(lseg, offset); | ||
| 613 | 599 | ||
| 614 | /* Perform an asynchronous write */ | 600 | /* Perform an asynchronous write */ |
| 615 | nfs_initiate_pgio(ds_clnt, data, | 601 | nfs_initiate_pgio(ds_clnt, hdr, |
| 616 | &filelayout_write_call_ops, sync, | 602 | &filelayout_write_call_ops, sync, |
| 617 | RPC_TASK_SOFTCONN); | 603 | RPC_TASK_SOFTCONN); |
| 618 | return PNFS_ATTEMPTED; | 604 | return PNFS_ATTEMPTED; |
| @@ -1023,6 +1009,7 @@ static u32 select_bucket_index(struct nfs4_filelayout_segment *fl, u32 j) | |||
| 1023 | 1009 | ||
| 1024 | /* The generic layer is about to remove the req from the commit list. | 1010 | /* The generic layer is about to remove the req from the commit list. |
| 1025 | * If this will make the bucket empty, it will need to put the lseg reference. | 1011 | * If this will make the bucket empty, it will need to put the lseg reference. |
| 1012 | * Note this is must be called holding the inode (/cinfo) lock | ||
| 1026 | */ | 1013 | */ |
| 1027 | static void | 1014 | static void |
| 1028 | filelayout_clear_request_commit(struct nfs_page *req, | 1015 | filelayout_clear_request_commit(struct nfs_page *req, |
| @@ -1030,7 +1017,6 @@ filelayout_clear_request_commit(struct nfs_page *req, | |||
| 1030 | { | 1017 | { |
| 1031 | struct pnfs_layout_segment *freeme = NULL; | 1018 | struct pnfs_layout_segment *freeme = NULL; |
| 1032 | 1019 | ||
| 1033 | spin_lock(cinfo->lock); | ||
| 1034 | if (!test_and_clear_bit(PG_COMMIT_TO_DS, &req->wb_flags)) | 1020 | if (!test_and_clear_bit(PG_COMMIT_TO_DS, &req->wb_flags)) |
| 1035 | goto out; | 1021 | goto out; |
| 1036 | cinfo->ds->nwritten--; | 1022 | cinfo->ds->nwritten--; |
| @@ -1045,22 +1031,25 @@ filelayout_clear_request_commit(struct nfs_page *req, | |||
| 1045 | } | 1031 | } |
| 1046 | out: | 1032 | out: |
| 1047 | nfs_request_remove_commit_list(req, cinfo); | 1033 | nfs_request_remove_commit_list(req, cinfo); |
| 1048 | spin_unlock(cinfo->lock); | 1034 | pnfs_put_lseg_async(freeme); |
| 1049 | pnfs_put_lseg(freeme); | ||
| 1050 | } | 1035 | } |
| 1051 | 1036 | ||
| 1052 | static struct list_head * | 1037 | static void |
| 1053 | filelayout_choose_commit_list(struct nfs_page *req, | 1038 | filelayout_mark_request_commit(struct nfs_page *req, |
| 1054 | struct pnfs_layout_segment *lseg, | 1039 | struct pnfs_layout_segment *lseg, |
| 1055 | struct nfs_commit_info *cinfo) | 1040 | struct nfs_commit_info *cinfo) |
| 1041 | |||
| 1056 | { | 1042 | { |
| 1057 | struct nfs4_filelayout_segment *fl = FILELAYOUT_LSEG(lseg); | 1043 | struct nfs4_filelayout_segment *fl = FILELAYOUT_LSEG(lseg); |
| 1058 | u32 i, j; | 1044 | u32 i, j; |
| 1059 | struct list_head *list; | 1045 | struct list_head *list; |
| 1060 | struct pnfs_commit_bucket *buckets; | 1046 | struct pnfs_commit_bucket *buckets; |
| 1061 | 1047 | ||
| 1062 | if (fl->commit_through_mds) | 1048 | if (fl->commit_through_mds) { |
| 1063 | return &cinfo->mds->list; | 1049 | list = &cinfo->mds->list; |
| 1050 | spin_lock(cinfo->lock); | ||
| 1051 | goto mds_commit; | ||
| 1052 | } | ||
| 1064 | 1053 | ||
| 1065 | /* Note that we are calling nfs4_fl_calc_j_index on each page | 1054 | /* Note that we are calling nfs4_fl_calc_j_index on each page |
| 1066 | * that ends up being committed to a data server. An attractive | 1055 | * that ends up being committed to a data server. An attractive |
| @@ -1084,19 +1073,22 @@ filelayout_choose_commit_list(struct nfs_page *req, | |||
| 1084 | } | 1073 | } |
| 1085 | set_bit(PG_COMMIT_TO_DS, &req->wb_flags); | 1074 | set_bit(PG_COMMIT_TO_DS, &req->wb_flags); |
| 1086 | cinfo->ds->nwritten++; | 1075 | cinfo->ds->nwritten++; |
| 1087 | spin_unlock(cinfo->lock); | ||
| 1088 | return list; | ||
| 1089 | } | ||
| 1090 | 1076 | ||
| 1091 | static void | 1077 | mds_commit: |
| 1092 | filelayout_mark_request_commit(struct nfs_page *req, | 1078 | /* nfs_request_add_commit_list(). We need to add req to list without |
| 1093 | struct pnfs_layout_segment *lseg, | 1079 | * dropping cinfo lock. |
| 1094 | struct nfs_commit_info *cinfo) | 1080 | */ |
| 1095 | { | 1081 | set_bit(PG_CLEAN, &(req)->wb_flags); |
| 1096 | struct list_head *list; | 1082 | nfs_list_add_request(req, list); |
| 1097 | 1083 | cinfo->mds->ncommit++; | |
| 1098 | list = filelayout_choose_commit_list(req, lseg, cinfo); | 1084 | spin_unlock(cinfo->lock); |
| 1099 | nfs_request_add_commit_list(req, list, cinfo); | 1085 | if (!cinfo->dreq) { |
| 1086 | inc_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); | ||
| 1087 | inc_bdi_stat(page_file_mapping(req->wb_page)->backing_dev_info, | ||
| 1088 | BDI_RECLAIMABLE); | ||
| 1089 | __mark_inode_dirty(req->wb_context->dentry->d_inode, | ||
| 1090 | I_DIRTY_DATASYNC); | ||
| 1091 | } | ||
| 1100 | } | 1092 | } |
| 1101 | 1093 | ||
| 1102 | static u32 calc_ds_index_from_commit(struct pnfs_layout_segment *lseg, u32 i) | 1094 | static u32 calc_ds_index_from_commit(struct pnfs_layout_segment *lseg, u32 i) |
| @@ -1244,15 +1236,63 @@ restart: | |||
| 1244 | spin_unlock(cinfo->lock); | 1236 | spin_unlock(cinfo->lock); |
| 1245 | } | 1237 | } |
| 1246 | 1238 | ||
| 1239 | /* filelayout_search_commit_reqs - Search lists in @cinfo for the head reqest | ||
| 1240 | * for @page | ||
| 1241 | * @cinfo - commit info for current inode | ||
| 1242 | * @page - page to search for matching head request | ||
| 1243 | * | ||
| 1244 | * Returns a the head request if one is found, otherwise returns NULL. | ||
| 1245 | */ | ||
| 1246 | static struct nfs_page * | ||
| 1247 | filelayout_search_commit_reqs(struct nfs_commit_info *cinfo, struct page *page) | ||
| 1248 | { | ||
| 1249 | struct nfs_page *freq, *t; | ||
| 1250 | struct pnfs_commit_bucket *b; | ||
| 1251 | int i; | ||
| 1252 | |||
| 1253 | /* Linearly search the commit lists for each bucket until a matching | ||
| 1254 | * request is found */ | ||
| 1255 | for (i = 0, b = cinfo->ds->buckets; i < cinfo->ds->nbuckets; i++, b++) { | ||
| 1256 | list_for_each_entry_safe(freq, t, &b->written, wb_list) { | ||
| 1257 | if (freq->wb_page == page) | ||
| 1258 | return freq->wb_head; | ||
| 1259 | } | ||
| 1260 | list_for_each_entry_safe(freq, t, &b->committing, wb_list) { | ||
| 1261 | if (freq->wb_page == page) | ||
| 1262 | return freq->wb_head; | ||
| 1263 | } | ||
| 1264 | } | ||
| 1265 | |||
| 1266 | return NULL; | ||
| 1267 | } | ||
| 1268 | |||
| 1269 | static void filelayout_retry_commit(struct nfs_commit_info *cinfo, int idx) | ||
| 1270 | { | ||
| 1271 | struct pnfs_ds_commit_info *fl_cinfo = cinfo->ds; | ||
| 1272 | struct pnfs_commit_bucket *bucket = fl_cinfo->buckets; | ||
| 1273 | struct pnfs_layout_segment *freeme; | ||
| 1274 | int i; | ||
| 1275 | |||
| 1276 | for (i = idx; i < fl_cinfo->nbuckets; i++, bucket++) { | ||
| 1277 | if (list_empty(&bucket->committing)) | ||
| 1278 | continue; | ||
| 1279 | nfs_retry_commit(&bucket->committing, bucket->clseg, cinfo); | ||
| 1280 | spin_lock(cinfo->lock); | ||
| 1281 | freeme = bucket->clseg; | ||
| 1282 | bucket->clseg = NULL; | ||
| 1283 | spin_unlock(cinfo->lock); | ||
| 1284 | pnfs_put_lseg(freeme); | ||
| 1285 | } | ||
| 1286 | } | ||
| 1287 | |||
| 1247 | static unsigned int | 1288 | static unsigned int |
| 1248 | alloc_ds_commits(struct nfs_commit_info *cinfo, struct list_head *list) | 1289 | alloc_ds_commits(struct nfs_commit_info *cinfo, struct list_head *list) |
| 1249 | { | 1290 | { |
| 1250 | struct pnfs_ds_commit_info *fl_cinfo; | 1291 | struct pnfs_ds_commit_info *fl_cinfo; |
| 1251 | struct pnfs_commit_bucket *bucket; | 1292 | struct pnfs_commit_bucket *bucket; |
| 1252 | struct nfs_commit_data *data; | 1293 | struct nfs_commit_data *data; |
| 1253 | int i, j; | 1294 | int i; |
| 1254 | unsigned int nreq = 0; | 1295 | unsigned int nreq = 0; |
| 1255 | struct pnfs_layout_segment *freeme; | ||
| 1256 | 1296 | ||
| 1257 | fl_cinfo = cinfo->ds; | 1297 | fl_cinfo = cinfo->ds; |
| 1258 | bucket = fl_cinfo->buckets; | 1298 | bucket = fl_cinfo->buckets; |
| @@ -1272,16 +1312,7 @@ alloc_ds_commits(struct nfs_commit_info *cinfo, struct list_head *list) | |||
| 1272 | } | 1312 | } |
| 1273 | 1313 | ||
| 1274 | /* Clean up on error */ | 1314 | /* Clean up on error */ |
| 1275 | for (j = i; j < fl_cinfo->nbuckets; j++, bucket++) { | 1315 | filelayout_retry_commit(cinfo, i); |
| 1276 | if (list_empty(&bucket->committing)) | ||
| 1277 | continue; | ||
| 1278 | nfs_retry_commit(&bucket->committing, bucket->clseg, cinfo); | ||
| 1279 | spin_lock(cinfo->lock); | ||
| 1280 | freeme = bucket->clseg; | ||
| 1281 | bucket->clseg = NULL; | ||
| 1282 | spin_unlock(cinfo->lock); | ||
| 1283 | pnfs_put_lseg(freeme); | ||
| 1284 | } | ||
| 1285 | /* Caller will clean up entries put on list */ | 1316 | /* Caller will clean up entries put on list */ |
| 1286 | return nreq; | 1317 | return nreq; |
| 1287 | } | 1318 | } |
| @@ -1301,8 +1332,12 @@ filelayout_commit_pagelist(struct inode *inode, struct list_head *mds_pages, | |||
| 1301 | data->lseg = NULL; | 1332 | data->lseg = NULL; |
| 1302 | list_add(&data->pages, &list); | 1333 | list_add(&data->pages, &list); |
| 1303 | nreq++; | 1334 | nreq++; |
| 1304 | } else | 1335 | } else { |
| 1305 | nfs_retry_commit(mds_pages, NULL, cinfo); | 1336 | nfs_retry_commit(mds_pages, NULL, cinfo); |
| 1337 | filelayout_retry_commit(cinfo, 0); | ||
| 1338 | cinfo->completion_ops->error_cleanup(NFS_I(inode)); | ||
| 1339 | return -ENOMEM; | ||
| 1340 | } | ||
| 1306 | } | 1341 | } |
| 1307 | 1342 | ||
| 1308 | nreq += alloc_ds_commits(cinfo, &list); | 1343 | nreq += alloc_ds_commits(cinfo, &list); |
| @@ -1380,6 +1415,7 @@ static struct pnfs_layoutdriver_type filelayout_type = { | |||
| 1380 | .clear_request_commit = filelayout_clear_request_commit, | 1415 | .clear_request_commit = filelayout_clear_request_commit, |
| 1381 | .scan_commit_lists = filelayout_scan_commit_lists, | 1416 | .scan_commit_lists = filelayout_scan_commit_lists, |
| 1382 | .recover_commit_reqs = filelayout_recover_commit_reqs, | 1417 | .recover_commit_reqs = filelayout_recover_commit_reqs, |
| 1418 | .search_commit_reqs = filelayout_search_commit_reqs, | ||
| 1383 | .commit_pagelist = filelayout_commit_pagelist, | 1419 | .commit_pagelist = filelayout_commit_pagelist, |
| 1384 | .read_pagelist = filelayout_read_pagelist, | 1420 | .read_pagelist = filelayout_read_pagelist, |
| 1385 | .write_pagelist = filelayout_write_pagelist, | 1421 | .write_pagelist = filelayout_write_pagelist, |
diff --git a/fs/nfs/filelayout/filelayoutdev.c b/fs/nfs/filelayout/filelayoutdev.c index 44bf0140a4c7..8540516f4d71 100644 --- a/fs/nfs/filelayout/filelayoutdev.c +++ b/fs/nfs/filelayout/filelayoutdev.c | |||
| @@ -695,7 +695,7 @@ filelayout_get_device_info(struct inode *inode, | |||
| 695 | if (pdev == NULL) | 695 | if (pdev == NULL) |
| 696 | return NULL; | 696 | return NULL; |
| 697 | 697 | ||
| 698 | pages = kzalloc(max_pages * sizeof(struct page *), gfp_flags); | 698 | pages = kcalloc(max_pages, sizeof(struct page *), gfp_flags); |
| 699 | if (pages == NULL) { | 699 | if (pages == NULL) { |
| 700 | kfree(pdev); | 700 | kfree(pdev); |
| 701 | return NULL; | 701 | return NULL; |
| @@ -783,8 +783,8 @@ nfs4_fl_select_ds_fh(struct pnfs_layout_segment *lseg, u32 j) | |||
| 783 | static void nfs4_wait_ds_connect(struct nfs4_pnfs_ds *ds) | 783 | static void nfs4_wait_ds_connect(struct nfs4_pnfs_ds *ds) |
| 784 | { | 784 | { |
| 785 | might_sleep(); | 785 | might_sleep(); |
| 786 | wait_on_bit(&ds->ds_state, NFS4DS_CONNECTING, | 786 | wait_on_bit_action(&ds->ds_state, NFS4DS_CONNECTING, |
| 787 | nfs_wait_bit_killable, TASK_KILLABLE); | 787 | nfs_wait_bit_killable, TASK_KILLABLE); |
| 788 | } | 788 | } |
| 789 | 789 | ||
| 790 | static void nfs4_clear_ds_conn_bit(struct nfs4_pnfs_ds *ds) | 790 | static void nfs4_clear_ds_conn_bit(struct nfs4_pnfs_ds *ds) |
