aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/coda/coda_fs_i.h1
-rw-r--r--fs/coda/coda_psdev.h3
-rw-r--r--fs/coda/file.c61
-rw-r--r--fs/coda/psdev.c2
-rw-r--r--fs/coda/upcall.c70
5 files changed, 112 insertions, 25 deletions
diff --git a/fs/coda/coda_fs_i.h b/fs/coda/coda_fs_i.h
index c99d574d1c43..1763ff95d865 100644
--- a/fs/coda/coda_fs_i.h
+++ b/fs/coda/coda_fs_i.h
@@ -40,6 +40,7 @@ struct coda_file_info {
40 int cfi_magic; /* magic number */ 40 int cfi_magic; /* magic number */
41 struct file *cfi_container; /* container file for this cnode */ 41 struct file *cfi_container; /* container file for this cnode */
42 unsigned int cfi_mapcount; /* nr of times this file is mapped */ 42 unsigned int cfi_mapcount; /* nr of times this file is mapped */
43 bool cfi_access_intent; /* is access intent supported */
43}; 44};
44 45
45/* flags */ 46/* flags */
diff --git a/fs/coda/coda_psdev.h b/fs/coda/coda_psdev.h
index 801423cbbdfc..52da08c770b0 100644
--- a/fs/coda/coda_psdev.h
+++ b/fs/coda/coda_psdev.h
@@ -83,6 +83,9 @@ int coda_downcall(struct venus_comm *vcp, int opcode, union outputArgs *out,
83 size_t nbytes); 83 size_t nbytes);
84int venus_fsync(struct super_block *sb, struct CodaFid *fid); 84int venus_fsync(struct super_block *sb, struct CodaFid *fid);
85int venus_statfs(struct dentry *dentry, struct kstatfs *sfs); 85int venus_statfs(struct dentry *dentry, struct kstatfs *sfs);
86int venus_access_intent(struct super_block *sb, struct CodaFid *fid,
87 bool *access_intent_supported,
88 size_t count, loff_t ppos, int type);
86 89
87/* 90/*
88 * Statistics 91 * Statistics
diff --git a/fs/coda/file.c b/fs/coda/file.c
index 0dbd13ab72e3..128d63df5bfb 100644
--- a/fs/coda/file.c
+++ b/fs/coda/file.c
@@ -20,6 +20,7 @@
20#include <linux/string.h> 20#include <linux/string.h>
21#include <linux/slab.h> 21#include <linux/slab.h>
22#include <linux/uaccess.h> 22#include <linux/uaccess.h>
23#include <linux/uio.h>
23 24
24#include <linux/coda.h> 25#include <linux/coda.h>
25#include "coda_psdev.h" 26#include "coda_psdev.h"
@@ -37,9 +38,25 @@ static ssize_t
37coda_file_read_iter(struct kiocb *iocb, struct iov_iter *to) 38coda_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
38{ 39{
39 struct file *coda_file = iocb->ki_filp; 40 struct file *coda_file = iocb->ki_filp;
41 struct inode *coda_inode = file_inode(coda_file);
40 struct coda_file_info *cfi = coda_ftoc(coda_file); 42 struct coda_file_info *cfi = coda_ftoc(coda_file);
43 loff_t ki_pos = iocb->ki_pos;
44 size_t count = iov_iter_count(to);
45 ssize_t ret;
46
47 ret = venus_access_intent(coda_inode->i_sb, coda_i2f(coda_inode),
48 &cfi->cfi_access_intent,
49 count, ki_pos, CODA_ACCESS_TYPE_READ);
50 if (ret)
51 goto finish_read;
41 52
42 return vfs_iter_read(cfi->cfi_container, to, &iocb->ki_pos, 0); 53 ret = vfs_iter_read(cfi->cfi_container, to, &iocb->ki_pos, 0);
54
55finish_read:
56 venus_access_intent(coda_inode->i_sb, coda_i2f(coda_inode),
57 &cfi->cfi_access_intent,
58 count, ki_pos, CODA_ACCESS_TYPE_READ_FINISH);
59 return ret;
43} 60}
44 61
45static ssize_t 62static ssize_t
@@ -48,10 +65,17 @@ coda_file_write_iter(struct kiocb *iocb, struct iov_iter *to)
48 struct file *coda_file = iocb->ki_filp; 65 struct file *coda_file = iocb->ki_filp;
49 struct inode *coda_inode = file_inode(coda_file); 66 struct inode *coda_inode = file_inode(coda_file);
50 struct coda_file_info *cfi = coda_ftoc(coda_file); 67 struct coda_file_info *cfi = coda_ftoc(coda_file);
51 struct file *host_file; 68 struct file *host_file = cfi->cfi_container;
69 loff_t ki_pos = iocb->ki_pos;
70 size_t count = iov_iter_count(to);
52 ssize_t ret; 71 ssize_t ret;
53 72
54 host_file = cfi->cfi_container; 73 ret = venus_access_intent(coda_inode->i_sb, coda_i2f(coda_inode),
74 &cfi->cfi_access_intent,
75 count, ki_pos, CODA_ACCESS_TYPE_WRITE);
76 if (ret)
77 goto finish_write;
78
55 file_start_write(host_file); 79 file_start_write(host_file);
56 inode_lock(coda_inode); 80 inode_lock(coda_inode);
57 ret = vfs_iter_write(cfi->cfi_container, to, &iocb->ki_pos, 0); 81 ret = vfs_iter_write(cfi->cfi_container, to, &iocb->ki_pos, 0);
@@ -60,6 +84,11 @@ coda_file_write_iter(struct kiocb *iocb, struct iov_iter *to)
60 coda_inode->i_mtime = coda_inode->i_ctime = current_time(coda_inode); 84 coda_inode->i_mtime = coda_inode->i_ctime = current_time(coda_inode);
61 inode_unlock(coda_inode); 85 inode_unlock(coda_inode);
62 file_end_write(host_file); 86 file_end_write(host_file);
87
88finish_write:
89 venus_access_intent(coda_inode->i_sb, coda_i2f(coda_inode),
90 &cfi->cfi_access_intent,
91 count, ki_pos, CODA_ACCESS_TYPE_WRITE_FINISH);
63 return ret; 92 return ret;
64} 93}
65 94
@@ -94,29 +123,35 @@ coda_vm_close(struct vm_area_struct *vma)
94static int 123static int
95coda_file_mmap(struct file *coda_file, struct vm_area_struct *vma) 124coda_file_mmap(struct file *coda_file, struct vm_area_struct *vma)
96{ 125{
97 struct coda_file_info *cfi; 126 struct inode *coda_inode = file_inode(coda_file);
127 struct coda_file_info *cfi = coda_ftoc(coda_file);
128 struct file *host_file = cfi->cfi_container;
129 struct inode *host_inode = file_inode(host_file);
98 struct coda_inode_info *cii; 130 struct coda_inode_info *cii;
99 struct file *host_file;
100 struct inode *coda_inode, *host_inode;
101 struct coda_vm_ops *cvm_ops; 131 struct coda_vm_ops *cvm_ops;
132 loff_t ppos;
133 size_t count;
102 int ret; 134 int ret;
103 135
104 cfi = coda_ftoc(coda_file);
105 host_file = cfi->cfi_container;
106
107 if (!host_file->f_op->mmap) 136 if (!host_file->f_op->mmap)
108 return -ENODEV; 137 return -ENODEV;
109 138
110 if (WARN_ON(coda_file != vma->vm_file)) 139 if (WARN_ON(coda_file != vma->vm_file))
111 return -EIO; 140 return -EIO;
112 141
142 count = vma->vm_end - vma->vm_start;
143 ppos = vma->vm_pgoff * PAGE_SIZE;
144
145 ret = venus_access_intent(coda_inode->i_sb, coda_i2f(coda_inode),
146 &cfi->cfi_access_intent,
147 count, ppos, CODA_ACCESS_TYPE_MMAP);
148 if (ret)
149 return ret;
150
113 cvm_ops = kmalloc(sizeof(struct coda_vm_ops), GFP_KERNEL); 151 cvm_ops = kmalloc(sizeof(struct coda_vm_ops), GFP_KERNEL);
114 if (!cvm_ops) 152 if (!cvm_ops)
115 return -ENOMEM; 153 return -ENOMEM;
116 154
117 coda_inode = file_inode(coda_file);
118 host_inode = file_inode(host_file);
119
120 cii = ITOC(coda_inode); 155 cii = ITOC(coda_inode);
121 spin_lock(&cii->c_lock); 156 spin_lock(&cii->c_lock);
122 coda_file->f_mapping = host_file->f_mapping; 157 coda_file->f_mapping = host_file->f_mapping;
@@ -188,6 +223,8 @@ int coda_open(struct inode *coda_inode, struct file *coda_file)
188 cfi->cfi_magic = CODA_MAGIC; 223 cfi->cfi_magic = CODA_MAGIC;
189 cfi->cfi_mapcount = 0; 224 cfi->cfi_mapcount = 0;
190 cfi->cfi_container = host_file; 225 cfi->cfi_container = host_file;
226 /* assume access intents are supported unless we hear otherwise */
227 cfi->cfi_access_intent = true;
191 228
192 BUG_ON(coda_file->private_data != NULL); 229 BUG_ON(coda_file->private_data != NULL);
193 coda_file->private_data = cfi; 230 coda_file->private_data = cfi;
diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c
index ebfbbea9fa48..240669f51eac 100644
--- a/fs/coda/psdev.c
+++ b/fs/coda/psdev.c
@@ -388,7 +388,7 @@ MODULE_AUTHOR("Jan Harkes, Peter J. Braam");
388MODULE_DESCRIPTION("Coda Distributed File System VFS interface"); 388MODULE_DESCRIPTION("Coda Distributed File System VFS interface");
389MODULE_ALIAS_CHARDEV_MAJOR(CODA_PSDEV_MAJOR); 389MODULE_ALIAS_CHARDEV_MAJOR(CODA_PSDEV_MAJOR);
390MODULE_LICENSE("GPL"); 390MODULE_LICENSE("GPL");
391MODULE_VERSION("6.11"); 391MODULE_VERSION("7.0");
392 392
393static int __init init_coda(void) 393static int __init init_coda(void)
394{ 394{
diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c
index 15c0e4fdb0e3..eb3b1898da46 100644
--- a/fs/coda/upcall.c
+++ b/fs/coda/upcall.c
@@ -569,6 +569,47 @@ int venus_statfs(struct dentry *dentry, struct kstatfs *sfs)
569 return error; 569 return error;
570} 570}
571 571
572int venus_access_intent(struct super_block *sb, struct CodaFid *fid,
573 bool *access_intent_supported,
574 size_t count, loff_t ppos, int type)
575{
576 union inputArgs *inp;
577 union outputArgs *outp;
578 int insize, outsize, error;
579 bool finalizer =
580 type == CODA_ACCESS_TYPE_READ_FINISH ||
581 type == CODA_ACCESS_TYPE_WRITE_FINISH;
582
583 if (!*access_intent_supported && !finalizer)
584 return 0;
585
586 insize = SIZE(access_intent);
587 UPARG(CODA_ACCESS_INTENT);
588
589 inp->coda_access_intent.VFid = *fid;
590 inp->coda_access_intent.count = count;
591 inp->coda_access_intent.pos = ppos;
592 inp->coda_access_intent.type = type;
593
594 error = coda_upcall(coda_vcp(sb), insize,
595 finalizer ? NULL : &outsize, inp);
596
597 /*
598 * we have to free the request buffer for synchronous upcalls
599 * or when asynchronous upcalls fail, but not when asynchronous
600 * upcalls succeed
601 */
602 if (!finalizer || error)
603 kvfree(inp);
604
605 /* Chunked access is not supported or an old Coda client */
606 if (error == -EOPNOTSUPP) {
607 *access_intent_supported = false;
608 error = 0;
609 }
610 return error;
611}
612
572/* 613/*
573 * coda_upcall and coda_downcall routines. 614 * coda_upcall and coda_downcall routines.
574 */ 615 */
@@ -598,10 +639,12 @@ static void coda_unblock_signals(sigset_t *old)
598 * has seen them, 639 * has seen them,
599 * - CODA_CLOSE or CODA_RELEASE upcall (to avoid reference count problems) 640 * - CODA_CLOSE or CODA_RELEASE upcall (to avoid reference count problems)
600 * - CODA_STORE (to avoid data loss) 641 * - CODA_STORE (to avoid data loss)
642 * - CODA_ACCESS_INTENT (to avoid reference count problems)
601 */ 643 */
602#define CODA_INTERRUPTIBLE(r) (!coda_hard && \ 644#define CODA_INTERRUPTIBLE(r) (!coda_hard && \
603 (((r)->uc_opcode != CODA_CLOSE && \ 645 (((r)->uc_opcode != CODA_CLOSE && \
604 (r)->uc_opcode != CODA_STORE && \ 646 (r)->uc_opcode != CODA_STORE && \
647 (r)->uc_opcode != CODA_ACCESS_INTENT && \
605 (r)->uc_opcode != CODA_RELEASE) || \ 648 (r)->uc_opcode != CODA_RELEASE) || \
606 (r)->uc_flags & CODA_REQ_READ)) 649 (r)->uc_flags & CODA_REQ_READ))
607 650
@@ -687,21 +730,25 @@ static int coda_upcall(struct venus_comm *vcp,
687 goto exit; 730 goto exit;
688 } 731 }
689 732
733 buffer->ih.unique = ++vcp->vc_seq;
734
690 req->uc_data = (void *)buffer; 735 req->uc_data = (void *)buffer;
691 req->uc_flags = 0; 736 req->uc_flags = outSize ? 0 : CODA_REQ_ASYNC;
692 req->uc_inSize = inSize; 737 req->uc_inSize = inSize;
693 req->uc_outSize = *outSize ? *outSize : inSize; 738 req->uc_outSize = (outSize && *outSize) ? *outSize : inSize;
694 req->uc_opcode = ((union inputArgs *)buffer)->ih.opcode; 739 req->uc_opcode = buffer->ih.opcode;
695 req->uc_unique = ++vcp->vc_seq; 740 req->uc_unique = buffer->ih.unique;
696 init_waitqueue_head(&req->uc_sleep); 741 init_waitqueue_head(&req->uc_sleep);
697 742
698 /* Fill in the common input args. */
699 ((union inputArgs *)buffer)->ih.unique = req->uc_unique;
700
701 /* Append msg to pending queue and poke Venus. */ 743 /* Append msg to pending queue and poke Venus. */
702 list_add_tail(&req->uc_chain, &vcp->vc_pending); 744 list_add_tail(&req->uc_chain, &vcp->vc_pending);
703
704 wake_up_interruptible(&vcp->vc_waitq); 745 wake_up_interruptible(&vcp->vc_waitq);
746
747 if (req->uc_flags & CODA_REQ_ASYNC) {
748 mutex_unlock(&vcp->vc_mutex);
749 return 0;
750 }
751
705 /* We can be interrupted while we wait for Venus to process 752 /* We can be interrupted while we wait for Venus to process
706 * our request. If the interrupt occurs before Venus has read 753 * our request. If the interrupt occurs before Venus has read
707 * the request, we dequeue and return. If it occurs after the 754 * the request, we dequeue and return. If it occurs after the
@@ -743,20 +790,20 @@ static int coda_upcall(struct venus_comm *vcp,
743 sig_req = kmalloc(sizeof(struct upc_req), GFP_KERNEL); 790 sig_req = kmalloc(sizeof(struct upc_req), GFP_KERNEL);
744 if (!sig_req) goto exit; 791 if (!sig_req) goto exit;
745 792
746 sig_req->uc_data = kvzalloc(sizeof(struct coda_in_hdr), GFP_KERNEL); 793 sig_inputArgs = kvzalloc(sizeof(struct coda_in_hdr), GFP_KERNEL);
747 if (!sig_req->uc_data) { 794 if (!sig_inputArgs) {
748 kfree(sig_req); 795 kfree(sig_req);
749 goto exit; 796 goto exit;
750 } 797 }
751 798
752 error = -EINTR; 799 error = -EINTR;
753 sig_inputArgs = (union inputArgs *)sig_req->uc_data;
754 sig_inputArgs->ih.opcode = CODA_SIGNAL; 800 sig_inputArgs->ih.opcode = CODA_SIGNAL;
755 sig_inputArgs->ih.unique = req->uc_unique; 801 sig_inputArgs->ih.unique = req->uc_unique;
756 802
757 sig_req->uc_flags = CODA_REQ_ASYNC; 803 sig_req->uc_flags = CODA_REQ_ASYNC;
758 sig_req->uc_opcode = sig_inputArgs->ih.opcode; 804 sig_req->uc_opcode = sig_inputArgs->ih.opcode;
759 sig_req->uc_unique = sig_inputArgs->ih.unique; 805 sig_req->uc_unique = sig_inputArgs->ih.unique;
806 sig_req->uc_data = (void *)sig_inputArgs;
760 sig_req->uc_inSize = sizeof(struct coda_in_hdr); 807 sig_req->uc_inSize = sizeof(struct coda_in_hdr);
761 sig_req->uc_outSize = sizeof(struct coda_in_hdr); 808 sig_req->uc_outSize = sizeof(struct coda_in_hdr);
762 809
@@ -911,4 +958,3 @@ unlock_out:
911 iput(inode); 958 iput(inode);
912 return 0; 959 return 0;
913} 960}
914