aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChuck Lever <cel@netapp.com>2006-03-20 13:44:32 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2006-03-20 13:44:32 -0500
commit47989d7454398827500d0e73766270986a3b488f (patch)
treeca7c3ce3ec47d6f16fa1b42be7c468266ed3fce9
parent462d5b3296b56289efec426499a83faad4c08d9e (diff)
NFS: remove support for multi-segment iovs in the direct write path
Eliminate the persistent use of automatic storage in all parts of the NFS client's direct write 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>
-rw-r--r--fs/nfs/direct.c68
1 files changed, 17 insertions, 51 deletions
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index dea3239cdded..9a7d45907054 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -510,6 +510,7 @@ static void nfs_direct_write_schedule(struct nfs_direct_req *dreq, struct inode
510 data->args.count = bytes; 510 data->args.count = bytes;
511 data->res.fattr = &data->fattr; 511 data->res.fattr = &data->fattr;
512 data->res.count = bytes; 512 data->res.count = bytes;
513 data->res.verf = &data->verf;
513 514
514 rpc_init_task(&data->task, NFS_CLIENT(inode), RPC_TASK_ASYNC, 515 rpc_init_task(&data->task, NFS_CLIENT(inode), RPC_TASK_ASYNC,
515 &nfs_write_direct_ops, data); 516 &nfs_write_direct_ops, data);
@@ -538,7 +539,7 @@ static void nfs_direct_write_schedule(struct nfs_direct_req *dreq, struct inode
538 } while (count != 0); 539 } while (count != 0);
539} 540}
540 541
541static 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) 542static ssize_t nfs_direct_write(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)
542{ 543{
543 ssize_t result; 544 ssize_t result;
544 sigset_t oldset; 545 sigset_t oldset;
@@ -552,6 +553,8 @@ static ssize_t nfs_direct_write_seg(struct inode *inode, struct nfs_open_context
552 dreq->pages = pages; 553 dreq->pages = pages;
553 dreq->npages = nr_pages; 554 dreq->npages = nr_pages;
554 555
556 nfs_add_stats(inode, NFSIOS_DIRECTWRITTENBYTES, count);
557
555 nfs_begin_data_update(inode); 558 nfs_begin_data_update(inode);
556 559
557 rpc_clnt_sigmask(clnt, &oldset); 560 rpc_clnt_sigmask(clnt, &oldset);
@@ -565,50 +568,6 @@ static ssize_t nfs_direct_write_seg(struct inode *inode, struct nfs_open_context
565 return result; 568 return result;
566} 569}
567 570
568/*
569 * Upon return, generic_file_direct_IO invalidates any cached pages
570 * that non-direct readers might access, so they will pick up these
571 * writes immediately.
572 */
573static ssize_t nfs_direct_write(struct inode *inode, struct nfs_open_context *ctx, const struct iovec *iov, loff_t file_offset, unsigned long nr_segs)
574{
575 ssize_t tot_bytes = 0;
576 unsigned long seg = 0;
577
578 while ((seg < nr_segs) && (tot_bytes >= 0)) {
579 ssize_t result;
580 int page_count;
581 struct page **pages;
582 const struct iovec *vec = &iov[seg++];
583 unsigned long user_addr = (unsigned long) vec->iov_base;
584 size_t size = vec->iov_len;
585
586 page_count = nfs_get_user_pages(WRITE, user_addr, size, &pages);
587 if (page_count < 0) {
588 nfs_free_user_pages(pages, 0, 0);
589 if (tot_bytes > 0)
590 break;
591 return page_count;
592 }
593
594 nfs_add_stats(inode, NFSIOS_DIRECTWRITTENBYTES, size);
595 result = nfs_direct_write_seg(inode, ctx, user_addr, size,
596 file_offset, pages, page_count);
597
598 if (result <= 0) {
599 if (tot_bytes > 0)
600 break;
601 return result;
602 }
603 nfs_add_stats(inode, NFSIOS_SERVERWRITTENBYTES, result);
604 tot_bytes += result;
605 file_offset += result;
606 if (result < size)
607 break;
608 }
609 return tot_bytes;
610}
611
612/** 571/**
613 * nfs_file_direct_read - file direct read operation for NFS files 572 * nfs_file_direct_read - file direct read operation for NFS files
614 * @iocb: target I/O control block 573 * @iocb: target I/O control block
@@ -701,14 +660,13 @@ out:
701ssize_t nfs_file_direct_write(struct kiocb *iocb, const char __user *buf, size_t count, loff_t pos) 660ssize_t nfs_file_direct_write(struct kiocb *iocb, const char __user *buf, size_t count, loff_t pos)
702{ 661{
703 ssize_t retval; 662 ssize_t retval;
663 int page_count;
664 struct page **pages;
704 struct file *file = iocb->ki_filp; 665 struct file *file = iocb->ki_filp;
705 struct nfs_open_context *ctx = 666 struct nfs_open_context *ctx =
706 (struct nfs_open_context *) file->private_data; 667 (struct nfs_open_context *) file->private_data;
707 struct address_space *mapping = file->f_mapping; 668 struct address_space *mapping = file->f_mapping;
708 struct inode *inode = mapping->host; 669 struct inode *inode = mapping->host;
709 struct iovec iov = {
710 .iov_base = (char __user *)buf,
711 };
712 670
713 dfprintk(VFS, "nfs: direct write(%s/%s, %lu@%Ld)\n", 671 dfprintk(VFS, "nfs: direct write(%s/%s, %lu@%Ld)\n",
714 file->f_dentry->d_parent->d_name.name, 672 file->f_dentry->d_parent->d_name.name,
@@ -729,17 +687,25 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, const char __user *buf, size_t
729 retval = 0; 687 retval = 0;
730 if (!count) 688 if (!count)
731 goto out; 689 goto out;
732 iov.iov_len = count,
733 690
734 retval = -EFAULT; 691 retval = -EFAULT;
735 if (!access_ok(VERIFY_READ, iov.iov_base, iov.iov_len)) 692 if (!access_ok(VERIFY_READ, buf, count))
736 goto out; 693 goto out;
737 694
738 retval = nfs_sync_mapping(mapping); 695 retval = nfs_sync_mapping(mapping);
739 if (retval) 696 if (retval)
740 goto out; 697 goto out;
741 698
742 retval = nfs_direct_write(inode, ctx, &iov, pos, 1); 699 page_count = nfs_get_user_pages(WRITE, (unsigned long) buf,
700 count, &pages);
701 if (page_count < 0) {
702 nfs_free_user_pages(pages, 0, 0);
703 retval = page_count;
704 goto out;
705 }
706
707 retval = nfs_direct_write(inode, ctx, (unsigned long) buf, count,
708 pos, pages, page_count);
743 if (mapping->nrpages) 709 if (mapping->nrpages)
744 invalidate_inode_pages2(mapping); 710 invalidate_inode_pages2(mapping);
745 if (retval > 0) 711 if (retval > 0)