Whamcloud - gitweb
62352351a50a8df3aefdae1348c818185ae4aae7
[fs/lustre-release.git] / lustre / smfs / file.c
1 /*
2  * file.c
3  */
4
5 #define DEBUG_SUBSYSTEM S_SM
6
7 #include <linux/module.h>
8 #include <linux/kernel.h>
9 #include <linux/string.h>
10 #include <linux/slab.h>
11 #include <linux/stat.h>
12 #include <linux/unistd.h>
13 #include <linux/pagemap.h>
14 #include "smfs_internal.h" 
15         
16 /* instantiate a file handle to the cache file */
17 void smfs_prepare_cachefile(struct inode *inode,
18                             struct file *file, 
19                             struct inode *cache_inode,
20                             struct file *cache_file,
21                             struct dentry *cache_dentry)
22 {
23         ENTRY;
24         cache_file->f_pos = file->f_pos;
25         cache_file->f_mode = file->f_mode;
26         cache_file->f_flags = file->f_flags;
27         cache_file->f_count  = file->f_count;
28         cache_file->f_owner  = file->f_owner;
29         cache_file->f_error = file->f_error;
30         cache_file->f_op = inode->i_fop;
31         cache_file->f_dentry = cache_dentry;
32         cache_file->f_dentry->d_inode = cache_inode;
33         cache_file->f_vfsmnt = file->f_vfsmnt;
34         cache_file->private_data = file->private_data;
35         cache_file->f_it = file->f_it;
36         cache_file->f_reada = file->f_reada;
37         cache_file->f_ramax = file->f_ramax;
38         cache_file->f_raend = file->f_raend;
39         cache_file->f_ralen = file->f_ralen;
40         cache_file->f_rawin = file->f_rawin;
41         EXIT;
42 }
43 /* update file structs*/
44 void smfs_update_file(struct file *file, 
45                       struct file *cache_file)
46 {
47         ENTRY;
48         file->f_pos = cache_file->f_pos;
49         file->f_mode = cache_file->f_mode;
50         file->f_flags = cache_file->f_flags;
51         file->f_count  = cache_file->f_count;
52         file->f_owner  = cache_file->f_owner;
53         file->f_reada = cache_file->f_reada;
54         file->f_ramax = cache_file->f_ramax;
55         file->f_raend = cache_file->f_raend;
56         file->f_ralen = cache_file->f_ralen;
57         file->f_rawin = cache_file->f_rawin;
58         EXIT;
59 }
60
61 static ssize_t smfs_write (struct file *filp, const char *buf, 
62                            size_t count, loff_t *ppos)
63 {
64         struct  inode *cache_inode;
65         struct  dentry *dentry = filp->f_dentry;
66         struct  inode *inode = dentry->d_inode;
67         struct  file open_file;
68         struct  dentry open_dentry;
69         loff_t  tmp_ppos;
70         loff_t  *cache_ppos;
71         int     rc = 0;
72         
73         ENTRY;
74         
75         cache_inode = I2CI(inode);
76  
77         if (!cache_inode)
78                 RETURN(-ENOENT);
79         
80         if (ppos != &(filp->f_pos)) {
81                 cache_ppos = &tmp_ppos; 
82         } else {
83                 cache_ppos = &open_file.f_pos; 
84         }
85         *cache_ppos = *ppos;
86         
87         smfs_prepare_cachefile(inode, filp, cache_inode, 
88                                &open_file, &open_dentry);
89         if (cache_inode->i_fop->write)
90                 rc = cache_inode->i_fop->write(&open_file, buf, count, cache_ppos);
91         
92         *ppos = *cache_ppos;
93         duplicate_inode(cache_inode, inode);
94         smfs_update_file(filp, &open_file);
95
96         RETURN(rc);
97 }
98
99 int smfs_ioctl(struct inode * inode, struct file * filp, 
100                unsigned int cmd, unsigned long arg)
101 {
102         struct  inode *cache_inode;
103         struct  dentry *dentry = filp->f_dentry;
104         struct  file open_file;
105         struct  dentry open_dentry;
106         ssize_t rc = 0;
107         
108         ENTRY;
109         
110         cache_inode = I2CI(dentry->d_inode);
111         if (!cache_inode)
112                 RETURN(-ENOENT);
113
114         smfs_prepare_cachefile(inode, filp, cache_inode, 
115                                &open_file, &open_dentry);
116         
117         if (cache_inode->i_fop->ioctl)
118                 rc = cache_inode->i_fop->ioctl(cache_inode, &open_file, cmd, arg);
119                 
120         duplicate_inode(cache_inode, inode);
121         smfs_update_file(filp, &open_file);
122         RETURN(rc);
123 }
124
125 static ssize_t smfs_read (struct file *filp, char *buf, 
126                           size_t count, loff_t *ppos)
127 {
128         struct  inode *cache_inode;
129         struct  dentry *dentry = filp->f_dentry;
130         struct  inode *inode = dentry->d_inode;
131         struct  file open_file;
132         struct  dentry open_dentry;
133         loff_t  tmp_ppos;
134         loff_t  *cache_ppos;
135         ssize_t rc = 0;
136         
137         ENTRY;
138         
139         cache_inode = I2CI(dentry->d_inode);
140         if (!cache_inode)
141                 RETURN(-ENOENT);
142
143         if (ppos != &(filp->f_pos)) {
144                 cache_ppos = &tmp_ppos; 
145         } else {
146                 cache_ppos = &open_file.f_pos; 
147         }
148         *cache_ppos = *ppos;
149         
150         
151         smfs_prepare_cachefile(inode, filp, cache_inode, 
152                                &open_file, &open_dentry);
153
154         
155         if (cache_inode->i_fop->read)
156                 rc = cache_inode->i_fop->read(&open_file, buf, count, cache_ppos);
157     
158         *ppos = *cache_ppos;
159         duplicate_inode(cache_inode, inode);
160         smfs_update_file(filp, &open_file);
161         RETURN(rc);
162 }
163
164 static loff_t smfs_llseek(struct file *file, 
165                           loff_t offset, 
166                           int origin)
167 {
168         struct  inode *cache_inode;
169         struct  dentry *dentry = file->f_dentry;
170         struct  file open_file;
171         struct  dentry open_dentry;
172         ssize_t rc = 0;
173         
174         ENTRY;
175         
176         cache_inode = I2CI(dentry->d_inode);
177         if (!cache_inode)
178                 RETURN(-ENOENT);
179
180         smfs_prepare_cachefile(dentry->d_inode, file, cache_inode, 
181                                &open_file, &open_dentry);
182         
183         if (cache_inode->i_fop->llseek)
184                 rc = cache_inode->i_fop->llseek(&open_file, offset, origin);
185
186         duplicate_inode(cache_inode, dentry->d_inode);
187         smfs_update_file(file, &open_file);
188                 
189         RETURN(rc);
190 }
191
192 static int smfs_mmap(struct file * file, struct vm_area_struct * vma)
193 {
194         struct inode *inode = file->f_dentry->d_inode;
195         struct inode *cache_inode = NULL;
196         struct  file open_file;
197         struct  dentry open_dentry;
198         int    rc = 0;
199
200         cache_inode = I2CI(inode);
201         if (!cache_inode)
202                 RETURN(-ENOENT);
203
204         smfs_prepare_cachefile(inode, file, cache_inode, 
205                                &open_file, &open_dentry);
206   
207         if (cache_inode->i_mapping == &cache_inode->i_data)
208                 inode->i_mapping = cache_inode->i_mapping;
209
210         if (cache_inode->i_fop->mmap)
211                 rc = cache_inode->i_fop->mmap(&open_file, vma);
212       
213         duplicate_inode(cache_inode, inode);
214         smfs_update_file(file, &open_file);
215         
216         RETURN(rc);
217 }
218
219 static int smfs_open(struct inode * inode, struct file * filp)
220 {
221         struct inode *cache_inode = NULL;
222         struct  file open_file;
223         struct  dentry open_dentry;
224         int    rc = 0;
225
226         cache_inode = I2CI(inode);
227         if (!cache_inode)
228                 RETURN(-ENOENT);
229
230         smfs_prepare_cachefile(inode, filp, cache_inode, 
231                                &open_file, &open_dentry);
232         
233         if (cache_inode->i_fop->open)
234                 rc = cache_inode->i_fop->open(cache_inode, &open_file);
235         
236         duplicate_inode(cache_inode, inode);
237         smfs_update_file(filp, &open_file);
238         
239         RETURN(rc);
240
241 }
242 static int smfs_release(struct inode * inode, struct file * filp)
243 {
244         struct inode *cache_inode = NULL;
245         struct  file open_file;
246         struct  dentry open_dentry;
247         int    rc = 0;
248
249         cache_inode = I2CI(inode);
250         if (!cache_inode)
251                 RETURN(-ENOENT);
252         
253         smfs_prepare_cachefile(inode, filp, cache_inode, 
254                                &open_file, &open_dentry);
255
256         if (cache_inode->i_fop->release)
257                 rc = cache_inode->i_fop->release(cache_inode, &open_file);
258
259         duplicate_inode(cache_inode, inode);
260         smfs_update_file(filp, &open_file);
261         
262         RETURN(rc);
263 }
264 int smfs_fsync(struct file * file, 
265                       struct dentry *dentry, 
266                       int datasync)
267 {
268         struct inode *inode = dentry->d_inode;
269         struct inode *cache_inode;
270         struct  file open_file;
271         struct  dentry open_dentry;
272         int    rc = 0;
273
274         cache_inode = I2CI(inode);
275         if (!cache_inode)
276                 RETURN(-ENOENT);
277         
278         smfs_prepare_cachefile(inode, file, cache_inode, 
279                                &open_file, &open_dentry);
280
281         if (cache_inode->i_fop->fsync)
282                 rc = cache_inode->i_fop->fsync(&open_file, &open_dentry, datasync);
283         
284         duplicate_inode(cache_inode, inode);
285         smfs_update_file(file, &open_file);
286         
287         RETURN(rc);
288 }
289
290 struct file_operations smfs_file_fops = {
291         llseek:         smfs_llseek,
292         read:           smfs_read,
293         write:          smfs_write,
294         ioctl:          smfs_ioctl,
295         mmap:           smfs_mmap,
296         open:           smfs_open,
297         release:        smfs_release,
298         fsync:          smfs_fsync,
299 };
300
301 static void smfs_prepare_cache_dentry(struct dentry *dentry, struct inode *inode)
302 {
303         atomic_set(&dentry->d_count, 1);
304         dentry->d_vfs_flags = 0;
305         dentry->d_flags = 0;
306         dentry->d_inode = inode;
307         dentry->d_op = NULL;
308         dentry->d_fsdata = NULL;
309         dentry->d_mounted = 0;
310         INIT_LIST_HEAD(&dentry->d_hash);
311         INIT_LIST_HEAD(&dentry->d_lru);
312         INIT_LIST_HEAD(&dentry->d_subdirs);
313         INIT_LIST_HEAD(&dentry->d_alias);
314 }
315
316 static void smfs_truncate(struct inode * inode)      
317 {
318         struct  inode *cache_inode;
319
320         cache_inode = I2CI(inode);
321
322         if (!cache_inode)
323                 return;
324         
325         if (cache_inode->i_op->truncate)
326                 cache_inode->i_op->truncate(cache_inode);
327
328         duplicate_inode(inode, cache_inode);            
329         
330         return; 
331
332  
333 int smfs_setattr(struct dentry *dentry, struct iattr *attr)      
334 {
335         struct  inode *cache_inode;
336         struct  dentry open_dentry;
337
338         int     rc = 0;
339
340         cache_inode = I2CI(dentry->d_inode);
341
342         if (!cache_inode) 
343                 RETURN(-ENOENT);
344         smfs_prepare_cache_dentry(&open_dentry, cache_inode);
345         
346         if (cache_inode->i_op->setattr)
347                 rc = cache_inode->i_op->setattr(&open_dentry, attr);
348
349         duplicate_inode(cache_inode, dentry->d_inode);          
350         
351         RETURN(rc);
352
353   
354 int smfs_setxattr(struct dentry *dentry, const char *name,
355                   const void *value, size_t size, int flags)
356 {
357         struct  inode *cache_inode;
358         struct  dentry open_dentry;
359         int     rc = 0;
360
361         cache_inode = I2CI(dentry->d_inode);
362
363         if (!cache_inode) 
364                 RETURN(-ENOENT);
365
366         smfs_prepare_cache_dentry(&open_dentry, cache_inode);
367         
368         if (cache_inode->i_op->setattr)
369                 rc = cache_inode->i_op->setxattr(&open_dentry, name, value, size, flags);
370
371         duplicate_inode(cache_inode, dentry->d_inode);          
372         RETURN(rc);
373
374                         
375 int smfs_getxattr(struct dentry *dentry, const char *name,
376                   void *buffer, size_t size)
377 {
378         struct  inode *cache_inode;
379         struct  dentry open_dentry;
380         int     rc = 0;
381
382         cache_inode = I2CI(dentry->d_inode);
383
384         if (!cache_inode) 
385                 RETURN(-ENOENT);
386
387         smfs_prepare_cache_dentry(&open_dentry, cache_inode);
388         
389         if (cache_inode->i_op->setattr)
390                 rc = cache_inode->i_op->getxattr(&open_dentry, name, buffer, size);
391
392         duplicate_inode(cache_inode, dentry->d_inode);          
393         RETURN(rc);
394 }
395
396 ssize_t smfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
397 {
398         struct  inode *cache_inode;
399         struct  dentry open_dentry;
400         int     rc = 0;
401
402         cache_inode = I2CI(dentry->d_inode);
403
404         if (!cache_inode) 
405                 RETURN(-ENOENT);
406
407         smfs_prepare_cache_dentry(&open_dentry, cache_inode);
408         
409         if (cache_inode->i_op->listxattr)
410                 rc = cache_inode->i_op->listxattr(&open_dentry, buffer, size);
411
412         duplicate_inode(cache_inode, dentry->d_inode);          
413         RETURN(rc);
414 }                                                                                                                                                           
415
416 int smfs_removexattr(struct dentry *dentry, const char *name)
417 {
418         struct  inode *cache_inode;
419         struct  dentry open_dentry;
420         int     rc = 0;
421
422         cache_inode = I2CI(dentry->d_inode);
423
424         if (!cache_inode) 
425                 RETURN(-ENOENT);
426
427         smfs_prepare_cache_dentry(&open_dentry, cache_inode);
428         
429         if (cache_inode->i_op->removexattr)
430                 rc = cache_inode->i_op->removexattr(&open_dentry, name);
431
432         duplicate_inode(cache_inode, dentry->d_inode);          
433         RETURN(rc);
434 }
435
436 struct inode_operations smfs_file_iops = {
437         truncate:       smfs_truncate,          /* BKL held */
438         setattr:        smfs_setattr,           /* BKL held */
439         setxattr:       smfs_setxattr,          /* BKL held */
440         getxattr:       smfs_getxattr,          /* BKL held */
441         listxattr:      smfs_listxattr,         /* BKL held */
442         removexattr:    smfs_removexattr,       /* BKL held */
443 };
444