diff options
author | Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> | 2011-02-28 06:34:04 -0500 |
---|---|---|
committer | Eric Van Hensbergen <ericvh@gmail.com> | 2011-03-15 10:57:40 -0400 |
commit | e959b54901e835f062ac8d44107bc543b66f0364 (patch) | |
tree | 89e8dae4796391a7effecd07b2950a08c1b5e410 /fs/9p | |
parent | fa6ea16160c72c448e2728dab4b6b0a133fdfc98 (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.c | 5 | ||||
-rw-r--r-- | fs/9p/vfs_file.c | 117 |
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 | */ |
257 | ssize_t v9fs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, | 257 | static ssize_t |
258 | loff_t pos, unsigned long nr_segs) | 258 | v9fs_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 | ||
582 | static ssize_t | ||
583 | v9fs_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 | */ | ||
611 | static ssize_t | ||
612 | v9fs_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 | |||
620 | static ssize_t | ||
621 | v9fs_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); | ||
663 | err_out: | ||
664 | mutex_unlock(&inode->i_mutex); | ||
665 | return retval; | ||
666 | |||
667 | buff_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 | */ | ||
680 | static ssize_t | ||
681 | v9fs_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 | |||
582 | static const struct vm_operations_struct v9fs_file_vm_ops = { | 690 | static 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 | |||
587 | const struct file_operations v9fs_cached_file_operations = { | 696 | const 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 | ||
600 | const struct file_operations v9fs_cached_file_operations_dotl = { | 709 | const 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, |