aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/direct.c
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2007-11-12 12:16:47 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2007-11-26 16:32:35 -0500
commit19f737879cc623c3aa73e655465faa3bff121768 (patch)
tree12b96a6b345892592260ce55aadb7528ef3e516f /fs/nfs/direct.c
parent014313a9d66272ed37b9ebd64c3f30b596a4c8e1 (diff)
NFS: Introduce iovec I/O helpers to fs/nfs/direct.c
Add helpers that iterate over multi-segment iovecs. These will be used to support multi-segment scatter/gather direct I/O in a later patch. 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/nfs/direct.c')
-rw-r--r--fs/nfs/direct.c71
1 files changed, 71 insertions, 0 deletions
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index afcab007a22b..e30d9285a566 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -355,6 +355,41 @@ static ssize_t nfs_direct_read_schedule(struct nfs_direct_req *dreq, unsigned lo
355 return result < 0 ? (ssize_t) result : -EFAULT; 355 return result < 0 ? (ssize_t) result : -EFAULT;
356} 356}
357 357
358static ssize_t nfs_direct_read_schedule_iovec(struct nfs_direct_req *dreq,
359 const struct iovec *iov,
360 unsigned long nr_segs,
361 loff_t pos)
362{
363 ssize_t result = -EINVAL;
364 size_t requested_bytes = 0;
365 unsigned long seg;
366
367 get_dreq(dreq);
368
369 for (seg = 0; seg < nr_segs; seg++) {
370 const struct iovec *vec = &iov[seg];
371 result = nfs_direct_read_schedule(dreq,
372 (unsigned long)vec->iov_base,
373 vec->iov_len, pos);
374 if (result < 0)
375 break;
376 requested_bytes += result;
377 if ((size_t)result < vec->iov_len)
378 break;
379 pos += vec->iov_len;
380 }
381
382 if (put_dreq(dreq))
383 nfs_direct_complete(dreq);
384
385 if (requested_bytes != 0)
386 return 0;
387
388 if (result < 0)
389 return result;
390 return -EIO;
391}
392
358static ssize_t nfs_direct_read(struct kiocb *iocb, unsigned long user_addr, size_t count, loff_t pos) 393static ssize_t nfs_direct_read(struct kiocb *iocb, unsigned long user_addr, size_t count, loff_t pos)
359{ 394{
360 ssize_t result = 0; 395 ssize_t result = 0;
@@ -697,6 +732,42 @@ static ssize_t nfs_direct_write_schedule(struct nfs_direct_req *dreq, unsigned l
697 return result < 0 ? (ssize_t) result : -EFAULT; 732 return result < 0 ? (ssize_t) result : -EFAULT;
698} 733}
699 734
735static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq,
736 const struct iovec *iov,
737 unsigned long nr_segs,
738 loff_t pos, int sync)
739{
740 ssize_t result = 0;
741 size_t requested_bytes = 0;
742 unsigned long seg;
743
744 get_dreq(dreq);
745
746 for (seg = 0; seg < nr_segs; seg++) {
747 const struct iovec *vec = &iov[seg];
748 result = nfs_direct_write_schedule(dreq,
749 (unsigned long)vec->iov_base,
750 vec->iov_len,
751 pos, sync);
752 if (result < 0)
753 break;
754 requested_bytes += result;
755 if ((size_t)result < vec->iov_len)
756 break;
757 pos += vec->iov_len;
758 }
759
760 if (put_dreq(dreq))
761 nfs_direct_write_complete(dreq, dreq->inode);
762
763 if (requested_bytes != 0)
764 return 0;
765
766 if (result < 0)
767 return result;
768 return -EIO;
769}
770
700static ssize_t nfs_direct_write(struct kiocb *iocb, unsigned long user_addr, size_t count, loff_t pos) 771static ssize_t nfs_direct_write(struct kiocb *iocb, unsigned long user_addr, size_t count, loff_t pos)
701{ 772{
702 ssize_t result = 0; 773 ssize_t result = 0;