Import 2.3.25pre1
[davej-history.git] / fs / coda / file.c
blob378c4f7a6b04d06b70511e29a860ddd3fd643a55
1 /*
2 * File operations for Coda.
3 * Original version: (C) 1996 Peter Braam
4 * Rewritten for Linux 2.1: (C) 1997 Carnegie Mellon University
6 * Carnegie Mellon encourages users of this code to contribute improvements
7 * to the Coda project. Contact Peter Braam <coda@cs.cmu.edu>.
8 */
10 #include <linux/types.h>
11 #include <linux/kernel.h>
12 #include <linux/sched.h>
13 #include <linux/fs.h>
14 #include <linux/stat.h>
15 #include <linux/errno.h>
16 #include <linux/locks.h>
17 #include <asm/segment.h>
18 #include <linux/string.h>
19 #include <asm/uaccess.h>
21 #include <linux/coda.h>
22 #include <linux/coda_linux.h>
23 #include <linux/coda_fs_i.h>
24 #include <linux/coda_psdev.h>
25 #include <linux/coda_cache.h>
26 #include <linux/coda_proc.h>
28 /* file operations */
29 static int coda_readpage(struct file *file, struct page * page);
30 static ssize_t coda_file_read(struct file *f, char *buf, size_t count, loff_t *off);
31 static ssize_t coda_file_write(struct file *f, const char *buf, size_t count, loff_t *off);
32 static int coda_file_mmap(struct file * file, struct vm_area_struct * vma);
34 /* also exported from this file (used for dirs) */
35 int coda_fsync(struct file *, struct dentry *dentry);
37 struct inode_operations coda_file_inode_operations = {
38 &coda_file_operations, /* default file operations */
39 NULL, /* create */
40 NULL, /* lookup */
41 NULL, /* link */
42 NULL, /* unlink */
43 NULL, /* symlink */
44 NULL, /* mkdir */
45 NULL, /* rmdir */
46 NULL, /* mknod */
47 NULL, /* rename */
48 NULL, /* readlink */
49 NULL, /* follow_link */
50 NULL, /* get_block */
51 coda_readpage, /* readpage */
52 NULL, /* writepage */
53 NULL, /* flushpage */
54 NULL, /* truncate */
55 coda_permission, /* permission */
56 NULL, /* smap */
57 coda_revalidate_inode /* revalidate */
60 struct file_operations coda_file_operations = {
61 NULL, /* lseek - default should work for coda */
62 coda_file_read, /* read */
63 coda_file_write, /* write */
64 NULL, /* readdir */
65 NULL, /* select - default */
66 NULL, /* ioctl */
67 coda_file_mmap, /* mmap */
68 coda_open, /* open */
69 NULL,
70 coda_release, /* release */
71 coda_fsync, /* fsync */
72 NULL, /* fasync */
73 NULL, /* check_media_change */
74 NULL, /* revalidate */
75 NULL /* lock */
78 /* File file operations */
79 static int coda_readpage(struct file * coda_file, struct page * page)
81 struct dentry *de = coda_file->f_dentry;
82 struct inode *coda_inode = de->d_inode;
83 struct dentry cont_dentry;
84 struct file cont_file;
85 struct coda_inode_info *cii;
87 ENTRY;
88 coda_vfs_stat.readpage++;
90 cii = ITOC(coda_inode);
92 if ( ! cii->c_ovp ) {
93 printk("coda_readpage: no open inode for ino %ld, %s\n",
94 coda_inode->i_ino, de->d_name.name);
95 return -ENXIO;
98 coda_prepare_openfile(coda_inode, coda_file, cii->c_ovp,
99 &cont_file, &cont_dentry);
101 CDEBUG(D_INODE, "coda ino: %ld, cached ino %ld, page offset: %lx\n",
102 coda_inode->i_ino, cii->c_ovp->i_ino, page->offset);
104 block_read_full_page(&cont_file, page);
105 EXIT;
106 return 0;
109 static int coda_file_mmap(struct file * file, struct vm_area_struct * vma)
111 struct coda_inode_info *cii;
112 int res;
114 coda_vfs_stat.file_mmap++;
116 ENTRY;
117 cii = ITOC(file->f_dentry->d_inode);
118 cii->c_mmcount++;
120 res =generic_file_mmap(file, vma);
121 EXIT;
122 return res;
125 static ssize_t coda_file_read(struct file *coda_file, char *buff,
126 size_t count, loff_t *ppos)
128 struct coda_inode_info *cnp;
129 struct inode *coda_inode = coda_file->f_dentry->d_inode;
130 struct inode *cont_inode = NULL;
131 struct file cont_file;
132 struct dentry cont_dentry;
133 int result = 0;
135 ENTRY;
136 coda_vfs_stat.file_read++;
138 cnp = ITOC(coda_inode);
139 CHECK_CNODE(cnp);
141 cont_inode = cnp->c_ovp;
142 if ( cont_inode == NULL ) {
143 printk("coda_file_read: cached inode is 0!\n");
144 return -1;
147 coda_prepare_openfile(coda_inode, coda_file, cont_inode,
148 &cont_file, &cont_dentry);
150 if (!cont_file.f_op || ! cont_file.f_op->read) {
151 printk( "container file has no read in file operations.\n");
152 return -1;
155 result = cont_file.f_op->read(&cont_file , buff, count,
156 &(cont_file.f_pos));
158 CDEBUG(D_FILE, "ops at %p result %d, count %ld, position: %d\n",
159 cont_file.f_op, result, (long)count, (int)cont_file.f_pos);
161 coda_restore_codafile(coda_inode, coda_file, cont_inode, &cont_file);
162 return result;
166 static ssize_t coda_file_write(struct file *coda_file, const char *buff,
167 size_t count, loff_t *ppos)
169 struct coda_inode_info *cnp;
170 struct inode *coda_inode = coda_file->f_dentry->d_inode;
171 struct inode *cont_inode = NULL;
172 struct file cont_file;
173 struct dentry cont_dentry;
174 int result = 0;
176 ENTRY;
177 coda_vfs_stat.file_write++;
179 cnp = ITOC(coda_inode);
180 CHECK_CNODE(cnp);
182 cont_inode = cnp->c_ovp;
183 if ( cont_inode == NULL ) {
184 printk("coda_file_write: cached inode is 0!\n");
185 return -1;
188 coda_prepare_openfile(coda_inode, coda_file, cont_inode,
189 &cont_file, &cont_dentry);
191 if (!cont_file.f_op || !cont_file.f_op->write) {
192 printk("coda_file_write: container file has no file ops.\n");
193 return -1;
196 down(&cont_inode->i_sem);
197 result = cont_file.f_op->write(&cont_file , buff, count,
198 &(cont_file.f_pos));
199 up(&cont_inode->i_sem);
200 coda_restore_codafile(coda_inode, coda_file, cont_inode, &cont_file);
202 if (result)
203 cnp->c_flags |= C_VATTR;
205 return result;
208 int coda_fsync(struct file *coda_file, struct dentry *coda_dentry)
210 struct coda_inode_info *cnp;
211 struct inode *coda_inode = coda_dentry->d_inode;
212 struct inode *cont_inode = NULL;
213 struct file cont_file;
214 struct dentry cont_dentry;
215 int result = 0;
216 ENTRY;
217 coda_vfs_stat.fsync++;
219 if (!(S_ISREG(coda_inode->i_mode) || S_ISDIR(coda_inode->i_mode) ||
220 S_ISLNK(coda_inode->i_mode)))
221 return -EINVAL;
223 cnp = ITOC(coda_inode);
224 CHECK_CNODE(cnp);
226 cont_inode = cnp->c_ovp;
227 if ( cont_inode == NULL ) {
228 printk("coda_file_write: cached inode is 0!\n");
229 return -1;
232 coda_prepare_openfile(coda_inode, coda_file, cont_inode,
233 &cont_file, &cont_dentry);
235 down(&cont_inode->i_sem);
237 result = file_fsync(&cont_file ,&cont_dentry);
238 if ( result == 0 ) {
239 result = venus_fsync(coda_inode->i_sb, &(cnp->c_fid));
242 up(&cont_inode->i_sem);
244 coda_restore_codafile(coda_inode, coda_file, cont_inode, &cont_file);
245 return result;
248 * support routines
251 /* instantiate the container file and dentry object to do io */
252 void coda_prepare_openfile(struct inode *i, struct file *coda_file,
253 struct inode *cont_inode, struct file *cont_file,
254 struct dentry *cont_dentry)
256 cont_file->f_pos = coda_file->f_pos;
257 cont_file->f_mode = coda_file->f_mode;
258 cont_file->f_flags = coda_file->f_flags;
259 atomic_set(&cont_file->f_count, atomic_read(&coda_file->f_count));
260 cont_file->f_owner = coda_file->f_owner;
261 cont_file->f_op = cont_inode->i_op->default_file_ops;
262 cont_file->f_dentry = cont_dentry;
263 cont_file->f_dentry->d_inode = cont_inode;
264 return ;
267 /* update the Coda file & inode after I/O */
268 void coda_restore_codafile(struct inode *coda_inode, struct file *coda_file,
269 struct inode *open_inode, struct file *open_file)
271 coda_file->f_pos = open_file->f_pos;
272 /* XXX what about setting the mtime here too? */
273 /* coda_inode->i_mtime = open_inode->i_mtime; */
274 coda_inode->i_size = open_inode->i_size;
275 return;
278 /* grab the ext2 inode of the container file */
279 int coda_inode_grab(dev_t dev, ino_t ino, struct inode **ind)
281 struct super_block *sbptr;
283 sbptr = get_super(dev);
285 if ( !sbptr ) {
286 printk("coda_inode_grab: coda_find_super returns NULL.\n");
287 return -ENXIO;
290 *ind = NULL;
291 *ind = iget(sbptr, ino);
293 if ( *ind == NULL ) {
294 printk("coda_inode_grab: iget(dev: %d, ino: %ld)
295 returns NULL.\n", dev, (long)ino);
296 return -ENOENT;
298 CDEBUG(D_FILE, "ino: %ld, ops at %p\n", (long)ino, (*ind)->i_op);
299 return 0;