diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-07-30 19:33:25 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-07-30 19:33:25 -0400 |
commit | 7f155c702677d057d03b192ce652311de5434697 (patch) | |
tree | dcee0fbb463ec3e55cb50181180c7d175d5895c3 /fs/nfs/direct.c | |
parent | d761f3ed6e71bcca724a6e9e39efcac65b7b4ac1 (diff) | |
parent | 944171cbf499d3445c749f7c13c46de0a564a905 (diff) |
Merge tag 'nfs-for-4.8-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull NFS client updates from Trond Myklebust:
"Highlights include:
Stable bugfixes:
- nfs: don't create zero-length requests
- several LAYOUTGET bugfixes
Features:
- several performance related features
- more aggressive caching when we can rely on close-to-open
cache consistency
- remove serialisation of O_DIRECT reads and writes
- optimise several code paths to not flush to disk unnecessarily.
However allow for the idiosyncracies of pNFS for those layout
types that need to issue a LAYOUTCOMMIT before the metadata can
be updated on the server.
- SUNRPC updates to the client data receive path
- pNFS/SCSI support RH/Fedora dm-mpath device nodes
- pNFS files/flexfiles can now use unprivileged ports when
the generic NFS mount options allow it.
Bugfixes:
- Don't use RDMA direct data placement together with data
integrity or privacy security flavours
- Remove the RDMA ALLPHYSICAL memory registration mode as
it has potential security holes.
- Several layout recall fixes to improve NFSv4.1 protocol
compliance.
- Fix an Oops in the pNFS files and flexfiles connection
setup to the DS
- Allow retry of operations that used a returned delegation
stateid
- Don't mark the inode as revalidated if a LAYOUTCOMMIT is
outstanding
- Fix writeback races in nfs4_copy_range() and
nfs42_proc_deallocate()"
* tag 'nfs-for-4.8-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: (104 commits)
pNFS: Actively set attributes as invalid if LAYOUTCOMMIT is outstanding
NFSv4: Clean up lookup of SECINFO_NO_NAME
NFSv4.2: Fix warning "variable ‘stateids’ set but not used"
NFSv4: Fix warning "no previous prototype for ‘nfs4_listxattr’"
SUNRPC: Fix a compiler warning in fs/nfs/clnt.c
pNFS: Remove redundant smp_mb() from pnfs_init_lseg()
pNFS: Cleanup - do layout segment initialisation in one place
pNFS: Remove redundant stateid invalidation
pNFS: Remove redundant pnfs_mark_layout_returned_if_empty()
pNFS: Clear the layout metadata if the server changed the layout stateid
pNFS: Cleanup - don't open code pnfs_mark_layout_stateid_invalid()
NFS: pnfs_mark_matching_lsegs_return() should match the layout sequence id
pNFS: Do not set plh_return_seq for non-callback related layoutreturns
pNFS: Ensure layoutreturn acts as a completion for layout callbacks
pNFS: Fix CB_LAYOUTRECALL stateid verification
pNFS: Always update the layout barrier seqid on LAYOUTGET
pNFS: Always update the layout stateid if NFS_LAYOUT_INVALID_STID is set
pNFS: Clear the layout return tracking on layout reinitialisation
pNFS: LAYOUTRETURN should only update the stateid if the layout is valid
nfs: don't create zero-length requests
...
Diffstat (limited to 'fs/nfs/direct.c')
-rw-r--r-- | fs/nfs/direct.c | 93 |
1 files changed, 32 insertions, 61 deletions
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index e6210ead71d0..72b7d13ee3c6 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c | |||
@@ -196,6 +196,12 @@ static void nfs_direct_set_hdr_verf(struct nfs_direct_req *dreq, | |||
196 | WARN_ON_ONCE(verfp->committed < 0); | 196 | WARN_ON_ONCE(verfp->committed < 0); |
197 | } | 197 | } |
198 | 198 | ||
199 | static int nfs_direct_cmp_verf(const struct nfs_writeverf *v1, | ||
200 | const struct nfs_writeverf *v2) | ||
201 | { | ||
202 | return nfs_write_verifier_cmp(&v1->verifier, &v2->verifier); | ||
203 | } | ||
204 | |||
199 | /* | 205 | /* |
200 | * nfs_direct_cmp_hdr_verf - compare verifier for pgio header | 206 | * nfs_direct_cmp_hdr_verf - compare verifier for pgio header |
201 | * @dreq - direct request possibly spanning multiple servers | 207 | * @dreq - direct request possibly spanning multiple servers |
@@ -215,7 +221,7 @@ static int nfs_direct_set_or_cmp_hdr_verf(struct nfs_direct_req *dreq, | |||
215 | nfs_direct_set_hdr_verf(dreq, hdr); | 221 | nfs_direct_set_hdr_verf(dreq, hdr); |
216 | return 0; | 222 | return 0; |
217 | } | 223 | } |
218 | return memcmp(verfp, &hdr->verf, sizeof(struct nfs_writeverf)); | 224 | return nfs_direct_cmp_verf(verfp, &hdr->verf); |
219 | } | 225 | } |
220 | 226 | ||
221 | /* | 227 | /* |
@@ -238,7 +244,7 @@ static int nfs_direct_cmp_commit_data_verf(struct nfs_direct_req *dreq, | |||
238 | if (verfp->committed < 0) | 244 | if (verfp->committed < 0) |
239 | return 1; | 245 | return 1; |
240 | 246 | ||
241 | return memcmp(verfp, &data->verf, sizeof(struct nfs_writeverf)); | 247 | return nfs_direct_cmp_verf(verfp, &data->verf); |
242 | } | 248 | } |
243 | 249 | ||
244 | /** | 250 | /** |
@@ -366,22 +372,10 @@ out: | |||
366 | * Synchronous I/O uses a stack-allocated iocb. Thus we can't trust | 372 | * Synchronous I/O uses a stack-allocated iocb. Thus we can't trust |
367 | * the iocb is still valid here if this is a synchronous request. | 373 | * the iocb is still valid here if this is a synchronous request. |
368 | */ | 374 | */ |
369 | static void nfs_direct_complete(struct nfs_direct_req *dreq, bool write) | 375 | static void nfs_direct_complete(struct nfs_direct_req *dreq) |
370 | { | 376 | { |
371 | struct inode *inode = dreq->inode; | 377 | struct inode *inode = dreq->inode; |
372 | 378 | ||
373 | if (dreq->iocb && write) { | ||
374 | loff_t pos = dreq->iocb->ki_pos + dreq->count; | ||
375 | |||
376 | spin_lock(&inode->i_lock); | ||
377 | if (i_size_read(inode) < pos) | ||
378 | i_size_write(inode, pos); | ||
379 | spin_unlock(&inode->i_lock); | ||
380 | } | ||
381 | |||
382 | if (write) | ||
383 | nfs_zap_mapping(inode, inode->i_mapping); | ||
384 | |||
385 | inode_dio_end(inode); | 379 | inode_dio_end(inode); |
386 | 380 | ||
387 | if (dreq->iocb) { | 381 | if (dreq->iocb) { |
@@ -436,7 +430,7 @@ static void nfs_direct_read_completion(struct nfs_pgio_header *hdr) | |||
436 | } | 430 | } |
437 | out_put: | 431 | out_put: |
438 | if (put_dreq(dreq)) | 432 | if (put_dreq(dreq)) |
439 | nfs_direct_complete(dreq, false); | 433 | nfs_direct_complete(dreq); |
440 | hdr->release(hdr); | 434 | hdr->release(hdr); |
441 | } | 435 | } |
442 | 436 | ||
@@ -542,7 +536,7 @@ static ssize_t nfs_direct_read_schedule_iovec(struct nfs_direct_req *dreq, | |||
542 | } | 536 | } |
543 | 537 | ||
544 | if (put_dreq(dreq)) | 538 | if (put_dreq(dreq)) |
545 | nfs_direct_complete(dreq, false); | 539 | nfs_direct_complete(dreq); |
546 | return 0; | 540 | return 0; |
547 | } | 541 | } |
548 | 542 | ||
@@ -583,17 +577,12 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, struct iov_iter *iter) | |||
583 | if (!count) | 577 | if (!count) |
584 | goto out; | 578 | goto out; |
585 | 579 | ||
586 | inode_lock(inode); | ||
587 | result = nfs_sync_mapping(mapping); | ||
588 | if (result) | ||
589 | goto out_unlock; | ||
590 | |||
591 | task_io_account_read(count); | 580 | task_io_account_read(count); |
592 | 581 | ||
593 | result = -ENOMEM; | 582 | result = -ENOMEM; |
594 | dreq = nfs_direct_req_alloc(); | 583 | dreq = nfs_direct_req_alloc(); |
595 | if (dreq == NULL) | 584 | if (dreq == NULL) |
596 | goto out_unlock; | 585 | goto out; |
597 | 586 | ||
598 | dreq->inode = inode; | 587 | dreq->inode = inode; |
599 | dreq->bytes_left = dreq->max_count = count; | 588 | dreq->bytes_left = dreq->max_count = count; |
@@ -608,10 +597,12 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, struct iov_iter *iter) | |||
608 | if (!is_sync_kiocb(iocb)) | 597 | if (!is_sync_kiocb(iocb)) |
609 | dreq->iocb = iocb; | 598 | dreq->iocb = iocb; |
610 | 599 | ||
600 | nfs_start_io_direct(inode); | ||
601 | |||
611 | NFS_I(inode)->read_io += count; | 602 | NFS_I(inode)->read_io += count; |
612 | result = nfs_direct_read_schedule_iovec(dreq, iter, iocb->ki_pos); | 603 | result = nfs_direct_read_schedule_iovec(dreq, iter, iocb->ki_pos); |
613 | 604 | ||
614 | inode_unlock(inode); | 605 | nfs_end_io_direct(inode); |
615 | 606 | ||
616 | if (!result) { | 607 | if (!result) { |
617 | result = nfs_direct_wait(dreq); | 608 | result = nfs_direct_wait(dreq); |
@@ -619,13 +610,8 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, struct iov_iter *iter) | |||
619 | iocb->ki_pos += result; | 610 | iocb->ki_pos += result; |
620 | } | 611 | } |
621 | 612 | ||
622 | nfs_direct_req_release(dreq); | ||
623 | return result; | ||
624 | |||
625 | out_release: | 613 | out_release: |
626 | nfs_direct_req_release(dreq); | 614 | nfs_direct_req_release(dreq); |
627 | out_unlock: | ||
628 | inode_unlock(inode); | ||
629 | out: | 615 | out: |
630 | return result; | 616 | return result; |
631 | } | 617 | } |
@@ -657,6 +643,8 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq) | |||
657 | nfs_direct_write_scan_commit_list(dreq->inode, &reqs, &cinfo); | 643 | nfs_direct_write_scan_commit_list(dreq->inode, &reqs, &cinfo); |
658 | 644 | ||
659 | dreq->count = 0; | 645 | dreq->count = 0; |
646 | dreq->verf.committed = NFS_INVALID_STABLE_HOW; | ||
647 | nfs_clear_pnfs_ds_commit_verifiers(&dreq->ds_cinfo); | ||
660 | for (i = 0; i < dreq->mirror_count; i++) | 648 | for (i = 0; i < dreq->mirror_count; i++) |
661 | dreq->mirrors[i].count = 0; | 649 | dreq->mirrors[i].count = 0; |
662 | get_dreq(dreq); | 650 | get_dreq(dreq); |
@@ -775,7 +763,8 @@ static void nfs_direct_write_schedule_work(struct work_struct *work) | |||
775 | nfs_direct_write_reschedule(dreq); | 763 | nfs_direct_write_reschedule(dreq); |
776 | break; | 764 | break; |
777 | default: | 765 | default: |
778 | nfs_direct_complete(dreq, true); | 766 | nfs_zap_mapping(dreq->inode, dreq->inode->i_mapping); |
767 | nfs_direct_complete(dreq); | ||
779 | } | 768 | } |
780 | } | 769 | } |
781 | 770 | ||
@@ -991,6 +980,7 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq, | |||
991 | ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter) | 980 | ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter) |
992 | { | 981 | { |
993 | ssize_t result = -EINVAL; | 982 | ssize_t result = -EINVAL; |
983 | size_t count; | ||
994 | struct file *file = iocb->ki_filp; | 984 | struct file *file = iocb->ki_filp; |
995 | struct address_space *mapping = file->f_mapping; | 985 | struct address_space *mapping = file->f_mapping; |
996 | struct inode *inode = mapping->host; | 986 | struct inode *inode = mapping->host; |
@@ -1001,34 +991,24 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter) | |||
1001 | dfprintk(FILE, "NFS: direct write(%pD2, %zd@%Ld)\n", | 991 | dfprintk(FILE, "NFS: direct write(%pD2, %zd@%Ld)\n", |
1002 | file, iov_iter_count(iter), (long long) iocb->ki_pos); | 992 | file, iov_iter_count(iter), (long long) iocb->ki_pos); |
1003 | 993 | ||
1004 | nfs_add_stats(mapping->host, NFSIOS_DIRECTWRITTENBYTES, | 994 | result = generic_write_checks(iocb, iter); |
1005 | iov_iter_count(iter)); | 995 | if (result <= 0) |
996 | return result; | ||
997 | count = result; | ||
998 | nfs_add_stats(mapping->host, NFSIOS_DIRECTWRITTENBYTES, count); | ||
1006 | 999 | ||
1007 | pos = iocb->ki_pos; | 1000 | pos = iocb->ki_pos; |
1008 | end = (pos + iov_iter_count(iter) - 1) >> PAGE_SHIFT; | 1001 | end = (pos + iov_iter_count(iter) - 1) >> PAGE_SHIFT; |
1009 | 1002 | ||
1010 | inode_lock(inode); | 1003 | task_io_account_write(count); |
1011 | |||
1012 | result = nfs_sync_mapping(mapping); | ||
1013 | if (result) | ||
1014 | goto out_unlock; | ||
1015 | |||
1016 | if (mapping->nrpages) { | ||
1017 | result = invalidate_inode_pages2_range(mapping, | ||
1018 | pos >> PAGE_SHIFT, end); | ||
1019 | if (result) | ||
1020 | goto out_unlock; | ||
1021 | } | ||
1022 | |||
1023 | task_io_account_write(iov_iter_count(iter)); | ||
1024 | 1004 | ||
1025 | result = -ENOMEM; | 1005 | result = -ENOMEM; |
1026 | dreq = nfs_direct_req_alloc(); | 1006 | dreq = nfs_direct_req_alloc(); |
1027 | if (!dreq) | 1007 | if (!dreq) |
1028 | goto out_unlock; | 1008 | goto out; |
1029 | 1009 | ||
1030 | dreq->inode = inode; | 1010 | dreq->inode = inode; |
1031 | dreq->bytes_left = dreq->max_count = iov_iter_count(iter); | 1011 | dreq->bytes_left = dreq->max_count = count; |
1032 | dreq->io_start = pos; | 1012 | dreq->io_start = pos; |
1033 | dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp)); | 1013 | dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp)); |
1034 | l_ctx = nfs_get_lock_context(dreq->ctx); | 1014 | l_ctx = nfs_get_lock_context(dreq->ctx); |
@@ -1040,6 +1020,8 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter) | |||
1040 | if (!is_sync_kiocb(iocb)) | 1020 | if (!is_sync_kiocb(iocb)) |
1041 | dreq->iocb = iocb; | 1021 | dreq->iocb = iocb; |
1042 | 1022 | ||
1023 | nfs_start_io_direct(inode); | ||
1024 | |||
1043 | result = nfs_direct_write_schedule_iovec(dreq, iter, pos); | 1025 | result = nfs_direct_write_schedule_iovec(dreq, iter, pos); |
1044 | 1026 | ||
1045 | if (mapping->nrpages) { | 1027 | if (mapping->nrpages) { |
@@ -1047,30 +1029,19 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter) | |||
1047 | pos >> PAGE_SHIFT, end); | 1029 | pos >> PAGE_SHIFT, end); |
1048 | } | 1030 | } |
1049 | 1031 | ||
1050 | inode_unlock(inode); | 1032 | nfs_end_io_direct(inode); |
1051 | 1033 | ||
1052 | if (!result) { | 1034 | if (!result) { |
1053 | result = nfs_direct_wait(dreq); | 1035 | result = nfs_direct_wait(dreq); |
1054 | if (result > 0) { | 1036 | if (result > 0) { |
1055 | struct inode *inode = mapping->host; | ||
1056 | |||
1057 | iocb->ki_pos = pos + result; | 1037 | iocb->ki_pos = pos + result; |
1058 | spin_lock(&inode->i_lock); | ||
1059 | if (i_size_read(inode) < iocb->ki_pos) | ||
1060 | i_size_write(inode, iocb->ki_pos); | ||
1061 | spin_unlock(&inode->i_lock); | ||
1062 | |||
1063 | /* XXX: should check the generic_write_sync retval */ | 1038 | /* XXX: should check the generic_write_sync retval */ |
1064 | generic_write_sync(iocb, result); | 1039 | generic_write_sync(iocb, result); |
1065 | } | 1040 | } |
1066 | } | 1041 | } |
1067 | nfs_direct_req_release(dreq); | ||
1068 | return result; | ||
1069 | |||
1070 | out_release: | 1042 | out_release: |
1071 | nfs_direct_req_release(dreq); | 1043 | nfs_direct_req_release(dreq); |
1072 | out_unlock: | 1044 | out: |
1073 | inode_unlock(inode); | ||
1074 | return result; | 1045 | return result; |
1075 | } | 1046 | } |
1076 | 1047 | ||