Whamcloud - gitweb
update smfs 1)delete inode->i_list in smfs_delete_inode for the cache inode will...
[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 struct address_space_operations smfs_file_aops = {
86         readpage:   smfs_readpage,
87         writepage:  smfs_writepage,
88 };
89         
90 /* instantiate a file handle to the cache file */
91 void smfs_prepare_cachefile(struct inode *inode,
92                             struct file *file, 
93                             struct inode *cache_inode,
94                             struct file *cache_file,
95                             struct dentry *cache_dentry)
96 {
97         ENTRY;
98         cache_file->f_pos = file->f_pos;
99         cache_file->f_mode = file->f_mode;
100         cache_file->f_flags = file->f_flags;
101         cache_file->f_count  = file->f_count;
102         cache_file->f_owner  = file->f_owner;
103         cache_file->f_error = file->f_error;
104         cache_file->f_op = inode->i_fop;
105         cache_file->f_dentry = cache_dentry;
106         cache_file->f_dentry->d_inode = cache_inode;
107         cache_file->f_vfsmnt = file->f_vfsmnt;
108         cache_file->private_data = file->private_data;
109         cache_file->f_it = file->f_it;
110         cache_file->f_reada = file->f_reada;
111         cache_file->f_ramax = file->f_ramax;
112         cache_file->f_raend = file->f_raend;
113         cache_file->f_ralen = file->f_ralen;
114         cache_file->f_rawin = file->f_rawin;
115         EXIT;
116 }
117 /* update file structs*/
118 void smfs_update_file(struct file *file, 
119                       struct file *cache_file)
120 {
121         ENTRY;
122         file->f_pos = cache_file->f_pos;
123         file->f_mode = cache_file->f_mode;
124         file->f_flags = cache_file->f_flags;
125         file->f_count  = cache_file->f_count;
126         file->f_owner  = cache_file->f_owner;
127         file->f_reada = cache_file->f_reada;
128         file->f_ramax = cache_file->f_ramax;
129         file->f_raend = cache_file->f_raend;
130         file->f_ralen = cache_file->f_ralen;
131         file->f_rawin = cache_file->f_rawin;
132         EXIT;
133 }
134
135 static ssize_t smfs_write (struct file *filp, const char *buf, 
136                            size_t count, loff_t *ppos)
137 {
138         struct  inode *cache_inode;
139         struct  dentry *dentry = filp->f_dentry;
140         struct  inode *inode = dentry->d_inode;
141         struct  file open_file;
142         struct  dentry open_dentry;
143         int     rc = 0;
144         
145         ENTRY;
146         
147         cache_inode = I2CI(inode);
148  
149         if (!cache_inode)
150                 RETURN(-ENOENT);
151         
152         smfs_prepare_cachefile(inode, filp, cache_inode, 
153                                &open_file, &open_dentry);
154         
155         if (cache_inode->i_fop->write)
156                 rc = cache_inode->i_fop->write(&open_file, buf, count, &open_file.f_pos);
157         
158         *ppos = open_file.f_pos;
159         duplicate_inode(cache_inode, inode);
160         smfs_update_file(filp, &open_file);
161
162         RETURN(rc);
163 }
164 int smfs_ioctl(struct inode * inode, struct file * filp, 
165                unsigned int cmd, unsigned long arg)
166 {
167         struct  inode *cache_inode;
168         struct  dentry *dentry = filp->f_dentry;
169         struct  file open_file;
170         struct  dentry open_dentry;
171         ssize_t rc;
172         
173         ENTRY;
174         
175         cache_inode = I2CI(dentry->d_inode);
176         if (!cache_inode)
177                 RETURN(-ENOENT);
178
179         smfs_prepare_cachefile(inode, filp, cache_inode, 
180                                &open_file, &open_dentry);
181         
182         if (cache_inode->i_fop->ioctl)
183                 rc = cache_inode->i_fop->ioctl(cache_inode, &open_file, cmd, arg);
184                 
185         duplicate_inode(cache_inode, inode);
186         smfs_update_file(filp, &open_file);
187         RETURN(rc);
188 }
189
190 static ssize_t smfs_read (struct file *filp, char *buf, 
191                           size_t count, loff_t *ppos)
192 {
193         struct  inode *cache_inode;
194         struct  dentry *dentry = filp->f_dentry;
195         struct  inode *inode = dentry->d_inode;
196         struct  file open_file;
197         struct  dentry open_dentry;
198         ssize_t rc;
199         
200         ENTRY;
201         
202         cache_inode = I2CI(dentry->d_inode);
203         if (!cache_inode)
204                 RETURN(-ENOENT);
205
206         smfs_prepare_cachefile(inode, filp, cache_inode, 
207                                &open_file, &open_dentry);
208         
209         if (cache_inode->i_fop->read)
210                 rc = cache_inode->i_fop->read(&open_file, buf, count, &open_file.f_pos);
211     
212         *ppos = open_file.f_pos;
213         duplicate_inode(cache_inode, inode);
214         smfs_update_file(filp, &open_file);
215         RETURN(rc);
216 }
217
218 static loff_t smfs_llseek(struct file *file, 
219                           loff_t offset, 
220                           int origin)
221 {
222         struct  inode *cache_inode;
223         struct  dentry *dentry = file->f_dentry;
224         struct  file open_file;
225         struct  dentry open_dentry;
226         ssize_t rc;
227         
228         ENTRY;
229         
230         cache_inode = I2CI(dentry->d_inode);
231         if (!cache_inode)
232                 RETURN(-ENOENT);
233
234         smfs_prepare_cachefile(dentry->d_inode, file, cache_inode, 
235                                &open_file, &open_dentry);
236         
237         if (cache_inode->i_fop->llseek)
238                 rc = cache_inode->i_fop->llseek(&open_file, offset, origin);
239         
240         duplicate_inode(cache_inode, dentry->d_inode);
241         smfs_update_file(file, &open_file);
242                 
243         RETURN(rc);
244 }
245
246 static int smfs_mmap(struct file * file, struct vm_area_struct * vma)
247 {
248         struct address_space *mapping = file->f_dentry->d_inode->i_mapping;
249         struct inode *inode = mapping->host;
250         struct inode *cache_inode = NULL;
251         struct  file open_file;
252         struct  dentry open_dentry;
253         int    rc = 0;
254
255         cache_inode = I2CI(inode);
256         if (!cache_inode)
257                 RETURN(-ENOENT);
258
259         smfs_prepare_cachefile(inode, file, cache_inode, 
260                                &open_file, &open_dentry);
261         
262         if (cache_inode->i_fop->mmap)
263                 rc = cache_inode->i_fop->mmap(&open_file, vma);
264        
265         duplicate_inode(cache_inode, inode);
266         smfs_update_file(file, &open_file);
267         
268         RETURN(rc);
269 }
270
271 static int smfs_open(struct inode * inode, struct file * filp)
272 {
273         struct inode *cache_inode = NULL;
274         struct  file open_file;
275         struct  dentry open_dentry;
276         int    rc = 0;
277
278         cache_inode = I2CI(inode);
279         if (!cache_inode)
280                 RETURN(-ENOENT);
281
282         smfs_prepare_cachefile(inode, filp, cache_inode, 
283                                &open_file, &open_dentry);
284         
285         if (cache_inode->i_fop->open)
286                 rc = cache_inode->i_fop->open(cache_inode, &open_file);
287         
288         duplicate_inode(cache_inode, inode);
289         smfs_update_file(filp, &open_file);
290         
291         RETURN(rc);
292
293 }
294 static int smfs_release(struct inode * inode, struct file * filp)
295 {
296         struct inode *cache_inode = NULL;
297         struct  file open_file;
298         struct  dentry open_dentry;
299         int    rc = 0;
300
301         cache_inode = I2CI(inode);
302         if (!cache_inode)
303                 RETURN(-ENOENT);
304         
305         smfs_prepare_cachefile(inode, filp, cache_inode, 
306                                &open_file, &open_dentry);
307
308         if (cache_inode->i_fop->release)
309                 rc = cache_inode->i_fop->release(cache_inode, &open_file);
310
311         duplicate_inode(cache_inode, inode);
312         smfs_update_file(filp, &open_file);
313         
314         RETURN(rc);
315 }
316 int smfs_fsync(struct file * file, 
317                       struct dentry *dentry, 
318                       int datasync)
319 {
320         struct inode *inode = dentry->d_inode;
321         struct inode *cache_inode;
322         struct  file open_file;
323         struct  dentry open_dentry;
324         int    rc = 0;
325
326         cache_inode = I2CI(inode);
327         if (!cache_inode)
328                 RETURN(-ENOENT);
329         
330         smfs_prepare_cachefile(inode, file, cache_inode, 
331                                &open_file, &open_dentry);
332
333         if (cache_inode->i_fop->fsync)
334                 rc = cache_inode->i_fop->fsync(&open_file, &open_dentry, datasync);
335         
336         duplicate_inode(cache_inode, inode);
337         smfs_update_file(file, &open_file);
338         
339         RETURN(rc);
340 }
341
342 struct file_operations smfs_file_fops = {
343         llseek:         smfs_llseek,
344         read:           smfs_read,
345         write:          smfs_write,
346         ioctl:          smfs_ioctl,
347         mmap:           smfs_mmap,
348         open:           smfs_open,
349         release:        smfs_release,
350         fsync:          smfs_fsync,
351 };
352
353 static void smfs_prepare_cache_dentry(struct dentry *dentry, struct inode *inode)
354 {
355         atomic_set(&dentry->d_count, 1);
356         dentry->d_vfs_flags = 0;
357         dentry->d_flags = 0;
358         dentry->d_inode = inode;
359         dentry->d_op = NULL;
360         dentry->d_fsdata = NULL;
361         dentry->d_mounted = 0;
362         INIT_LIST_HEAD(&dentry->d_hash);
363         INIT_LIST_HEAD(&dentry->d_lru);
364         INIT_LIST_HEAD(&dentry->d_subdirs);
365         INIT_LIST_HEAD(&dentry->d_alias);
366 }
367
368 static void smfs_truncate(struct inode * inode)      
369 {
370         struct  inode *cache_inode;
371
372         cache_inode = I2CI(inode);
373
374         if (!cache_inode)
375                 return;
376         
377         if (cache_inode->i_op->truncate)
378                 cache_inode->i_op->truncate(cache_inode);
379
380         duplicate_inode(inode, cache_inode);            
381         
382         return; 
383
384  
385 int smfs_setattr(struct dentry *dentry, struct iattr *attr)      
386 {
387         struct  inode *cache_inode;
388         struct  dentry open_dentry;
389
390         int     rc = 0;
391
392         cache_inode = I2CI(dentry->d_inode);
393
394         if (!cache_inode) 
395                 RETURN(-ENOENT);
396         smfs_prepare_cache_dentry(&open_dentry, cache_inode);
397         
398         if (cache_inode->i_op->setattr)
399                 rc = cache_inode->i_op->setattr(&open_dentry, attr);
400
401         RETURN(rc);
402
403   
404 int smfs_setxattr(struct dentry *dentry, const char *name,
405                   const void *value, size_t size, int flags)
406 {
407         struct  inode *cache_inode;
408         struct  dentry open_dentry;
409         int     rc = 0;
410
411         cache_inode = I2CI(dentry->d_inode);
412
413         if (!cache_inode) 
414                 RETURN(-ENOENT);
415
416         smfs_prepare_cache_dentry(&open_dentry, cache_inode);
417         
418         if (cache_inode->i_op->setattr)
419                 rc = cache_inode->i_op->setxattr(&open_dentry, name, value, size, flags);
420
421         RETURN(rc);
422
423                         
424 int smfs_getxattr(struct dentry *dentry, const char *name,
425                   void *buffer, size_t size)
426 {
427         struct  inode *cache_inode;
428         struct  dentry open_dentry;
429         int     rc = 0;
430
431         cache_inode = I2CI(dentry->d_inode);
432
433         if (!cache_inode) 
434                 RETURN(-ENOENT);
435
436         smfs_prepare_cache_dentry(&open_dentry, cache_inode);
437         
438         if (cache_inode->i_op->setattr)
439                 rc = cache_inode->i_op->getxattr(&open_dentry, name, buffer, size);
440
441         RETURN(rc);
442 }
443
444 ssize_t smfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
445 {
446         struct  inode *cache_inode;
447         struct  dentry open_dentry;
448         int     rc = 0;
449
450         cache_inode = I2CI(dentry->d_inode);
451
452         if (!cache_inode) 
453                 RETURN(-ENOENT);
454
455         smfs_prepare_cache_dentry(&open_dentry, cache_inode);
456         
457         if (cache_inode->i_op->listxattr)
458                 rc = cache_inode->i_op->listxattr(&open_dentry, buffer, size);
459
460         RETURN(rc);
461 }                                                                                                                                                           
462
463 int smfs_removexattr(struct dentry *dentry, const char *name)
464 {
465         struct  inode *cache_inode;
466         struct  dentry open_dentry;
467         int     rc = 0;
468
469         cache_inode = I2CI(dentry->d_inode);
470
471         if (!cache_inode) 
472                 RETURN(-ENOENT);
473
474         smfs_prepare_cache_dentry(&open_dentry, cache_inode);
475         
476         if (cache_inode->i_op->removexattr)
477                 rc = cache_inode->i_op->removexattr(&open_dentry, name);
478
479         RETURN(rc);
480 }
481
482 struct inode_operations smfs_file_iops = {
483         truncate:       smfs_truncate,          /* BKL held */
484         setattr:        smfs_setattr,           /* BKL held */
485         setxattr:       smfs_setxattr,          /* BKL held */
486         getxattr:       smfs_getxattr,          /* BKL held */
487         listxattr:      smfs_listxattr,         /* BKL held */
488         removexattr:    smfs_removexattr,       /* BKL held */
489 };
490