Whamcloud - gitweb
update smfs 1)fix read file bugs 2)add some superblock operations 3)some minor fix
[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, ppos);
157         
158         duplicate_inode(cache_inode, inode);
159         smfs_update_file(filp, &open_file);
160
161         RETURN(rc);
162 }
163 int smfs_ioctl(struct inode * inode, struct file * filp, 
164                unsigned int cmd, unsigned long arg)
165 {
166         struct  inode *cache_inode;
167         struct  dentry *dentry = filp->f_dentry;
168         struct  file open_file;
169         struct  dentry open_dentry;
170         ssize_t rc;
171         
172         ENTRY;
173         
174         cache_inode = I2CI(dentry->d_inode);
175         if (!cache_inode)
176                 RETURN(-ENOENT);
177
178         smfs_prepare_cachefile(inode, filp, cache_inode, 
179                                &open_file, &open_dentry);
180         
181         if (cache_inode->i_fop->ioctl)
182                 rc = cache_inode->i_fop->ioctl(cache_inode, &open_file, cmd, arg);
183                 
184         duplicate_inode(cache_inode, inode);
185         smfs_update_file(filp, &open_file);
186         RETURN(rc);
187 }
188
189 static ssize_t smfs_read (struct file *filp, char *buf, 
190                           size_t count, loff_t *ppos)
191 {
192         struct  inode *cache_inode;
193         struct  dentry *dentry = filp->f_dentry;
194         ssize_t rc;
195         
196         ENTRY;
197         
198         cache_inode = I2CI(dentry->d_inode);
199         if (!cache_inode)
200                 RETURN(-ENOENT);
201
202         if (cache_inode->i_fop->read)
203                 rc = cache_inode->i_fop->read(filp, buf, count, ppos);
204     
205         duplicate_inode(cache_inode, dentry->d_inode);
206         RETURN(rc);
207 }
208
209 static loff_t smfs_llseek(struct file *file, 
210                           loff_t offset, 
211                           int origin)
212 {
213         struct  inode *cache_inode;
214         struct  dentry *dentry = file->f_dentry;
215         struct  file open_file;
216         struct  dentry open_dentry;
217         ssize_t rc;
218         
219         ENTRY;
220         
221         cache_inode = I2CI(dentry->d_inode);
222         if (!cache_inode)
223                 RETURN(-ENOENT);
224
225         smfs_prepare_cachefile(dentry->d_inode, file, cache_inode, 
226                                &open_file, &open_dentry);
227         
228         if (cache_inode->i_fop->llseek)
229                 rc = cache_inode->i_fop->llseek(&open_file, offset, origin);
230         
231         duplicate_inode(cache_inode, dentry->d_inode);
232         smfs_update_file(file, &open_file);
233                 
234         RETURN(rc);
235 }
236
237 static int smfs_mmap(struct file * file, struct vm_area_struct * vma)
238 {
239         struct address_space *mapping = file->f_dentry->d_inode->i_mapping;
240         struct inode *inode = mapping->host;
241         struct inode *cache_inode = NULL;
242         struct  file open_file;
243         struct  dentry open_dentry;
244         int    rc = 0;
245
246         cache_inode = I2CI(inode);
247         if (!cache_inode)
248                 RETURN(-ENOENT);
249
250         smfs_prepare_cachefile(inode, file, cache_inode, 
251                                &open_file, &open_dentry);
252         
253         if (cache_inode->i_fop->mmap)
254                 rc = cache_inode->i_fop->mmap(&open_file, vma);
255        
256         duplicate_inode(cache_inode, inode);
257         smfs_update_file(file, &open_file);
258         
259         RETURN(rc);
260 }
261
262 static int smfs_open(struct inode * inode, struct file * filp)
263 {
264         struct inode *cache_inode = NULL;
265         struct  file open_file;
266         struct  dentry open_dentry;
267         int    rc = 0;
268
269         cache_inode = I2CI(inode);
270         if (!cache_inode)
271                 RETURN(-ENOENT);
272
273         smfs_prepare_cachefile(inode, filp, cache_inode, 
274                                &open_file, &open_dentry);
275         
276         if (cache_inode->i_fop->open)
277                 rc = cache_inode->i_fop->open(cache_inode, &open_file);
278         
279         duplicate_inode(cache_inode, inode);
280         smfs_update_file(filp, &open_file);
281         
282         RETURN(rc);
283
284 }
285 static int smfs_release(struct inode * inode, struct file * filp)
286 {
287         struct inode *cache_inode = NULL;
288         struct  file open_file;
289         struct  dentry open_dentry;
290         int    rc = 0;
291
292         cache_inode = I2CI(inode);
293         if (!cache_inode)
294                 RETURN(-ENOENT);
295         
296         smfs_prepare_cachefile(inode, filp, cache_inode, 
297                                &open_file, &open_dentry);
298
299         if (cache_inode->i_fop->release)
300                 rc = cache_inode->i_fop->release(cache_inode, &open_file);
301
302         duplicate_inode(cache_inode, inode);
303         smfs_update_file(filp, &open_file);
304         
305         RETURN(rc);
306 }
307 int smfs_fsync(struct file * file, 
308                       struct dentry *dentry, 
309                       int datasync)
310 {
311         struct inode *inode = dentry->d_inode;
312         struct inode *cache_inode;
313         struct  file open_file;
314         struct  dentry open_dentry;
315         int    rc = 0;
316
317         cache_inode = I2CI(inode);
318         if (!cache_inode)
319                 RETURN(-ENOENT);
320         
321         smfs_prepare_cachefile(inode, file, cache_inode, 
322                                &open_file, &open_dentry);
323
324         if (cache_inode->i_fop->fsync)
325                 rc = cache_inode->i_fop->fsync(&open_file, &open_dentry, datasync);
326         
327         duplicate_inode(cache_inode, inode);
328         smfs_update_file(file, &open_file);
329         
330         RETURN(rc);
331 }
332
333 struct file_operations smfs_file_fops = {
334         llseek:         smfs_llseek,
335         read:           smfs_read,
336         write:          smfs_write,
337         ioctl:          smfs_ioctl,
338         mmap:           smfs_mmap,
339         open:           smfs_open,
340         release:        smfs_release,
341         fsync:          smfs_fsync,
342 };
343
344 static void smfs_prepare_cache_dentry(struct dentry *dentry, struct inode *inode)
345 {
346         atomic_set(&dentry->d_count, 1);
347         dentry->d_vfs_flags = 0;
348         dentry->d_flags = 0;
349         dentry->d_inode = inode;
350         dentry->d_op = NULL;
351         dentry->d_fsdata = NULL;
352         dentry->d_mounted = 0;
353         INIT_LIST_HEAD(&dentry->d_hash);
354         INIT_LIST_HEAD(&dentry->d_lru);
355         INIT_LIST_HEAD(&dentry->d_subdirs);
356         INIT_LIST_HEAD(&dentry->d_alias);
357 }
358
359 static void smfs_truncate(struct inode * inode)      
360 {
361         struct  inode *cache_inode;
362
363         cache_inode = I2CI(inode);
364
365         if (!cache_inode)
366                 return;
367         
368         if (cache_inode->i_op->truncate)
369                 cache_inode->i_op->truncate(cache_inode);
370
371         duplicate_inode(inode, cache_inode);            
372         
373         return; 
374
375  
376 int smfs_setattr(struct dentry *dentry, struct iattr *attr)      
377 {
378         struct  inode *cache_inode;
379         struct  dentry open_dentry;
380
381         int     rc = 0;
382
383         cache_inode = I2CI(dentry->d_inode);
384
385         if (!cache_inode) 
386                 RETURN(-ENOENT);
387         smfs_prepare_cache_dentry(&open_dentry, cache_inode);
388         
389         if (cache_inode->i_op->setattr)
390                 rc = cache_inode->i_op->setattr(&open_dentry, attr);
391
392         RETURN(rc);
393
394   
395 int smfs_setxattr(struct dentry *dentry, const char *name,
396                   const void *value, size_t size, int flags)
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->setattr)
410                 rc = cache_inode->i_op->setxattr(&open_dentry, name, value, size, flags);
411
412         RETURN(rc);
413
414                         
415 int smfs_getxattr(struct dentry *dentry, const char *name,
416                   void *buffer, size_t size)
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->setattr)
430                 rc = cache_inode->i_op->getxattr(&open_dentry, name, buffer, size);
431
432         RETURN(rc);
433 }
434
435 ssize_t smfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
436 {
437         struct  inode *cache_inode;
438         struct  dentry open_dentry;
439         int     rc = 0;
440
441         cache_inode = I2CI(dentry->d_inode);
442
443         if (!cache_inode) 
444                 RETURN(-ENOENT);
445
446         smfs_prepare_cache_dentry(&open_dentry, cache_inode);
447         
448         if (cache_inode->i_op->listxattr)
449                 rc = cache_inode->i_op->listxattr(&open_dentry, buffer, size);
450
451         RETURN(rc);
452 }                                                                                                                                                           
453
454 int smfs_removexattr(struct dentry *dentry, const char *name)
455 {
456         struct  inode *cache_inode;
457         struct  dentry open_dentry;
458         int     rc = 0;
459
460         cache_inode = I2CI(dentry->d_inode);
461
462         if (!cache_inode) 
463                 RETURN(-ENOENT);
464
465         smfs_prepare_cache_dentry(&open_dentry, cache_inode);
466         
467         if (cache_inode->i_op->removexattr)
468                 rc = cache_inode->i_op->removexattr(&open_dentry, name);
469
470         RETURN(rc);
471 }
472
473 struct inode_operations smfs_file_iops = {
474         truncate:       smfs_truncate,          /* BKL held */
475         setattr:        smfs_setattr,           /* BKL held */
476         setxattr:       smfs_setxattr,          /* BKL held */
477         getxattr:       smfs_getxattr,          /* BKL held */
478         listxattr:      smfs_listxattr,         /* BKL held */
479         removexattr:    smfs_removexattr,       /* BKL held */
480 };
481