diff options
Diffstat (limited to 'fs/nfs/direct.c')
-rw-r--r-- | fs/nfs/direct.c | 48 |
1 files changed, 32 insertions, 16 deletions
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index e5da9d7fb69e..6a4083d550c6 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c | |||
@@ -288,8 +288,8 @@ ssize_t nfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter) | |||
288 | VM_BUG_ON(iov_iter_count(iter) != PAGE_SIZE); | 288 | VM_BUG_ON(iov_iter_count(iter) != PAGE_SIZE); |
289 | 289 | ||
290 | if (iov_iter_rw(iter) == READ) | 290 | if (iov_iter_rw(iter) == READ) |
291 | return nfs_file_direct_read(iocb, iter); | 291 | return nfs_file_direct_read(iocb, iter, true); |
292 | return nfs_file_direct_write(iocb, iter); | 292 | return nfs_file_direct_write(iocb, iter, true); |
293 | } | 293 | } |
294 | 294 | ||
295 | static void nfs_direct_release_pages(struct page **pages, unsigned int npages) | 295 | static void nfs_direct_release_pages(struct page **pages, unsigned int npages) |
@@ -553,6 +553,7 @@ static ssize_t nfs_direct_read_schedule_iovec(struct nfs_direct_req *dreq, | |||
553 | * nfs_file_direct_read - file direct read operation for NFS files | 553 | * nfs_file_direct_read - file direct read operation for NFS files |
554 | * @iocb: target I/O control block | 554 | * @iocb: target I/O control block |
555 | * @iter: vector of user buffers into which to read data | 555 | * @iter: vector of user buffers into which to read data |
556 | * @swap: flag indicating this is swap IO, not O_DIRECT IO | ||
556 | * | 557 | * |
557 | * We use this function for direct reads instead of calling | 558 | * We use this function for direct reads instead of calling |
558 | * generic_file_aio_read() in order to avoid gfar's check to see if | 559 | * generic_file_aio_read() in order to avoid gfar's check to see if |
@@ -568,7 +569,8 @@ static ssize_t nfs_direct_read_schedule_iovec(struct nfs_direct_req *dreq, | |||
568 | * client must read the updated atime from the server back into its | 569 | * client must read the updated atime from the server back into its |
569 | * cache. | 570 | * cache. |
570 | */ | 571 | */ |
571 | ssize_t nfs_file_direct_read(struct kiocb *iocb, struct iov_iter *iter) | 572 | ssize_t nfs_file_direct_read(struct kiocb *iocb, struct iov_iter *iter, |
573 | bool swap) | ||
572 | { | 574 | { |
573 | struct file *file = iocb->ki_filp; | 575 | struct file *file = iocb->ki_filp; |
574 | struct address_space *mapping = file->f_mapping; | 576 | struct address_space *mapping = file->f_mapping; |
@@ -610,12 +612,14 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, struct iov_iter *iter) | |||
610 | if (iter_is_iovec(iter)) | 612 | if (iter_is_iovec(iter)) |
611 | dreq->flags = NFS_ODIRECT_SHOULD_DIRTY; | 613 | dreq->flags = NFS_ODIRECT_SHOULD_DIRTY; |
612 | 614 | ||
613 | nfs_start_io_direct(inode); | 615 | if (!swap) |
616 | nfs_start_io_direct(inode); | ||
614 | 617 | ||
615 | NFS_I(inode)->read_io += count; | 618 | NFS_I(inode)->read_io += count; |
616 | requested = nfs_direct_read_schedule_iovec(dreq, iter, iocb->ki_pos); | 619 | requested = nfs_direct_read_schedule_iovec(dreq, iter, iocb->ki_pos); |
617 | 620 | ||
618 | nfs_end_io_direct(inode); | 621 | if (!swap) |
622 | nfs_end_io_direct(inode); | ||
619 | 623 | ||
620 | if (requested > 0) { | 624 | if (requested > 0) { |
621 | result = nfs_direct_wait(dreq); | 625 | result = nfs_direct_wait(dreq); |
@@ -884,7 +888,7 @@ static const struct nfs_pgio_completion_ops nfs_direct_write_completion_ops = { | |||
884 | */ | 888 | */ |
885 | static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq, | 889 | static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq, |
886 | struct iov_iter *iter, | 890 | struct iov_iter *iter, |
887 | loff_t pos) | 891 | loff_t pos, int ioflags) |
888 | { | 892 | { |
889 | struct nfs_pageio_descriptor desc; | 893 | struct nfs_pageio_descriptor desc; |
890 | struct inode *inode = dreq->inode; | 894 | struct inode *inode = dreq->inode; |
@@ -892,7 +896,7 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq, | |||
892 | size_t requested_bytes = 0; | 896 | size_t requested_bytes = 0; |
893 | size_t wsize = max_t(size_t, NFS_SERVER(inode)->wsize, PAGE_SIZE); | 897 | size_t wsize = max_t(size_t, NFS_SERVER(inode)->wsize, PAGE_SIZE); |
894 | 898 | ||
895 | nfs_pageio_init_write(&desc, inode, FLUSH_COND_STABLE, false, | 899 | nfs_pageio_init_write(&desc, inode, ioflags, false, |
896 | &nfs_direct_write_completion_ops); | 900 | &nfs_direct_write_completion_ops); |
897 | desc.pg_dreq = dreq; | 901 | desc.pg_dreq = dreq; |
898 | get_dreq(dreq); | 902 | get_dreq(dreq); |
@@ -971,6 +975,7 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq, | |||
971 | * nfs_file_direct_write - file direct write operation for NFS files | 975 | * nfs_file_direct_write - file direct write operation for NFS files |
972 | * @iocb: target I/O control block | 976 | * @iocb: target I/O control block |
973 | * @iter: vector of user buffers from which to write data | 977 | * @iter: vector of user buffers from which to write data |
978 | * @swap: flag indicating this is swap IO, not O_DIRECT IO | ||
974 | * | 979 | * |
975 | * We use this function for direct writes instead of calling | 980 | * We use this function for direct writes instead of calling |
976 | * generic_file_aio_write() in order to avoid taking the inode | 981 | * generic_file_aio_write() in order to avoid taking the inode |
@@ -987,7 +992,8 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq, | |||
987 | * Note that O_APPEND is not supported for NFS direct writes, as there | 992 | * Note that O_APPEND is not supported for NFS direct writes, as there |
988 | * is no atomic O_APPEND write facility in the NFS protocol. | 993 | * is no atomic O_APPEND write facility in the NFS protocol. |
989 | */ | 994 | */ |
990 | ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter) | 995 | ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter, |
996 | bool swap) | ||
991 | { | 997 | { |
992 | ssize_t result = -EINVAL, requested; | 998 | ssize_t result = -EINVAL, requested; |
993 | size_t count; | 999 | size_t count; |
@@ -1001,7 +1007,11 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter) | |||
1001 | dfprintk(FILE, "NFS: direct write(%pD2, %zd@%Ld)\n", | 1007 | dfprintk(FILE, "NFS: direct write(%pD2, %zd@%Ld)\n", |
1002 | file, iov_iter_count(iter), (long long) iocb->ki_pos); | 1008 | file, iov_iter_count(iter), (long long) iocb->ki_pos); |
1003 | 1009 | ||
1004 | result = generic_write_checks(iocb, iter); | 1010 | if (swap) |
1011 | /* bypass generic checks */ | ||
1012 | result = iov_iter_count(iter); | ||
1013 | else | ||
1014 | result = generic_write_checks(iocb, iter); | ||
1005 | if (result <= 0) | 1015 | if (result <= 0) |
1006 | return result; | 1016 | return result; |
1007 | count = result; | 1017 | count = result; |
@@ -1031,16 +1041,22 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter) | |||
1031 | if (!is_sync_kiocb(iocb)) | 1041 | if (!is_sync_kiocb(iocb)) |
1032 | dreq->iocb = iocb; | 1042 | dreq->iocb = iocb; |
1033 | 1043 | ||
1034 | nfs_start_io_direct(inode); | 1044 | if (swap) { |
1045 | requested = nfs_direct_write_schedule_iovec(dreq, iter, pos, | ||
1046 | FLUSH_STABLE); | ||
1047 | } else { | ||
1048 | nfs_start_io_direct(inode); | ||
1035 | 1049 | ||
1036 | requested = nfs_direct_write_schedule_iovec(dreq, iter, pos); | 1050 | requested = nfs_direct_write_schedule_iovec(dreq, iter, pos, |
1051 | FLUSH_COND_STABLE); | ||
1037 | 1052 | ||
1038 | if (mapping->nrpages) { | 1053 | if (mapping->nrpages) { |
1039 | invalidate_inode_pages2_range(mapping, | 1054 | invalidate_inode_pages2_range(mapping, |
1040 | pos >> PAGE_SHIFT, end); | 1055 | pos >> PAGE_SHIFT, end); |
1041 | } | 1056 | } |
1042 | 1057 | ||
1043 | nfs_end_io_direct(inode); | 1058 | nfs_end_io_direct(inode); |
1059 | } | ||
1044 | 1060 | ||
1045 | if (requested > 0) { | 1061 | if (requested > 0) { |
1046 | result = nfs_direct_wait(dreq); | 1062 | result = nfs_direct_wait(dreq); |