aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorChuck Lever <cel@netapp.com>2006-03-20 13:44:29 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2006-03-20 13:44:29 -0500
commit0cdd80d07fb0f558dfdb30f6e0b9905f5e5475f1 (patch)
treec25fe5e4bdb4196039bf5b098c1c9f58e98af2e2 /fs/nfs
parent5dd602f20688e08c85ac91e0451c4e6321ed25d7 (diff)
NFS: remove support for multi-segment iovs in the direct read path
Eliminate the persistent use of automatic storage in all parts of the NFS client's direct read path to pave the way for introducing support for aio against files opened with the O_DIRECT flag. Test plan: Compile the kernel with CONFIG_NFS and CONFIG_NFS_DIRECTIO enabled. Millions of fsx-odirect ops. OraSim. Signed-off-by: Chuck Lever <cel@netapp.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/direct.c66
1 files changed, 15 insertions, 51 deletions
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 8f5d2dfd5a8a..6ecde9602f99 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -321,7 +321,7 @@ static ssize_t nfs_direct_read_wait(struct nfs_direct_req *dreq, int intr)
321 return (ssize_t) result; 321 return (ssize_t) result;
322} 322}
323 323
324static ssize_t nfs_direct_read_seg(struct inode *inode, struct nfs_open_context *ctx, unsigned long user_addr, size_t count, loff_t file_offset, struct page **pages, unsigned int nr_pages) 324static ssize_t nfs_direct_read(struct inode *inode, struct nfs_open_context *ctx, unsigned long user_addr, size_t count, loff_t file_offset, struct page **pages, unsigned int nr_pages)
325{ 325{
326 ssize_t result; 326 ssize_t result;
327 sigset_t oldset; 327 sigset_t oldset;
@@ -346,48 +346,6 @@ static ssize_t nfs_direct_read_seg(struct inode *inode, struct nfs_open_context
346 return result; 346 return result;
347} 347}
348 348
349/*
350 * We've already pushed out any non-direct writes so that this read
351 * will see them when we read from the server.
352 */
353static ssize_t nfs_direct_read(struct inode *inode, struct nfs_open_context *ctx, const struct iovec *iov, loff_t file_offset, unsigned long nr_segs)
354{
355 ssize_t tot_bytes = 0;
356 unsigned long seg = 0;
357
358 while ((seg < nr_segs) && (tot_bytes >= 0)) {
359 ssize_t result;
360 int page_count;
361 struct page **pages;
362 const struct iovec *vec = &iov[seg++];
363 unsigned long user_addr = (unsigned long) vec->iov_base;
364 size_t size = vec->iov_len;
365
366 page_count = nfs_get_user_pages(READ, user_addr, size, &pages);
367 if (page_count < 0) {
368 nfs_free_user_pages(pages, 0, 0);
369 if (tot_bytes > 0)
370 break;
371 return page_count;
372 }
373
374 result = nfs_direct_read_seg(inode, ctx, user_addr, size,
375 file_offset, pages, page_count);
376
377 if (result <= 0) {
378 if (tot_bytes > 0)
379 break;
380 return result;
381 }
382 tot_bytes += result;
383 file_offset += result;
384 if (result < size)
385 break;
386 }
387
388 return tot_bytes;
389}
390
391static ssize_t nfs_direct_write_seg(struct inode *inode, struct nfs_open_context *ctx, unsigned long user_addr, size_t count, loff_t file_offset, struct page **pages, int nr_pages) 349static ssize_t nfs_direct_write_seg(struct inode *inode, struct nfs_open_context *ctx, unsigned long user_addr, size_t count, loff_t file_offset, struct page **pages, int nr_pages)
392{ 350{
393 const unsigned int wsize = NFS_SERVER(inode)->wsize; 351 const unsigned int wsize = NFS_SERVER(inode)->wsize;
@@ -559,16 +517,13 @@ static ssize_t nfs_direct_write(struct inode *inode, struct nfs_open_context *ct
559ssize_t nfs_file_direct_read(struct kiocb *iocb, char __user *buf, size_t count, loff_t pos) 517ssize_t nfs_file_direct_read(struct kiocb *iocb, char __user *buf, size_t count, loff_t pos)
560{ 518{
561 ssize_t retval = -EINVAL; 519 ssize_t retval = -EINVAL;
562 loff_t *ppos = &iocb->ki_pos; 520 int page_count;
521 struct page **pages;
563 struct file *file = iocb->ki_filp; 522 struct file *file = iocb->ki_filp;
564 struct nfs_open_context *ctx = 523 struct nfs_open_context *ctx =
565 (struct nfs_open_context *) file->private_data; 524 (struct nfs_open_context *) file->private_data;
566 struct address_space *mapping = file->f_mapping; 525 struct address_space *mapping = file->f_mapping;
567 struct inode *inode = mapping->host; 526 struct inode *inode = mapping->host;
568 struct iovec iov = {
569 .iov_base = buf,
570 .iov_len = count,
571 };
572 527
573 dprintk("nfs: direct read(%s/%s, %lu@%Ld)\n", 528 dprintk("nfs: direct read(%s/%s, %lu@%Ld)\n",
574 file->f_dentry->d_parent->d_name.name, 529 file->f_dentry->d_parent->d_name.name,
@@ -580,7 +535,7 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, char __user *buf, size_t count,
580 if (count < 0) 535 if (count < 0)
581 goto out; 536 goto out;
582 retval = -EFAULT; 537 retval = -EFAULT;
583 if (!access_ok(VERIFY_WRITE, iov.iov_base, iov.iov_len)) 538 if (!access_ok(VERIFY_WRITE, buf, count))
584 goto out; 539 goto out;
585 retval = 0; 540 retval = 0;
586 if (!count) 541 if (!count)
@@ -590,9 +545,18 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, char __user *buf, size_t count,
590 if (retval) 545 if (retval)
591 goto out; 546 goto out;
592 547
593 retval = nfs_direct_read(inode, ctx, &iov, pos, 1); 548 page_count = nfs_get_user_pages(READ, (unsigned long) buf,
549 count, &pages);
550 if (page_count < 0) {
551 nfs_free_user_pages(pages, 0, 0);
552 retval = page_count;
553 goto out;
554 }
555
556 retval = nfs_direct_read(inode, ctx, (unsigned long) buf, count, pos,
557 pages, page_count);
594 if (retval > 0) 558 if (retval > 0)
595 *ppos = pos + retval; 559 iocb->ki_pos = pos + retval;
596 560
597out: 561out:
598 return retval; 562 return retval;