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>.
10 #include <linux/types.h>
11 #include <linux/kernel.h>
12 #include <linux/time.h>
13 #include <linux/file.h>
15 #include <linux/stat.h>
16 #include <linux/errno.h>
17 #include <linux/smp_lock.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>
29 coda_file_read(struct file
*coda_file
, char __user
*buf
, size_t count
, loff_t
*ppos
)
31 struct coda_file_info
*cfi
;
32 struct file
*host_file
;
34 cfi
= CODA_FTOC(coda_file
);
35 BUG_ON(!cfi
|| cfi
->cfi_magic
!= CODA_MAGIC
);
36 host_file
= cfi
->cfi_container
;
38 if (!host_file
->f_op
|| !host_file
->f_op
->read
)
41 return host_file
->f_op
->read(host_file
, buf
, count
, ppos
);
45 coda_file_splice_read(struct file
*coda_file
, loff_t
*ppos
,
46 struct pipe_inode_info
*pipe
, size_t count
,
49 struct coda_file_info
*cfi
;
50 struct file
*host_file
;
52 cfi
= CODA_FTOC(coda_file
);
53 BUG_ON(!cfi
|| cfi
->cfi_magic
!= CODA_MAGIC
);
54 host_file
= cfi
->cfi_container
;
56 if (!host_file
->f_op
|| !host_file
->f_op
->splice_read
)
59 return host_file
->f_op
->splice_read(host_file
, ppos
, pipe
, count
,flags
);
63 coda_file_write(struct file
*coda_file
, const char __user
*buf
, size_t count
, loff_t
*ppos
)
65 struct inode
*host_inode
, *coda_inode
= coda_file
->f_path
.dentry
->d_inode
;
66 struct coda_file_info
*cfi
;
67 struct file
*host_file
;
70 cfi
= CODA_FTOC(coda_file
);
71 BUG_ON(!cfi
|| cfi
->cfi_magic
!= CODA_MAGIC
);
72 host_file
= cfi
->cfi_container
;
74 if (!host_file
->f_op
|| !host_file
->f_op
->write
)
77 host_inode
= host_file
->f_path
.dentry
->d_inode
;
78 mutex_lock(&coda_inode
->i_mutex
);
80 ret
= host_file
->f_op
->write(host_file
, buf
, count
, ppos
);
82 coda_inode
->i_size
= host_inode
->i_size
;
83 coda_inode
->i_blocks
= (coda_inode
->i_size
+ 511) >> 9;
84 coda_inode
->i_mtime
= coda_inode
->i_ctime
= CURRENT_TIME_SEC
;
85 mutex_unlock(&coda_inode
->i_mutex
);
91 coda_file_mmap(struct file
*coda_file
, struct vm_area_struct
*vma
)
93 struct coda_file_info
*cfi
;
94 struct coda_inode_info
*cii
;
95 struct file
*host_file
;
96 struct inode
*coda_inode
, *host_inode
;
98 cfi
= CODA_FTOC(coda_file
);
99 BUG_ON(!cfi
|| cfi
->cfi_magic
!= CODA_MAGIC
);
100 host_file
= cfi
->cfi_container
;
102 if (!host_file
->f_op
|| !host_file
->f_op
->mmap
)
105 coda_inode
= coda_file
->f_path
.dentry
->d_inode
;
106 host_inode
= host_file
->f_path
.dentry
->d_inode
;
107 coda_file
->f_mapping
= host_file
->f_mapping
;
108 if (coda_inode
->i_mapping
== &coda_inode
->i_data
)
109 coda_inode
->i_mapping
= host_inode
->i_mapping
;
111 /* only allow additional mmaps as long as userspace isn't changing
112 * the container file on us! */
113 else if (coda_inode
->i_mapping
!= host_inode
->i_mapping
)
116 /* keep track of how often the coda_inode/host_file has been mmapped */
117 cii
= ITOC(coda_inode
);
121 return host_file
->f_op
->mmap(host_file
, vma
);
124 int coda_open(struct inode
*coda_inode
, struct file
*coda_file
)
126 struct file
*host_file
= NULL
;
128 unsigned short flags
= coda_file
->f_flags
& (~O_EXCL
);
129 unsigned short coda_flags
= coda_flags_to_cflags(flags
);
130 struct coda_file_info
*cfi
;
132 cfi
= kmalloc(sizeof(struct coda_file_info
), GFP_KERNEL
);
138 error
= venus_open(coda_inode
->i_sb
, coda_i2f(coda_inode
), coda_flags
,
149 host_file
->f_flags
|= coda_file
->f_flags
& (O_APPEND
| O_SYNC
);
151 cfi
->cfi_magic
= CODA_MAGIC
;
152 cfi
->cfi_mapcount
= 0;
153 cfi
->cfi_container
= host_file
;
155 BUG_ON(coda_file
->private_data
!= NULL
);
156 coda_file
->private_data
= cfi
;
162 int coda_release(struct inode
*coda_inode
, struct file
*coda_file
)
164 unsigned short flags
= (coda_file
->f_flags
) & (~O_EXCL
);
165 unsigned short coda_flags
= coda_flags_to_cflags(flags
);
166 struct coda_file_info
*cfi
;
167 struct coda_inode_info
*cii
;
168 struct inode
*host_inode
;
173 cfi
= CODA_FTOC(coda_file
);
174 BUG_ON(!cfi
|| cfi
->cfi_magic
!= CODA_MAGIC
);
176 err
= venus_close(coda_inode
->i_sb
, coda_i2f(coda_inode
),
177 coda_flags
, coda_file
->f_uid
);
179 host_inode
= cfi
->cfi_container
->f_path
.dentry
->d_inode
;
180 cii
= ITOC(coda_inode
);
182 /* did we mmap this file? */
183 if (coda_inode
->i_mapping
== &host_inode
->i_data
) {
184 cii
->c_mapcount
-= cfi
->cfi_mapcount
;
185 if (!cii
->c_mapcount
)
186 coda_inode
->i_mapping
= &coda_inode
->i_data
;
189 fput(cfi
->cfi_container
);
190 kfree(coda_file
->private_data
);
191 coda_file
->private_data
= NULL
;
195 /* VFS fput ignores the return value from file_operations->release, so
196 * there is no use returning an error here */
200 int coda_fsync(struct file
*coda_file
, struct dentry
*coda_dentry
, int datasync
)
202 struct file
*host_file
;
203 struct dentry
*host_dentry
;
204 struct inode
*host_inode
, *coda_inode
= coda_dentry
->d_inode
;
205 struct coda_file_info
*cfi
;
208 if (!(S_ISREG(coda_inode
->i_mode
) || S_ISDIR(coda_inode
->i_mode
) ||
209 S_ISLNK(coda_inode
->i_mode
)))
212 cfi
= CODA_FTOC(coda_file
);
213 BUG_ON(!cfi
|| cfi
->cfi_magic
!= CODA_MAGIC
);
214 host_file
= cfi
->cfi_container
;
216 if (host_file
->f_op
&& host_file
->f_op
->fsync
) {
217 host_dentry
= host_file
->f_path
.dentry
;
218 host_inode
= host_dentry
->d_inode
;
219 mutex_lock(&host_inode
->i_mutex
);
220 err
= host_file
->f_op
->fsync(host_file
, host_dentry
, datasync
);
221 mutex_unlock(&host_inode
->i_mutex
);
224 if ( !err
&& !datasync
) {
226 err
= venus_fsync(coda_inode
->i_sb
, coda_i2f(coda_inode
));
233 const struct file_operations coda_file_operations
= {
234 .llseek
= generic_file_llseek
,
235 .read
= coda_file_read
,
236 .write
= coda_file_write
,
237 .mmap
= coda_file_mmap
,
239 .release
= coda_release
,
241 .splice_read
= coda_file_splice_read
,