Whamcloud - gitweb
1)reorganize the smfs hook ops to make smfs walk a list of hooks ops in hook macro
[fs/lustre-release.git] / lustre / smfs / file.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  lustre/smfs/inode.c
5  *  Lustre filesystem abstraction routines
6  *
7  *  Copyright (C) 2004 Cluster File Systems, Inc.
8  *
9  *   This file is part of Lustre, http://www.lustre.org.
10  *
11  *   Lustre is free software; you can redistribute it and/or
12  *   modify it under the terms of version 2 of the GNU General Public
13  *   License as published by the Free Software Foundation.
14  *
15  *   Lustre is distributed in the hope that it will be useful,
16  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *   GNU General Public License for more details.
19  *
20  *   You should have received a copy of the GNU General Public License
21  *   along with Lustre; if not, write to the Free Software
22  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  */
24
25 #define DEBUG_SUBSYSTEM S_SM
26
27 #include <linux/module.h>
28 #include <linux/kernel.h>
29 #include <linux/string.h>
30 #include <linux/slab.h>
31 #include <linux/stat.h>
32 #include <linux/unistd.h>
33 #include <linux/pagemap.h>
34 #include <linux/file.h>
35 #include <linux/fs.h>
36 #include <linux/obd_class.h>
37 #include <linux/obd_support.h>
38 #include <linux/lustre_lib.h>
39 #include <linux/lustre_idl.h>
40 #include <linux/lustre_fsfilt.h>
41 #include <linux/lustre_smfs.h>
42 #include <linux/lustre_snap.h>
43
44 #include "smfs_internal.h"
45
46 static ssize_t smfs_write(struct file *filp, const char *buf, size_t count,
47                           loff_t *ppos)
48 {
49         struct inode *cache_inode;
50         struct smfs_file_info *sfi;
51         loff_t tmp_ppos;
52         loff_t *cache_ppos;
53         int rc = 0;
54         ENTRY;
55
56         cache_inode = I2CI(filp->f_dentry->d_inode);
57
58         if (!cache_inode)
59                 RETURN(-ENOENT);
60
61         sfi = F2SMFI(filp);
62
63         if (sfi->magic != SMFS_FILE_MAGIC) 
64                 LBUG();
65
66         if (filp->f_flags & O_APPEND)
67                 tmp_ppos = filp->f_dentry->d_inode->i_size;
68         else {
69                 tmp_ppos = *ppos;
70         }
71         SMFS_HOOK(filp->f_dentry->d_inode, filp->f_dentry, &count, &tmp_ppos,
72                   HOOK_WRITE, NULL, PRE_HOOK, rc, exit);
73
74         if (ppos != &(filp->f_pos)) {
75                 cache_ppos = &tmp_ppos;
76         } else {
77                 cache_ppos = &sfi->c_file->f_pos;
78         }
79         *cache_ppos = *ppos;
80
81         pre_smfs_inode(filp->f_dentry->d_inode, cache_inode);
82
83         if (cache_inode->i_fop->write) {
84                 rc = cache_inode->i_fop->write(sfi->c_file, buf,
85                                                count, cache_ppos);
86         }
87
88         SMFS_HOOK(filp->f_dentry->d_inode, filp->f_dentry, ppos, &count,
89                   HOOK_WRITE, NULL, POST_HOOK, rc, exit);
90 exit:
91         post_smfs_inode(filp->f_dentry->d_inode, cache_inode);
92         *ppos = *cache_ppos;
93         duplicate_file(filp, sfi->c_file);
94         RETURN(rc);
95 }
96
97 int smfs_ioctl(struct inode * inode, struct file * filp,
98                unsigned int cmd, unsigned long arg)
99 {
100         struct        inode *cache_inode;
101         struct  smfs_file_info *sfi;
102         ssize_t rc = 0;
103
104         ENTRY;
105
106         cache_inode = I2CI(filp->f_dentry->d_inode);
107         if (!cache_inode)
108                 RETURN(-ENOENT);
109
110         sfi = F2SMFI(filp);
111         if (sfi->magic != SMFS_FILE_MAGIC) 
112                 LBUG();
113
114         pre_smfs_inode(inode, cache_inode);
115
116         if (cache_inode->i_fop->ioctl) {
117                 rc = cache_inode->i_fop->ioctl(cache_inode,
118                                                sfi->c_file, cmd, arg);
119         }
120
121         post_smfs_inode(inode, cache_inode);
122         duplicate_file(filp, sfi->c_file);
123
124         RETURN(rc);
125 }
126
127 static ssize_t smfs_read(struct file *filp, char *buf,
128                          size_t count, loff_t *ppos)
129 {
130         struct        inode *cache_inode;
131         struct  smfs_file_info *sfi;
132         loff_t  tmp_ppos;
133         loff_t  *cache_ppos;
134         ssize_t rc = 0;
135
136         ENTRY;
137
138         cache_inode = I2CI(filp->f_dentry->d_inode);
139         if (!cache_inode)
140                 RETURN(-ENOENT);
141
142         sfi = F2SMFI(filp);
143         if (sfi->magic != SMFS_FILE_MAGIC) 
144                 LBUG();
145
146         if (ppos != &(filp->f_pos)) {
147                 cache_ppos = &tmp_ppos;
148         } else {
149                 cache_ppos = &sfi->c_file->f_pos;
150         }
151         *cache_ppos = *ppos;
152
153         pre_smfs_inode(filp->f_dentry->d_inode, cache_inode);
154
155         if (cache_inode->i_fop->read) {
156                 rc = cache_inode->i_fop->read(sfi->c_file, buf,
157                                               count, cache_ppos);
158         }
159
160         *ppos = *cache_ppos;
161         post_smfs_inode(filp->f_dentry->d_inode, cache_inode);
162         duplicate_file(filp, sfi->c_file);
163
164         RETURN(rc);
165 }
166
167 static loff_t smfs_llseek(struct file *file,
168                           loff_t offset,
169                           int origin)
170 {
171         struct        inode *cache_inode;
172         struct  smfs_file_info *sfi;
173         ssize_t rc = 0;
174
175         ENTRY;
176
177         cache_inode = I2CI(file->f_dentry->d_inode);
178         if (!cache_inode)
179                 RETURN(-ENOENT);
180
181         sfi = F2SMFI(file);
182         if (sfi->magic != SMFS_FILE_MAGIC) 
183                 LBUG();
184
185         pre_smfs_inode(file->f_dentry->d_inode, cache_inode);
186
187         if (cache_inode->i_fop->llseek) {
188                 rc = cache_inode->i_fop->llseek(sfi->c_file,
189                                                 offset, origin);
190         }
191
192         post_smfs_inode(file->f_dentry->d_inode, cache_inode);
193         duplicate_file(file, sfi->c_file);
194
195         RETURN(rc);
196 }
197
198 static int smfs_mmap(struct file *file, struct vm_area_struct *vma)
199 {
200         struct inode *inode = file->f_dentry->d_inode;
201         struct smfs_file_info *sfi;
202         struct inode *cache_inode = NULL;
203         int rc = 0;
204         ENTRY;
205
206         cache_inode = I2CI(inode);
207         if (!cache_inode)
208                 RETURN(-ENOENT);
209
210         sfi = F2SMFI(file);
211         if (sfi->magic != SMFS_FILE_MAGIC)
212                 LBUG();
213
214         if (cache_inode->i_mapping == &cache_inode->i_data)
215                 inode->i_mapping = cache_inode->i_mapping;
216
217         pre_smfs_inode(inode, cache_inode);
218         if (cache_inode->i_fop->mmap)
219                 rc = cache_inode->i_fop->mmap(sfi->c_file, vma);
220
221         post_smfs_inode(inode, cache_inode);
222         duplicate_file(file, sfi->c_file);
223
224         RETURN(rc);
225 }
226
227 static int smfs_init_cache_file(struct inode *inode, struct file *filp)
228 {
229         struct smfs_file_info *sfi = NULL;
230         struct file *cache_filp = NULL;
231         struct dentry *cache_dentry = NULL;
232         int rc = 0;
233         ENTRY;
234
235         OBD_ALLOC(sfi, sizeof(struct smfs_file_info));
236         if (!sfi)
237                 RETURN(-ENOMEM);
238
239         cache_filp = get_empty_filp();
240         if (!cache_filp)
241                 GOTO(err_exit, rc = -ENOMEM);
242
243         sfi->magic = SMFS_FILE_MAGIC;
244
245         cache_dentry = pre_smfs_dentry(NULL, I2CI(inode), filp->f_dentry);
246         if (!cache_dentry)
247                 GOTO(err_exit, rc = -ENOMEM);
248
249         cache_filp->f_vfsmnt = filp->f_vfsmnt;
250
251         cache_filp->f_dentry = cache_dentry;
252         duplicate_file(cache_filp, filp);
253
254         sfi->c_file = cache_filp;
255
256         if (filp->private_data != NULL)
257                 LBUG();
258
259         filp->private_data = sfi;
260
261         RETURN(rc);
262 err_exit:
263         if (sfi)
264                 OBD_FREE(sfi, sizeof(struct smfs_file_info));
265         if (cache_filp)
266                 put_filp(cache_filp);
267         RETURN(rc);
268 }
269
270 static int smfs_cleanup_cache_file(struct file *filp)
271 {
272         struct smfs_file_info *sfi = NULL;
273         int rc = 0;
274         ENTRY;
275
276         if (!filp)
277                 RETURN(rc);
278         sfi = F2SMFI(filp);
279
280         post_smfs_dentry(sfi->c_file->f_dentry);
281
282         put_filp(sfi->c_file);
283
284         OBD_FREE(sfi, sizeof(struct smfs_file_info));
285
286         filp->private_data = NULL;
287
288         RETURN(rc);
289 }
290
291 int smfs_open(struct inode *inode, struct file *filp)
292 {
293         struct inode *cache_inode = NULL;
294         int rc = 0;
295         ENTRY;
296
297         cache_inode = I2CI(inode);
298         if (!cache_inode)
299                 RETURN(-ENOENT);
300
301         if ((rc = smfs_init_cache_file(inode, filp)))
302                 RETURN(rc);
303
304         pre_smfs_inode(inode, cache_inode);
305         if (cache_inode->i_fop->open)
306                 rc = cache_inode->i_fop->open(cache_inode, F2CF(filp));
307
308         post_smfs_inode(inode, cache_inode);
309         duplicate_file(filp, F2CF(filp));
310         RETURN(rc);
311 }
312
313 int smfs_release(struct inode *inode, struct file *filp)
314 {
315         struct inode *cache_inode = NULL;
316         struct file *cache_file = NULL;
317         struct smfs_file_info *sfi = NULL;
318         int rc = 0;
319         ENTRY;
320
321         cache_inode = I2CI(inode);
322         if (!cache_inode)
323                 RETURN(-ENOENT);
324         if (filp) {
325                 sfi = F2SMFI(filp);
326                 if (sfi->magic != SMFS_FILE_MAGIC)
327                         LBUG();
328                 cache_file = sfi->c_file;
329         }
330         pre_smfs_inode(inode, cache_inode);
331         if (cache_inode->i_fop->release)
332                 rc = cache_inode->i_fop->release(cache_inode, cache_file);
333
334         post_smfs_inode(inode, cache_inode);
335         duplicate_file(filp, cache_file);
336
337         smfs_cleanup_cache_file(filp);
338         RETURN(rc);
339 }
340
341 int smfs_fsync(struct file *file, struct dentry *dentry, int datasync)
342 {
343         struct smfs_file_info *sfi = NULL;
344         struct dentry *cache_dentry = NULL;
345         struct file *cache_file = NULL;
346         struct inode *cache_inode;
347         int rc = 0;
348
349         cache_inode = I2CI(dentry->d_inode);
350         if (!cache_inode)
351                 RETURN(-ENOENT);
352         
353         cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
354         if (!cache_dentry)
355                 RETURN(-ENOMEM);
356
357         if (file) {
358                 sfi = F2SMFI(file);
359                 if (sfi->magic != SMFS_FILE_MAGIC)
360                         LBUG();
361                 cache_file = sfi->c_file;
362         } 
363
364         pre_smfs_inode(dentry->d_inode, cache_inode);
365
366         if (cache_inode->i_fop->fsync) {
367                 rc = cache_inode->i_fop->fsync(cache_file,
368                                                cache_dentry, datasync);
369         
370         }
371         post_smfs_inode(dentry->d_inode, cache_inode);
372         duplicate_file(file, cache_file);
373         post_smfs_dentry(cache_dentry);
374
375         RETURN(rc);
376 }
377
378 struct file_operations smfs_file_fops = {
379         llseek:         smfs_llseek,
380         read:           smfs_read,
381         write:          smfs_write,
382         ioctl:          smfs_ioctl,
383         mmap:           smfs_mmap,
384         open:           smfs_open,
385         release:        smfs_release,
386         fsync:          smfs_fsync,
387 };
388
389 static void smfs_truncate(struct inode *inode)
390 {
391         struct inode *cache_inode;
392
393         cache_inode = I2CI(inode);
394
395         if (!cache_inode)
396                 return;
397
398         if (!cache_inode)
399                 return;
400
401         pre_smfs_inode(inode, cache_inode);
402         if (cache_inode->i_op->truncate)
403                 cache_inode->i_op->truncate(cache_inode);
404
405         post_smfs_inode(inode, cache_inode);
406
407         return;
408 }
409
410 int smfs_setattr(struct dentry *dentry, struct iattr *attr)
411 {
412         struct inode *cache_inode;
413         struct dentry *cache_dentry;
414         void  *handle = NULL;
415         int rc = 0;
416
417         cache_inode = I2CI(dentry->d_inode);
418         if (!cache_inode)
419                 RETURN(-ENOENT);
420
421         cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
422         if (!cache_dentry)
423                 RETURN(-ENOMEM);
424
425         handle = smfs_trans_start(dentry->d_inode, FSFILT_OP_SETATTR, NULL);
426         if (IS_ERR(handle) ) {
427                 CERROR("smfs_do_mkdir: no space for transaction\n");
428                 RETURN(-ENOSPC);
429         }
430
431         pre_smfs_inode(dentry->d_inode, cache_inode);
432
433         if (cache_inode->i_op->setattr)
434                 rc = cache_inode->i_op->setattr(cache_dentry, attr);
435
436         SMFS_HOOK(dentry->d_inode, dentry, attr, NULL, HOOK_SETATTR, NULL, 
437                   POST_HOOK, rc, exit); 
438                   
439 exit:
440         post_smfs_inode(dentry->d_inode, cache_inode);
441         post_smfs_dentry(cache_dentry);
442         smfs_trans_commit(dentry->d_inode, handle, 0);
443         RETURN(rc);
444 }
445
446 int smfs_setxattr(struct dentry *dentry, const char *name, const void *value,
447                   size_t size, int flags)
448 {
449         struct inode *cache_inode;
450         struct dentry *cache_dentry;
451         int rc = 0;
452
453         cache_inode = I2CI(dentry->d_inode);
454         if (!cache_inode)
455                 RETURN(-ENOENT);
456
457         cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
458         if (!cache_dentry)
459                 RETURN(-ENOMEM);
460
461         pre_smfs_inode(dentry->d_inode, cache_inode);
462
463         if (cache_inode->i_op->setxattr)
464                 rc = cache_inode->i_op->setxattr(cache_dentry, name, value,
465                                                  size, flags);
466
467         post_smfs_inode(dentry->d_inode, cache_inode);
468         post_smfs_dentry(cache_dentry);
469
470         RETURN(rc);
471 }
472
473 int smfs_getxattr(struct dentry *dentry, const char *name, void *buffer,
474                   size_t size)
475 {
476         struct inode *cache_inode;
477         struct dentry *cache_dentry;
478         int rc = 0;
479
480         cache_inode = I2CI(dentry->d_inode);
481         if (!cache_inode)
482                 RETURN(-ENOENT);
483
484         cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
485         if (!cache_dentry)
486                 RETURN(-ENOMEM);
487
488         pre_smfs_inode(dentry->d_inode, cache_inode);
489
490         if (cache_inode->i_op->getattr)
491                 rc = cache_inode->i_op->getxattr(cache_dentry, name, buffer,
492                                                  size);
493
494         post_smfs_inode(dentry->d_inode, cache_inode);
495         post_smfs_dentry(cache_dentry);
496
497         RETURN(rc);
498 }
499
500 ssize_t smfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
501 {
502         struct inode *cache_inode;
503         struct dentry *cache_dentry;
504         int rc = 0;
505
506         cache_inode = I2CI(dentry->d_inode);
507         if (!cache_inode)
508                 RETURN(-ENOENT);
509
510         cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
511         if (!cache_dentry)
512                 RETURN(-ENOMEM);
513
514         pre_smfs_inode(dentry->d_inode, cache_inode);
515
516         if (cache_inode->i_op->listxattr)
517                 rc = cache_inode->i_op->listxattr(cache_dentry, buffer, size);
518
519         post_smfs_inode(dentry->d_inode, cache_inode);
520         post_smfs_dentry(cache_dentry);
521
522         RETURN(rc);
523 }
524
525 int smfs_removexattr(struct dentry *dentry, const char *name)
526 {
527         struct inode *cache_inode;
528         struct dentry *cache_dentry;
529         int rc = 0;
530
531         cache_inode = I2CI(dentry->d_inode);
532         if (!cache_inode)
533                 RETURN(-ENOENT);
534
535         cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
536         if (!cache_dentry)
537                 RETURN(-ENOMEM);
538
539         pre_smfs_inode(dentry->d_inode, cache_inode);
540
541         if (cache_inode->i_op->removexattr)
542                 rc = cache_inode->i_op->removexattr(cache_dentry, name);
543
544         post_smfs_inode(dentry->d_inode, cache_inode);
545         post_smfs_dentry(cache_dentry);
546
547         RETURN(rc);
548 }
549
550 struct inode_operations smfs_file_iops = {
551         truncate:       smfs_truncate,          /* BKL held */
552         setattr:        smfs_setattr,           /* BKL held */
553         setxattr:       smfs_setxattr,          /* BKL held */
554         getxattr:       smfs_getxattr,          /* BKL held */
555         listxattr:      smfs_listxattr,         /* BKL held */
556         removexattr:    smfs_removexattr,       /* BKL held */
557 };