aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/file.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-06-15 13:50:00 -0400
committerDavid Woodhouse <dwmw2@hera.kernel.org>2007-06-15 13:50:00 -0400
commit9ebefb180bad4914a31c4e1748ba187a30e1e990 (patch)
tree68d4833889fac64b1b69e6212afa9584cc88f2ff /fs/btrfs/file.c
parentf1ace244c8c1e16eaa5c8b3b5339849651e31ede (diff)
Btrfs: patch queue: page_mkwrite
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/file.c')
-rw-r--r--fs/btrfs/file.c176
1 files changed, 26 insertions, 150 deletions
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 83836fb3d4e9..de8d47b44e12 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -103,10 +103,6 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans,
103 this_write = min((size_t)PAGE_CACHE_SIZE - offset, write_bytes); 103 this_write = min((size_t)PAGE_CACHE_SIZE - offset, write_bytes);
104 /* FIXME, one block at a time */ 104 /* FIXME, one block at a time */
105 105
106 mutex_lock(&root->fs_info->fs_mutex);
107 trans = btrfs_start_transaction(root, 1);
108 btrfs_set_trans_block_group(trans, inode);
109
110 bh = page_buffers(pages[i]); 106 bh = page_buffers(pages[i]);
111 107
112 if (buffer_mapped(bh) && bh->b_blocknr == 0) { 108 if (buffer_mapped(bh) && bh->b_blocknr == 0) {
@@ -115,6 +111,10 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans,
115 char *ptr, *kaddr; 111 char *ptr, *kaddr;
116 u32 datasize; 112 u32 datasize;
117 113
114 mutex_lock(&root->fs_info->fs_mutex);
115 trans = btrfs_start_transaction(root, 1);
116 btrfs_set_trans_block_group(trans, inode);
117
118 /* create an inline extent, and copy the data in */ 118 /* create an inline extent, and copy the data in */
119 path = btrfs_alloc_path(); 119 path = btrfs_alloc_path();
120 BUG_ON(!path); 120 BUG_ON(!path);
@@ -135,24 +135,19 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans,
135 btrfs_set_file_extent_type(ei, 135 btrfs_set_file_extent_type(ei,
136 BTRFS_FILE_EXTENT_INLINE); 136 BTRFS_FILE_EXTENT_INLINE);
137 ptr = btrfs_file_extent_inline_start(ei); 137 ptr = btrfs_file_extent_inline_start(ei);
138
138 kaddr = kmap_atomic(bh->b_page, KM_USER0); 139 kaddr = kmap_atomic(bh->b_page, KM_USER0);
139 btrfs_memcpy(root, path->nodes[0]->b_data, 140 btrfs_memcpy(root, path->nodes[0]->b_data,
140 ptr, kaddr + bh_offset(bh), 141 ptr, kaddr + bh_offset(bh),
141 offset + write_bytes); 142 offset + write_bytes);
142 kunmap_atomic(kaddr, KM_USER0); 143 kunmap_atomic(kaddr, KM_USER0);
144
143 mark_buffer_dirty(path->nodes[0]); 145 mark_buffer_dirty(path->nodes[0]);
144 btrfs_free_path(path); 146 btrfs_free_path(path);
145 } else if (buffer_mapped(bh)) { 147 ret = btrfs_end_transaction(trans, root);
146 /* csum the file data */ 148 BUG_ON(ret);
147 btrfs_csum_file_block(trans, root, inode->i_ino, 149 mutex_unlock(&root->fs_info->fs_mutex);
148 pages[i]->index << PAGE_CACHE_SHIFT,
149 kmap(pages[i]), PAGE_CACHE_SIZE);
150 kunmap(pages[i]);
151 } 150 }
152 SetPageChecked(pages[i]);
153 ret = btrfs_end_transaction(trans, root);
154 BUG_ON(ret);
155 mutex_unlock(&root->fs_info->fs_mutex);
156 151
157 ret = btrfs_commit_write(file, pages[i], offset, 152 ret = btrfs_commit_write(file, pages[i], offset,
158 offset + this_write); 153 offset + this_write);
@@ -503,7 +498,7 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf,
503 if ((pos & (PAGE_CACHE_SIZE - 1))) { 498 if ((pos & (PAGE_CACHE_SIZE - 1))) {
504 pinned[0] = grab_cache_page(inode->i_mapping, first_index); 499 pinned[0] = grab_cache_page(inode->i_mapping, first_index);
505 if (!PageUptodate(pinned[0])) { 500 if (!PageUptodate(pinned[0])) {
506 ret = mpage_readpage(pinned[0], btrfs_get_block); 501 ret = btrfs_readpage(NULL, pinned[0]);
507 BUG_ON(ret); 502 BUG_ON(ret);
508 wait_on_page_locked(pinned[0]); 503 wait_on_page_locked(pinned[0]);
509 } else { 504 } else {
@@ -513,7 +508,7 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf,
513 if ((pos + count) & (PAGE_CACHE_SIZE - 1)) { 508 if ((pos + count) & (PAGE_CACHE_SIZE - 1)) {
514 pinned[1] = grab_cache_page(inode->i_mapping, last_index); 509 pinned[1] = grab_cache_page(inode->i_mapping, last_index);
515 if (!PageUptodate(pinned[1])) { 510 if (!PageUptodate(pinned[1])) {
516 ret = mpage_readpage(pinned[1], btrfs_get_block); 511 ret = btrfs_readpage(NULL, pinned[1]);
517 BUG_ON(ret); 512 BUG_ON(ret);
518 wait_on_page_locked(pinned[1]); 513 wait_on_page_locked(pinned[1]);
519 } else { 514 } else {
@@ -633,138 +628,6 @@ out:
633 return num_written ? num_written : err; 628 return num_written ? num_written : err;
634} 629}
635 630
636/*
637 * FIXME, do this by stuffing the csum we want in the info hanging off
638 * page->private. For now, verify file csums on read
639 */
640static int btrfs_read_actor(read_descriptor_t *desc, struct page *page,
641 unsigned long offset, unsigned long size)
642{
643 char *kaddr;
644 unsigned long left, count = desc->count;
645 struct inode *inode = page->mapping->host;
646
647 if (size > count)
648 size = count;
649
650 if (!PageChecked(page)) {
651 /* FIXME, do it per block */
652 struct btrfs_root *root = BTRFS_I(inode)->root;
653 int ret;
654 struct buffer_head *bh;
655
656 if (page_has_buffers(page)) {
657 bh = page_buffers(page);
658 if (!buffer_mapped(bh)) {
659 SetPageChecked(page);
660 goto checked;
661 }
662 }
663
664 ret = btrfs_csum_verify_file_block(root,
665 page->mapping->host->i_ino,
666 page->index << PAGE_CACHE_SHIFT,
667 kmap(page), PAGE_CACHE_SIZE);
668 if (ret) {
669 if (ret != -ENOENT) {
670 printk("failed to verify ino %lu page %lu ret %d\n",
671 page->mapping->host->i_ino,
672 page->index, ret);
673 memset(page_address(page), 1, PAGE_CACHE_SIZE);
674 flush_dcache_page(page);
675 }
676 }
677 SetPageChecked(page);
678 kunmap(page);
679 }
680checked:
681 /*
682 * Faults on the destination of a read are common, so do it before
683 * taking the kmap.
684 */
685 if (!fault_in_pages_writeable(desc->arg.buf, size)) {
686 kaddr = kmap_atomic(page, KM_USER0);
687 left = __copy_to_user_inatomic(desc->arg.buf,
688 kaddr + offset, size);
689 kunmap_atomic(kaddr, KM_USER0);
690 if (left == 0)
691 goto success;
692 }
693
694 /* Do it the slow way */
695 kaddr = kmap(page);
696 left = __copy_to_user(desc->arg.buf, kaddr + offset, size);
697 kunmap(page);
698
699 if (left) {
700 size -= left;
701 desc->error = -EFAULT;
702 }
703success:
704 desc->count = count - size;
705 desc->written += size;
706 desc->arg.buf += size;
707 return size;
708}
709
710/**
711 * btrfs_file_aio_read - filesystem read routine, with a mod to csum verify
712 * @iocb: kernel I/O control block
713 * @iov: io vector request
714 * @nr_segs: number of segments in the iovec
715 * @pos: current file position
716 */
717static ssize_t btrfs_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
718 unsigned long nr_segs, loff_t pos)
719{
720 struct file *filp = iocb->ki_filp;
721 ssize_t retval;
722 unsigned long seg;
723 size_t count;
724 loff_t *ppos = &iocb->ki_pos;
725
726 count = 0;
727 for (seg = 0; seg < nr_segs; seg++) {
728 const struct iovec *iv = &iov[seg];
729
730 /*
731 * If any segment has a negative length, or the cumulative
732 * length ever wraps negative then return -EINVAL.
733 */
734 count += iv->iov_len;
735 if (unlikely((ssize_t)(count|iv->iov_len) < 0))
736 return -EINVAL;
737 if (access_ok(VERIFY_WRITE, iv->iov_base, iv->iov_len))
738 continue;
739 if (seg == 0)
740 return -EFAULT;
741 nr_segs = seg;
742 count -= iv->iov_len; /* This segment is no good */
743 break;
744 }
745 retval = 0;
746 if (count) {
747 for (seg = 0; seg < nr_segs; seg++) {
748 read_descriptor_t desc;
749
750 desc.written = 0;
751 desc.arg.buf = iov[seg].iov_base;
752 desc.count = iov[seg].iov_len;
753 if (desc.count == 0)
754 continue;
755 desc.error = 0;
756 do_generic_file_read(filp, ppos, &desc,
757 btrfs_read_actor);
758 retval += desc.written;
759 if (desc.error) {
760 retval = retval ?: desc.error;
761 break;
762 }
763 }
764 }
765 return retval;
766}
767
768static int btrfs_sync_file(struct file *file, 631static int btrfs_sync_file(struct file *file,
769 struct dentry *dentry, int datasync) 632 struct dentry *dentry, int datasync)
770{ 633{
@@ -789,12 +652,25 @@ out:
789 return ret > 0 ? EIO : ret; 652 return ret > 0 ? EIO : ret;
790} 653}
791 654
655static struct vm_operations_struct btrfs_file_vm_ops = {
656 .nopage = filemap_nopage,
657 .populate = filemap_populate,
658 .page_mkwrite = btrfs_page_mkwrite,
659};
660
661static int btrfs_file_mmap(struct file *filp, struct vm_area_struct *vma)
662{
663 vma->vm_ops = &btrfs_file_vm_ops;
664 file_accessed(filp);
665 return 0;
666}
667
792struct file_operations btrfs_file_operations = { 668struct file_operations btrfs_file_operations = {
793 .llseek = generic_file_llseek, 669 .llseek = generic_file_llseek,
794 .read = do_sync_read, 670 .read = do_sync_read,
795 .aio_read = btrfs_file_aio_read, 671 .aio_read = generic_file_aio_read,
796 .write = btrfs_file_write, 672 .write = btrfs_file_write,
797 .mmap = generic_file_mmap, 673 .mmap = btrfs_file_mmap,
798 .open = generic_file_open, 674 .open = generic_file_open,
799 .ioctl = btrfs_ioctl, 675 .ioctl = btrfs_ioctl,
800 .fsync = btrfs_sync_file, 676 .fsync = btrfs_sync_file,