Whamcloud - gitweb
fce003a593c6481f16b52ea280f83cd8dbaf230b
[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 static int smfs_readpage(struct file *file, 
17                          struct page *page)
18 {
19         struct  inode *inode = page->mapping->host;
20         struct  inode *cache_inode;
21         struct page *cache_page = NULL;
22         int rc = 0; 
23
24         ENTRY;
25         
26         cache_inode = I2CI(inode);
27  
28         if (!cache_inode)
29                 RETURN(-ENOENT);
30         
31         cache_page = grab_cache_page(cache_inode->i_mapping, page->index);
32
33         if (!cache_page) 
34                 GOTO(exit_release, rc = -ENOMEM);
35
36         if ((rc = cache_inode->i_mapping->a_ops->readpage(file, cache_page)))
37                 GOTO(exit_release, 0);
38         
39         wait_on_page(cache_page);
40
41         if (!Page_Uptodate(cache_page))
42                 GOTO(exit_release, rc = -EIO);
43
44         memcpy(kmap(page), kmap(cache_page), PAGE_CACHE_SIZE);
45
46         flush_dcache_page(page);
47
48         kunmap(cache_page);
49         page_cache_release(cache_page);
50
51 exit:   
52         kunmap(page);
53         SetPageUptodate(page);
54         UnlockPage(page);
55
56         RETURN(rc);
57
58 exit_release:
59         if (cache_page) 
60                 page_cache_release(cache_page);
61         UnlockPage(page);
62         RETURN(rc);
63 }
64
65 static int smfs_writepage(struct page *page)
66 {
67
68         struct  inode *inode = page->mapping->host;
69         struct  inode *cache_inode;
70         int     rc;
71         
72         ENTRY;
73         
74         cache_inode = I2CI(inode);
75  
76         if (!cache_inode)
77                 RETURN(-ENOENT);
78
79         if (cache_inode->i_mapping->a_ops->writepage)
80                 rc = cache_inode->i_mapping->a_ops->writepage(page);
81                 
82         RETURN(rc);
83 }
84
85 static int smfs_sync_page(struct page *page)
86 {
87         struct inode *inode = page->mapping->host;
88         struct inode *cache_inode;
89         int    rc = 0;
90                 
91         cache_inode = I2CI(inode);
92  
93         if (!cache_inode)
94                 RETURN(-ENOENT);
95
96         if (cache_inode->i_mapping->a_ops->sync_page)
97                 rc = cache_inode->i_mapping->a_ops->sync_page(page);
98
99         RETURN(rc);
100 }
101
102 static int smfs_prepare_write(struct file *file, struct page *page,
103                               unsigned from, unsigned to)
104 {
105         struct inode *inode = page->mapping->host;
106         struct inode *cache_inode;
107         int    rc = 0;
108                 
109         cache_inode = I2CI(inode);
110  
111         if (!cache_inode)
112                 RETURN(-ENOENT);
113
114         if (cache_inode->i_mapping->a_ops->prepare_write)
115                 rc = cache_inode->i_mapping->a_ops->prepare_write(file, page, from, to);
116
117         RETURN(rc);
118 }
119
120 static int smfs_commit_write(struct file *file, struct page *page,
121                              unsigned from, unsigned to)
122 {
123         struct inode *inode = page->mapping->host;
124         struct inode *cache_inode;
125         int    rc = 0;
126                 
127         cache_inode = I2CI(inode);
128  
129         if (!cache_inode)
130                 RETURN(-ENOENT);
131
132         if (cache_inode->i_mapping->a_ops->commit_write)
133                 rc = cache_inode->i_mapping->a_ops->commit_write(file, page, from, to);
134
135         RETURN(rc);
136 }
137
138 static int smfs_bmap(struct address_space *mapping, long block)
139 {
140         struct inode *inode = mapping->host;
141         struct inode *cache_inode;
142         int    rc = 0;
143                 
144         cache_inode = I2CI(inode);
145  
146         if (!cache_inode)
147                 RETURN(-ENOENT);
148
149         if (cache_inode->i_mapping->a_ops->bmap)
150                 rc = cache_inode->i_mapping->a_ops->bmap(mapping, block);
151
152         RETURN(rc);
153 }
154
155 static int smfs_flushpage(struct page *page, unsigned long offset) 
156 {
157         struct inode *inode = page->mapping->host;
158         struct inode *cache_inode;
159         int    rc = 0;
160                 
161         cache_inode = I2CI(inode);
162  
163         if (!cache_inode)
164                 RETURN(-ENOENT);
165
166         if (cache_inode->i_mapping->a_ops->flushpage)
167                 rc = cache_inode->i_mapping->a_ops->flushpage(page, offset);
168
169         RETURN(rc);
170 }
171
172 static int smfs_releasepage(struct page *page, int wait) 
173 {
174         struct inode *inode = page->mapping->host;
175         struct inode *cache_inode;
176         int    rc = 0;
177                 
178         cache_inode = I2CI(inode);
179  
180         if (!cache_inode)
181                 RETURN(-ENOENT);
182
183         if (cache_inode->i_mapping->a_ops->releasepage)
184                 rc = cache_inode->i_mapping->a_ops->releasepage(page, wait);
185
186         RETURN(rc);
187 }
188
189 static int smfs_direct_IO(int rw, struct inode *inode, struct kiobuf *iobuf,
190                 unsigned long blocknr, int blocksize) 
191 {
192         struct inode *cache_inode;
193         int    rc = 0;
194                 
195         cache_inode = I2CI(inode);
196  
197         if (!cache_inode)
198                 RETURN(-ENOENT);
199
200         if (cache_inode->i_mapping->a_ops->direct_IO)
201                 rc = cache_inode->i_mapping->a_ops->direct_IO(rw, cache_inode, iobuf,
202                                                               blocknr, blocksize);
203         RETURN(rc);
204 }
205
206 struct address_space_operations smfs_file_aops = {
207         readpage:       smfs_readpage,
208         writepage:      smfs_writepage,
209         sync_page:      smfs_sync_page,
210         prepare_write:  smfs_prepare_write,
211         commit_write:   smfs_commit_write,
212         bmap:           smfs_bmap,
213         flushpage:      smfs_flushpage,
214         releasepage:    smfs_releasepage,
215         direct_IO:      smfs_direct_IO, 
216 };
217         
218 /* instantiate a file handle to the cache file */
219 void smfs_prepare_cachefile(struct inode *inode,
220                             struct file *file, 
221                             struct inode *cache_inode,
222                             struct file *cache_file,
223                             struct dentry *cache_dentry)
224 {
225         ENTRY;
226         cache_file->f_pos = file->f_pos;
227         cache_file->f_mode = file->f_mode;
228         cache_file->f_flags = file->f_flags;
229         cache_file->f_count  = file->f_count;
230         cache_file->f_owner  = file->f_owner;
231         cache_file->f_error = file->f_error;
232         cache_file->f_op = inode->i_fop;
233         cache_file->f_dentry = cache_dentry;
234         cache_file->f_dentry->d_inode = cache_inode;
235         cache_file->f_vfsmnt = file->f_vfsmnt;
236         cache_file->private_data = file->private_data;
237         cache_file->f_it = file->f_it;
238         cache_file->f_reada = file->f_reada;
239         cache_file->f_ramax = file->f_ramax;
240         cache_file->f_raend = file->f_raend;
241         cache_file->f_ralen = file->f_ralen;
242         cache_file->f_rawin = file->f_rawin;
243         EXIT;
244 }
245 /* update file structs*/
246 void smfs_update_file(struct file *file, 
247                       struct file *cache_file)
248 {
249         ENTRY;
250         file->f_pos = cache_file->f_pos;
251         file->f_mode = cache_file->f_mode;
252         file->f_flags = cache_file->f_flags;
253         file->f_count  = cache_file->f_count;
254         file->f_owner  = cache_file->f_owner;
255         file->f_reada = cache_file->f_reada;
256         file->f_ramax = cache_file->f_ramax;
257         file->f_raend = cache_file->f_raend;
258         file->f_ralen = cache_file->f_ralen;
259         file->f_rawin = cache_file->f_rawin;
260         EXIT;
261 }
262
263 static ssize_t smfs_write (struct file *filp, const char *buf, 
264                            size_t count, loff_t *ppos)
265 {
266         struct  inode *cache_inode;
267         struct  dentry *dentry = filp->f_dentry;
268         struct  inode *inode = dentry->d_inode;
269         struct  file open_file;
270         struct  dentry open_dentry;
271         loff_t  tmp_ppos;
272         loff_t  *cache_ppos;
273         int     rc = 0;
274         
275         ENTRY;
276         
277         cache_inode = I2CI(inode);
278  
279         if (!cache_inode)
280                 RETURN(-ENOENT);
281         
282         if (ppos != &(filp->f_pos)) {
283                 cache_ppos = &tmp_ppos; 
284         } else {
285                 cache_ppos = &open_file.f_pos; 
286         }
287         *cache_ppos = *ppos;
288         
289         smfs_prepare_cachefile(inode, filp, cache_inode, 
290                                &open_file, &open_dentry);
291         if (cache_inode->i_fop->write)
292                 rc = cache_inode->i_fop->write(&open_file, buf, count, cache_ppos);
293         
294         *ppos = *cache_ppos;
295         duplicate_inode(cache_inode, inode);
296         smfs_update_file(filp, &open_file);
297
298         RETURN(rc);
299 }
300
301 int smfs_ioctl(struct inode * inode, struct file * filp, 
302                unsigned int cmd, unsigned long arg)
303 {
304         struct  inode *cache_inode;
305         struct  dentry *dentry = filp->f_dentry;
306         struct  file open_file;
307         struct  dentry open_dentry;
308         ssize_t rc = 0;
309         
310         ENTRY;
311         
312         cache_inode = I2CI(dentry->d_inode);
313         if (!cache_inode)
314                 RETURN(-ENOENT);
315
316         smfs_prepare_cachefile(inode, filp, cache_inode, 
317                                &open_file, &open_dentry);
318         
319         if (cache_inode->i_fop->ioctl)
320                 rc = cache_inode->i_fop->ioctl(cache_inode, &open_file, cmd, arg);
321                 
322         duplicate_inode(cache_inode, inode);
323         smfs_update_file(filp, &open_file);
324         RETURN(rc);
325 }
326
327 static ssize_t smfs_read (struct file *filp, char *buf, 
328                           size_t count, loff_t *ppos)
329 {
330         struct  inode *cache_inode;
331         struct  dentry *dentry = filp->f_dentry;
332         struct  inode *inode = dentry->d_inode;
333         struct  file open_file;
334         struct  dentry open_dentry;
335         loff_t  tmp_ppos;
336         loff_t  *cache_ppos;
337         ssize_t rc = 0;
338         
339         ENTRY;
340         
341         cache_inode = I2CI(dentry->d_inode);
342         if (!cache_inode)
343                 RETURN(-ENOENT);
344
345         if (ppos != &(filp->f_pos)) {
346                 cache_ppos = &tmp_ppos; 
347         } else {
348                 cache_ppos = &open_file.f_pos; 
349         }
350         *cache_ppos = *ppos;
351         
352         
353         smfs_prepare_cachefile(inode, filp, cache_inode, 
354                                &open_file, &open_dentry);
355
356         
357         if (cache_inode->i_fop->read)
358                 rc = cache_inode->i_fop->read(&open_file, buf, count, cache_ppos);
359     
360         *ppos = *cache_ppos;
361         duplicate_inode(cache_inode, inode);
362         smfs_update_file(filp, &open_file);
363         RETURN(rc);
364 }
365
366 static loff_t smfs_llseek(struct file *file, 
367                           loff_t offset, 
368                           int origin)
369 {
370         struct  inode *cache_inode;
371         struct  dentry *dentry = file->f_dentry;
372         struct  file open_file;
373         struct  dentry open_dentry;
374         ssize_t rc = 0;
375         
376         ENTRY;
377         
378         cache_inode = I2CI(dentry->d_inode);
379         if (!cache_inode)
380                 RETURN(-ENOENT);
381
382         smfs_prepare_cachefile(dentry->d_inode, file, cache_inode, 
383                                &open_file, &open_dentry);
384         
385         if (cache_inode->i_fop->llseek)
386                 rc = cache_inode->i_fop->llseek(&open_file, offset, origin);
387
388         duplicate_inode(cache_inode, dentry->d_inode);
389         smfs_update_file(file, &open_file);
390                 
391         RETURN(rc);
392 }
393
394 static int smfs_mmap(struct file * file, struct vm_area_struct * vma)
395 {
396         struct address_space *mapping = file->f_dentry->d_inode->i_mapping;
397         struct inode *inode = mapping->host;
398         struct inode *cache_inode = NULL;
399         struct  file open_file;
400         struct  dentry open_dentry;
401         int    rc = 0;
402
403         cache_inode = I2CI(inode);
404         if (!cache_inode)
405                 RETURN(-ENOENT);
406
407         smfs_prepare_cachefile(inode, file, cache_inode, 
408                                &open_file, &open_dentry);
409         
410         if (cache_inode->i_fop->mmap)
411                 rc = cache_inode->i_fop->mmap(&open_file, vma);
412        
413         duplicate_inode(cache_inode, inode);
414         smfs_update_file(file, &open_file);
415         
416         RETURN(rc);
417 }
418
419 static int smfs_open(struct inode * inode, struct file * filp)
420 {
421         struct inode *cache_inode = NULL;
422         struct  file open_file;
423         struct  dentry open_dentry;
424         int    rc = 0;
425
426         cache_inode = I2CI(inode);
427         if (!cache_inode)
428                 RETURN(-ENOENT);
429
430         smfs_prepare_cachefile(inode, filp, cache_inode, 
431                                &open_file, &open_dentry);
432         
433         if (cache_inode->i_fop->open)
434                 rc = cache_inode->i_fop->open(cache_inode, &open_file);
435         
436         duplicate_inode(cache_inode, inode);
437         smfs_update_file(filp, &open_file);
438         
439         RETURN(rc);
440
441 }
442 static int smfs_release(struct inode * inode, struct file * filp)
443 {
444         struct inode *cache_inode = NULL;
445         struct  file open_file;
446         struct  dentry open_dentry;
447         int    rc = 0;
448
449         cache_inode = I2CI(inode);
450         if (!cache_inode)
451                 RETURN(-ENOENT);
452         
453         smfs_prepare_cachefile(inode, filp, cache_inode, 
454                                &open_file, &open_dentry);
455
456         if (cache_inode->i_fop->release)
457                 rc = cache_inode->i_fop->release(cache_inode, &open_file);
458
459         duplicate_inode(cache_inode, inode);
460         smfs_update_file(filp, &open_file);
461         
462         RETURN(rc);
463 }
464 int smfs_fsync(struct file * file, 
465                       struct dentry *dentry, 
466                       int datasync)
467 {
468         struct inode *inode = dentry->d_inode;
469         struct inode *cache_inode;
470         struct  file open_file;
471         struct  dentry open_dentry;
472         int    rc = 0;
473
474         cache_inode = I2CI(inode);
475         if (!cache_inode)
476                 RETURN(-ENOENT);
477         
478         smfs_prepare_cachefile(inode, file, cache_inode, 
479                                &open_file, &open_dentry);
480
481         if (cache_inode->i_fop->fsync)
482                 rc = cache_inode->i_fop->fsync(&open_file, &open_dentry, datasync);
483         
484         duplicate_inode(cache_inode, inode);
485         smfs_update_file(file, &open_file);
486         
487         RETURN(rc);
488 }
489
490 struct file_operations smfs_file_fops = {
491         llseek:         smfs_llseek,
492         read:           smfs_read,
493         write:          smfs_write,
494         ioctl:          smfs_ioctl,
495         mmap:           smfs_mmap,
496         open:           smfs_open,
497         release:        smfs_release,
498         fsync:          smfs_fsync,
499 };
500
501 static void smfs_prepare_cache_dentry(struct dentry *dentry, struct inode *inode)
502 {
503         atomic_set(&dentry->d_count, 1);
504         dentry->d_vfs_flags = 0;
505         dentry->d_flags = 0;
506         dentry->d_inode = inode;
507         dentry->d_op = NULL;
508         dentry->d_fsdata = NULL;
509         dentry->d_mounted = 0;
510         INIT_LIST_HEAD(&dentry->d_hash);
511         INIT_LIST_HEAD(&dentry->d_lru);
512         INIT_LIST_HEAD(&dentry->d_subdirs);
513         INIT_LIST_HEAD(&dentry->d_alias);
514 }
515
516 static void smfs_truncate(struct inode * inode)      
517 {
518         struct  inode *cache_inode;
519
520         cache_inode = I2CI(inode);
521
522         if (!cache_inode)
523                 return;
524         
525         if (cache_inode->i_op->truncate)
526                 cache_inode->i_op->truncate(cache_inode);
527
528         duplicate_inode(inode, cache_inode);            
529         
530         return; 
531
532  
533 int smfs_setattr(struct dentry *dentry, struct iattr *attr)      
534 {
535         struct  inode *cache_inode;
536         struct  dentry open_dentry;
537
538         int     rc = 0;
539
540         cache_inode = I2CI(dentry->d_inode);
541
542         if (!cache_inode) 
543                 RETURN(-ENOENT);
544         smfs_prepare_cache_dentry(&open_dentry, cache_inode);
545         
546         if (cache_inode->i_op->setattr)
547                 rc = cache_inode->i_op->setattr(&open_dentry, attr);
548
549         duplicate_inode(cache_inode, dentry->d_inode);          
550         
551         RETURN(rc);
552
553   
554 int smfs_setxattr(struct dentry *dentry, const char *name,
555                   const void *value, size_t size, int flags)
556 {
557         struct  inode *cache_inode;
558         struct  dentry open_dentry;
559         int     rc = 0;
560
561         cache_inode = I2CI(dentry->d_inode);
562
563         if (!cache_inode) 
564                 RETURN(-ENOENT);
565
566         smfs_prepare_cache_dentry(&open_dentry, cache_inode);
567         
568         if (cache_inode->i_op->setattr)
569                 rc = cache_inode->i_op->setxattr(&open_dentry, name, value, size, flags);
570
571         duplicate_inode(cache_inode, dentry->d_inode);          
572         RETURN(rc);
573
574                         
575 int smfs_getxattr(struct dentry *dentry, const char *name,
576                   void *buffer, size_t size)
577 {
578         struct  inode *cache_inode;
579         struct  dentry open_dentry;
580         int     rc = 0;
581
582         cache_inode = I2CI(dentry->d_inode);
583
584         if (!cache_inode) 
585                 RETURN(-ENOENT);
586
587         smfs_prepare_cache_dentry(&open_dentry, cache_inode);
588         
589         if (cache_inode->i_op->setattr)
590                 rc = cache_inode->i_op->getxattr(&open_dentry, name, buffer, size);
591
592         duplicate_inode(cache_inode, dentry->d_inode);          
593         RETURN(rc);
594 }
595
596 ssize_t smfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
597 {
598         struct  inode *cache_inode;
599         struct  dentry open_dentry;
600         int     rc = 0;
601
602         cache_inode = I2CI(dentry->d_inode);
603
604         if (!cache_inode) 
605                 RETURN(-ENOENT);
606
607         smfs_prepare_cache_dentry(&open_dentry, cache_inode);
608         
609         if (cache_inode->i_op->listxattr)
610                 rc = cache_inode->i_op->listxattr(&open_dentry, buffer, size);
611
612         duplicate_inode(cache_inode, dentry->d_inode);          
613         RETURN(rc);
614 }                                                                                                                                                           
615
616 int smfs_removexattr(struct dentry *dentry, const char *name)
617 {
618         struct  inode *cache_inode;
619         struct  dentry open_dentry;
620         int     rc = 0;
621
622         cache_inode = I2CI(dentry->d_inode);
623
624         if (!cache_inode) 
625                 RETURN(-ENOENT);
626
627         smfs_prepare_cache_dentry(&open_dentry, cache_inode);
628         
629         if (cache_inode->i_op->removexattr)
630                 rc = cache_inode->i_op->removexattr(&open_dentry, name);
631
632         duplicate_inode(cache_inode, dentry->d_inode);          
633         RETURN(rc);
634 }
635
636 struct inode_operations smfs_file_iops = {
637         truncate:       smfs_truncate,          /* BKL held */
638         setattr:        smfs_setattr,           /* BKL held */
639         setxattr:       smfs_setxattr,          /* BKL held */
640         getxattr:       smfs_getxattr,          /* BKL held */
641         listxattr:      smfs_listxattr,         /* BKL held */
642         removexattr:    smfs_removexattr,       /* BKL held */
643 };
644