aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2007-11-12 12:16:52 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2007-11-26 16:32:36 -0500
commitc216fd708e1a97431925ecffd6d1896cff61df0a (patch)
tree3f6e61bb72f5c852773faad9a5baaec00adae39e /fs
parent19f737879cc623c3aa73e655465faa3bff121768 (diff)
NFS: Support multiple segment iovecs in the NFS direct I/O path
Allow applications to perform asynchronous scatter-gather direct I/O to NFS files. Signed-off-by: Chuck Lever <cel@netapp.com> Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/nfs/direct.c67
1 files changed, 23 insertions, 44 deletions
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index e30d9285a566..88d5d1c7f987 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -272,8 +272,6 @@ static ssize_t nfs_direct_read_schedule(struct nfs_direct_req *dreq, unsigned lo
272 int result; 272 int result;
273 ssize_t started = 0; 273 ssize_t started = 0;
274 274
275 get_dreq(dreq);
276
277 do { 275 do {
278 struct nfs_read_data *data; 276 struct nfs_read_data *data;
279 size_t bytes; 277 size_t bytes;
@@ -347,11 +345,8 @@ static ssize_t nfs_direct_read_schedule(struct nfs_direct_req *dreq, unsigned lo
347 count -= bytes; 345 count -= bytes;
348 } while (count != 0); 346 } while (count != 0);
349 347
350 if (put_dreq(dreq))
351 nfs_direct_complete(dreq);
352
353 if (started) 348 if (started)
354 return 0; 349 return started;
355 return result < 0 ? (ssize_t) result : -EFAULT; 350 return result < 0 ? (ssize_t) result : -EFAULT;
356} 351}
357 352
@@ -390,7 +385,8 @@ static ssize_t nfs_direct_read_schedule_iovec(struct nfs_direct_req *dreq,
390 return -EIO; 385 return -EIO;
391} 386}
392 387
393static ssize_t nfs_direct_read(struct kiocb *iocb, unsigned long user_addr, size_t count, loff_t pos) 388static ssize_t nfs_direct_read(struct kiocb *iocb, const struct iovec *iov,
389 unsigned long nr_segs, loff_t pos)
394{ 390{
395 ssize_t result = 0; 391 ssize_t result = 0;
396 sigset_t oldset; 392 sigset_t oldset;
@@ -407,9 +403,8 @@ static ssize_t nfs_direct_read(struct kiocb *iocb, unsigned long user_addr, size
407 if (!is_sync_kiocb(iocb)) 403 if (!is_sync_kiocb(iocb))
408 dreq->iocb = iocb; 404 dreq->iocb = iocb;
409 405
410 nfs_add_stats(inode, NFSIOS_DIRECTREADBYTES, count);
411 rpc_clnt_sigmask(clnt, &oldset); 406 rpc_clnt_sigmask(clnt, &oldset);
412 result = nfs_direct_read_schedule(dreq, user_addr, count, pos); 407 result = nfs_direct_read_schedule_iovec(dreq, iov, nr_segs, pos);
413 if (!result) 408 if (!result)
414 result = nfs_direct_wait(dreq); 409 result = nfs_direct_wait(dreq);
415 rpc_clnt_sigunmask(clnt, &oldset); 410 rpc_clnt_sigunmask(clnt, &oldset);
@@ -645,8 +640,6 @@ static ssize_t nfs_direct_write_schedule(struct nfs_direct_req *dreq, unsigned l
645 int result; 640 int result;
646 ssize_t started = 0; 641 ssize_t started = 0;
647 642
648 get_dreq(dreq);
649
650 do { 643 do {
651 struct nfs_write_data *data; 644 struct nfs_write_data *data;
652 size_t bytes; 645 size_t bytes;
@@ -724,11 +717,8 @@ static ssize_t nfs_direct_write_schedule(struct nfs_direct_req *dreq, unsigned l
724 count -= bytes; 717 count -= bytes;
725 } while (count != 0); 718 } while (count != 0);
726 719
727 if (put_dreq(dreq))
728 nfs_direct_write_complete(dreq, inode);
729
730 if (started) 720 if (started)
731 return 0; 721 return started;
732 return result < 0 ? (ssize_t) result : -EFAULT; 722 return result < 0 ? (ssize_t) result : -EFAULT;
733} 723}
734 724
@@ -768,7 +758,9 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq,
768 return -EIO; 758 return -EIO;
769} 759}
770 760
771static ssize_t nfs_direct_write(struct kiocb *iocb, unsigned long user_addr, size_t count, loff_t pos) 761static ssize_t nfs_direct_write(struct kiocb *iocb, const struct iovec *iov,
762 unsigned long nr_segs, loff_t pos,
763 size_t count)
772{ 764{
773 ssize_t result = 0; 765 ssize_t result = 0;
774 sigset_t oldset; 766 sigset_t oldset;
@@ -791,10 +783,8 @@ static ssize_t nfs_direct_write(struct kiocb *iocb, unsigned long user_addr, siz
791 if (!is_sync_kiocb(iocb)) 783 if (!is_sync_kiocb(iocb))
792 dreq->iocb = iocb; 784 dreq->iocb = iocb;
793 785
794 nfs_add_stats(inode, NFSIOS_DIRECTWRITTENBYTES, count);
795
796 rpc_clnt_sigmask(clnt, &oldset); 786 rpc_clnt_sigmask(clnt, &oldset);
797 result = nfs_direct_write_schedule(dreq, user_addr, count, pos, sync); 787 result = nfs_direct_write_schedule_iovec(dreq, iov, nr_segs, pos, sync);
798 if (!result) 788 if (!result)
799 result = nfs_direct_wait(dreq); 789 result = nfs_direct_wait(dreq);
800 rpc_clnt_sigunmask(clnt, &oldset); 790 rpc_clnt_sigunmask(clnt, &oldset);
@@ -830,21 +820,16 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, const struct iovec *iov,
830 ssize_t retval = -EINVAL; 820 ssize_t retval = -EINVAL;
831 struct file *file = iocb->ki_filp; 821 struct file *file = iocb->ki_filp;
832 struct address_space *mapping = file->f_mapping; 822 struct address_space *mapping = file->f_mapping;
833 /* XXX: temporary */ 823 size_t count;
834 const char __user *buf = iov[0].iov_base; 824
835 size_t count = iov[0].iov_len; 825 count = iov_length(iov, nr_segs);
826 nfs_add_stats(mapping->host, NFSIOS_DIRECTREADBYTES, count);
836 827
837 dprintk("nfs: direct read(%s/%s, %lu@%Ld)\n", 828 dprintk("nfs: direct read(%s/%s, %zd@%Ld)\n",
838 file->f_path.dentry->d_parent->d_name.name, 829 file->f_path.dentry->d_parent->d_name.name,
839 file->f_path.dentry->d_name.name, 830 file->f_path.dentry->d_name.name,
840 (unsigned long) count, (long long) pos); 831 count, (long long) pos);
841 832
842 if (nr_segs != 1)
843 goto out;
844
845 retval = -EFAULT;
846 if (!access_ok(VERIFY_WRITE, buf, count))
847 goto out;
848 retval = 0; 833 retval = 0;
849 if (!count) 834 if (!count)
850 goto out; 835 goto out;
@@ -853,7 +838,7 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, const struct iovec *iov,
853 if (retval) 838 if (retval)
854 goto out; 839 goto out;
855 840
856 retval = nfs_direct_read(iocb, (unsigned long) buf, count, pos); 841 retval = nfs_direct_read(iocb, iov, nr_segs, pos);
857 if (retval > 0) 842 if (retval > 0)
858 iocb->ki_pos = pos + retval; 843 iocb->ki_pos = pos + retval;
859 844
@@ -892,17 +877,15 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
892 ssize_t retval = -EINVAL; 877 ssize_t retval = -EINVAL;
893 struct file *file = iocb->ki_filp; 878 struct file *file = iocb->ki_filp;
894 struct address_space *mapping = file->f_mapping; 879 struct address_space *mapping = file->f_mapping;
895 /* XXX: temporary */ 880 size_t count;
896 const char __user *buf = iov[0].iov_base;
897 size_t count = iov[0].iov_len;
898 881
899 dprintk("nfs: direct write(%s/%s, %lu@%Ld)\n", 882 count = iov_length(iov, nr_segs);
883 nfs_add_stats(mapping->host, NFSIOS_DIRECTWRITTENBYTES, count);
884
885 dfprintk(VFS, "nfs: direct write(%s/%s, %zd@%Ld)\n",
900 file->f_path.dentry->d_parent->d_name.name, 886 file->f_path.dentry->d_parent->d_name.name,
901 file->f_path.dentry->d_name.name, 887 file->f_path.dentry->d_name.name,
902 (unsigned long) count, (long long) pos); 888 count, (long long) pos);
903
904 if (nr_segs != 1)
905 goto out;
906 889
907 retval = generic_write_checks(file, &pos, &count, 0); 890 retval = generic_write_checks(file, &pos, &count, 0);
908 if (retval) 891 if (retval)
@@ -915,15 +898,11 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
915 if (!count) 898 if (!count)
916 goto out; 899 goto out;
917 900
918 retval = -EFAULT;
919 if (!access_ok(VERIFY_READ, buf, count))
920 goto out;
921
922 retval = nfs_sync_mapping(mapping); 901 retval = nfs_sync_mapping(mapping);
923 if (retval) 902 if (retval)
924 goto out; 903 goto out;
925 904
926 retval = nfs_direct_write(iocb, (unsigned long) buf, count, pos); 905 retval = nfs_direct_write(iocb, iov, nr_segs, pos, count);
927 906
928 if (retval > 0) 907 if (retval > 0)
929 iocb->ki_pos = pos + retval; 908 iocb->ki_pos = pos + retval;