aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/direct.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-07-30 19:33:25 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-07-30 19:33:25 -0400
commit7f155c702677d057d03b192ce652311de5434697 (patch)
treedcee0fbb463ec3e55cb50181180c7d175d5895c3 /fs/nfs/direct.c
parentd761f3ed6e71bcca724a6e9e39efcac65b7b4ac1 (diff)
parent944171cbf499d3445c749f7c13c46de0a564a905 (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.c93
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
199static 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 */
369static void nfs_direct_complete(struct nfs_direct_req *dreq, bool write) 375static 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 }
437out_put: 431out_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
625out_release: 613out_release:
626 nfs_direct_req_release(dreq); 614 nfs_direct_req_release(dreq);
627out_unlock:
628 inode_unlock(inode);
629out: 615out:
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,
991ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter) 980ssize_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
1070out_release: 1042out_release:
1071 nfs_direct_req_release(dreq); 1043 nfs_direct_req_release(dreq);
1072out_unlock: 1044out:
1073 inode_unlock(inode);
1074 return result; 1045 return result;
1075} 1046}
1076 1047