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