aboutsummaryrefslogtreecommitdiffstats
path: root/fs/9p
diff options
context:
space:
mode:
authorAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>2011-02-28 06:34:04 -0500
committerEric Van Hensbergen <ericvh@gmail.com>2011-03-15 10:57:40 -0400
commite959b54901e835f062ac8d44107bc543b66f0364 (patch)
tree89e8dae4796391a7effecd07b2950a08c1b5e410 /fs/9p
parentfa6ea16160c72c448e2728dab4b6b0a133fdfc98 (diff)
fs/9p: Add direct IO support in cached mode
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> Signed-off-by: Venkateswararao Jujjuri <jvrao@linux.vnet.ibm.com> Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com>
Diffstat (limited to 'fs/9p')
-rw-r--r--fs/9p/vfs_addr.c5
-rw-r--r--fs/9p/vfs_file.c117
2 files changed, 116 insertions, 6 deletions
diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c
index ee455526ca5b..2524e4cbb8ea 100644
--- a/fs/9p/vfs_addr.c
+++ b/fs/9p/vfs_addr.c
@@ -254,8 +254,9 @@ static int v9fs_launder_page(struct page *page)
254 * with an error. 254 * with an error.
255 * 255 *
256 */ 256 */
257ssize_t v9fs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, 257static ssize_t
258 loff_t pos, unsigned long nr_segs) 258v9fs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
259 loff_t pos, unsigned long nr_segs)
259{ 260{
260 /* 261 /*
261 * FIXME 262 * FIXME
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
index 3cff25e759ec..78bcb97c3425 100644
--- a/fs/9p/vfs_file.c
+++ b/fs/9p/vfs_file.c
@@ -579,15 +579,124 @@ out_unlock:
579 return VM_FAULT_NOPAGE; 579 return VM_FAULT_NOPAGE;
580} 580}
581 581
582static ssize_t
583v9fs_direct_read(struct file *filp, char __user *udata, size_t count,
584 loff_t *offsetp)
585{
586 loff_t size, offset;
587 struct inode *inode;
588 struct address_space *mapping;
589
590 offset = *offsetp;
591 mapping = filp->f_mapping;
592 inode = mapping->host;
593 if (!count)
594 return 0;
595 size = i_size_read(inode);
596 if (offset < size)
597 filemap_write_and_wait_range(mapping, offset,
598 offset + count - 1);
599
600 return v9fs_file_read(filp, udata, count, offsetp);
601}
602
603/**
604 * v9fs_cached_file_read - read from a file
605 * @filp: file pointer to read
606 * @udata: user data buffer to read data into
607 * @count: size of buffer
608 * @offset: offset at which to read data
609 *
610 */
611static ssize_t
612v9fs_cached_file_read(struct file *filp, char __user *data, size_t count,
613 loff_t *offset)
614{
615 if (filp->f_flags & O_DIRECT)
616 return v9fs_direct_read(filp, data, count, offset);
617 return do_sync_read(filp, data, count, offset);
618}
619
620static ssize_t
621v9fs_direct_write(struct file *filp, const char __user * data,
622 size_t count, loff_t *offsetp)
623{
624 loff_t offset;
625 ssize_t retval;
626 struct inode *inode;
627 struct address_space *mapping;
628
629 offset = *offsetp;
630 mapping = filp->f_mapping;
631 inode = mapping->host;
632 if (!count)
633 return 0;
634
635 mutex_lock(&inode->i_mutex);
636 retval = filemap_write_and_wait_range(mapping, offset,
637 offset + count - 1);
638 if (retval)
639 goto err_out;
640 /*
641 * After a write we want buffered reads to be sure to go to disk to get
642 * the new data. We invalidate clean cached page from the region we're
643 * about to write. We do this *before* the write so that if we fail
644 * here we fall back to buffered write
645 */
646 if (mapping->nrpages) {
647 pgoff_t pg_start = offset >> PAGE_CACHE_SHIFT;
648 pgoff_t pg_end = (offset + count - 1) >> PAGE_CACHE_SHIFT;
649
650 retval = invalidate_inode_pages2_range(mapping,
651 pg_start, pg_end);
652 /*
653 * If a page can not be invalidated, fall back
654 * to buffered write.
655 */
656 if (retval) {
657 if (retval == -EBUSY)
658 goto buff_write;
659 goto err_out;
660 }
661 }
662 retval = v9fs_file_write(filp, data, count, offsetp);
663err_out:
664 mutex_unlock(&inode->i_mutex);
665 return retval;
666
667buff_write:
668 mutex_unlock(&inode->i_mutex);
669 return do_sync_write(filp, data, count, offsetp);
670}
671
672/**
673 * v9fs_cached_file_write - write to a file
674 * @filp: file pointer to write
675 * @data: data buffer to write data from
676 * @count: size of buffer
677 * @offset: offset at which to write data
678 *
679 */
680static ssize_t
681v9fs_cached_file_write(struct file *filp, const char __user * data,
682 size_t count, loff_t *offset)
683{
684
685 if (filp->f_flags & O_DIRECT)
686 return v9fs_direct_write(filp, data, count, offset);
687 return do_sync_write(filp, data, count, offset);
688}
689
582static const struct vm_operations_struct v9fs_file_vm_ops = { 690static const struct vm_operations_struct v9fs_file_vm_ops = {
583 .fault = filemap_fault, 691 .fault = filemap_fault,
584 .page_mkwrite = v9fs_vm_page_mkwrite, 692 .page_mkwrite = v9fs_vm_page_mkwrite,
585}; 693};
586 694
695
587const struct file_operations v9fs_cached_file_operations = { 696const struct file_operations v9fs_cached_file_operations = {
588 .llseek = generic_file_llseek, 697 .llseek = generic_file_llseek,
589 .read = do_sync_read, 698 .read = v9fs_cached_file_read,
590 .write = do_sync_write, 699 .write = v9fs_cached_file_write,
591 .aio_read = generic_file_aio_read, 700 .aio_read = generic_file_aio_read,
592 .aio_write = generic_file_aio_write, 701 .aio_write = generic_file_aio_write,
593 .open = v9fs_file_open, 702 .open = v9fs_file_open,
@@ -599,8 +708,8 @@ const struct file_operations v9fs_cached_file_operations = {
599 708
600const struct file_operations v9fs_cached_file_operations_dotl = { 709const struct file_operations v9fs_cached_file_operations_dotl = {
601 .llseek = generic_file_llseek, 710 .llseek = generic_file_llseek,
602 .read = do_sync_read, 711 .read = v9fs_cached_file_read,
603 .write = do_sync_write, 712 .write = v9fs_cached_file_write,
604 .aio_read = generic_file_aio_read, 713 .aio_read = generic_file_aio_read,
605 .aio_write = generic_file_aio_write, 714 .aio_write = generic_file_aio_write,
606 .open = v9fs_file_open, 715 .open = v9fs_file_open,