Whamcloud - gitweb
af1e1f5f7d50f5f2d8da722726ab3eec077886e5
[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
43 #include "smfs_internal.h"
44
45 static ssize_t smfs_write(struct file *filp, const char *buf, size_t count,
46                           loff_t *ppos)
47 {
48         struct inode *cache_inode;
49         struct smfs_file_info *sfi;
50         loff_t tmp_ppos;
51         loff_t *cache_ppos;
52         int rc = 0;
53         ENTRY;
54
55         cache_inode = I2CI(filp->f_dentry->d_inode);
56
57         if (!cache_inode)
58                 RETURN(-ENOENT);
59
60         sfi = F2SMFI(filp);
61
62         if (sfi->magic != SMFS_FILE_MAGIC) 
63                 LBUG();
64
65         if (ppos != &(filp->f_pos)) {
66                 cache_ppos = &tmp_ppos;
67         } else {
68                 cache_ppos = &sfi->c_file->f_pos;
69         }
70         *cache_ppos = *ppos;
71
72         pre_smfs_inode(filp->f_dentry->d_inode, cache_inode);
73
74         if (cache_inode->i_fop->write) {
75                 rc = cache_inode->i_fop->write(sfi->c_file, buf,
76                                                count, cache_ppos);
77         }
78
79         SMFS_KML_POST(filp->f_dentry->d_inode, filp->f_dentry,
80                       ppos, &count, REINT_WRITE, "write", rc, exit);
81 exit:
82         post_smfs_inode(filp->f_dentry->d_inode, cache_inode);
83         *ppos = *cache_ppos;
84         duplicate_file(filp, sfi->c_file);
85         RETURN(rc);
86 }
87
88 int smfs_ioctl(struct inode * inode, struct file * filp,
89                unsigned int cmd, unsigned long arg)
90 {
91         struct        inode *cache_inode;
92         struct  smfs_file_info *sfi;
93         ssize_t rc = 0;
94
95         ENTRY;
96
97         cache_inode = I2CI(filp->f_dentry->d_inode);
98         if (!cache_inode)
99                 RETURN(-ENOENT);
100
101         sfi = F2SMFI(filp);
102         if (sfi->magic != SMFS_FILE_MAGIC) 
103                 LBUG();
104
105         pre_smfs_inode(inode, cache_inode);
106
107         if (cache_inode->i_fop->ioctl) {
108                 rc = cache_inode->i_fop->ioctl(cache_inode,
109                                                sfi->c_file, cmd, arg);
110         }
111
112         post_smfs_inode(inode, cache_inode);
113         duplicate_file(filp, sfi->c_file);
114
115         RETURN(rc);
116 }
117
118 static ssize_t smfs_read(struct file *filp, char *buf,
119                          size_t count, loff_t *ppos)
120 {
121         struct        inode *cache_inode;
122         struct  smfs_file_info *sfi;
123         loff_t  tmp_ppos;
124         loff_t  *cache_ppos;
125         ssize_t rc = 0;
126
127         ENTRY;
128
129         cache_inode = I2CI(filp->f_dentry->d_inode);
130         if (!cache_inode)
131                 RETURN(-ENOENT);
132
133         sfi = F2SMFI(filp);
134         if (sfi->magic != SMFS_FILE_MAGIC) 
135                 LBUG();
136
137         if (ppos != &(filp->f_pos)) {
138                 cache_ppos = &tmp_ppos;
139         } else {
140                 cache_ppos = &sfi->c_file->f_pos;
141         }
142         *cache_ppos = *ppos;
143
144         pre_smfs_inode(filp->f_dentry->d_inode, cache_inode);
145
146         if (cache_inode->i_fop->read) {
147                 rc = cache_inode->i_fop->read(sfi->c_file, buf,
148                                               count, cache_ppos);
149         }
150
151         *ppos = *cache_ppos;
152         post_smfs_inode(filp->f_dentry->d_inode, cache_inode);
153         duplicate_file(filp, sfi->c_file);
154
155         RETURN(rc);
156 }
157
158 static loff_t smfs_llseek(struct file *file,
159                           loff_t offset,
160                           int origin)
161 {
162         struct        inode *cache_inode;
163         struct  smfs_file_info *sfi;
164         ssize_t rc = 0;
165
166         ENTRY;
167
168         cache_inode = I2CI(file->f_dentry->d_inode);
169         if (!cache_inode)
170                 RETURN(-ENOENT);
171
172         sfi = F2SMFI(file);
173         if (sfi->magic != SMFS_FILE_MAGIC) 
174                 LBUG();
175
176         pre_smfs_inode(file->f_dentry->d_inode, cache_inode);
177
178         if (cache_inode->i_fop->llseek) {
179                 rc = cache_inode->i_fop->llseek(sfi->c_file,
180                                                 offset, origin);
181         }
182
183         post_smfs_inode(file->f_dentry->d_inode, cache_inode);
184         duplicate_file(file, sfi->c_file);
185
186         RETURN(rc);
187 }
188
189 static int smfs_mmap(struct file *file, struct vm_area_struct *vma)
190 {
191         struct inode *inode = file->f_dentry->d_inode;
192         struct smfs_file_info *sfi;
193         struct inode *cache_inode = NULL;
194         int rc = 0;
195         ENTRY;
196
197         cache_inode = I2CI(inode);
198         if (!cache_inode)
199                 RETURN(-ENOENT);
200
201         sfi = F2SMFI(file);
202         if (sfi->magic != SMFS_FILE_MAGIC)
203                 LBUG();
204
205         if (cache_inode->i_mapping == &cache_inode->i_data)
206                 inode->i_mapping = cache_inode->i_mapping;
207
208         pre_smfs_inode(inode, cache_inode);
209         if (cache_inode->i_fop->mmap)
210                 rc = cache_inode->i_fop->mmap(sfi->c_file, vma);
211
212         post_smfs_inode(inode, cache_inode);
213         duplicate_file(file, sfi->c_file);
214
215         RETURN(rc);
216 }
217
218 static int smfs_init_cache_file(struct inode *inode, struct file *filp)
219 {
220         struct smfs_file_info *sfi = NULL;
221         struct file *cache_filp = NULL;
222         struct dentry *cache_dentry = NULL;
223         int rc = 0;
224         ENTRY;
225
226         OBD_ALLOC(sfi, sizeof(struct smfs_file_info));
227         if (!sfi)
228                 RETURN(-ENOMEM);
229
230         cache_filp = get_empty_filp();
231         if (!cache_filp)
232                 GOTO(err_exit, rc = -ENOMEM);
233
234         sfi->magic = SMFS_FILE_MAGIC;
235
236         cache_dentry = pre_smfs_dentry(NULL, I2CI(inode), filp->f_dentry);
237         if (!cache_dentry)
238                 GOTO(err_exit, rc = -ENOMEM);
239
240         cache_filp->f_vfsmnt = filp->f_vfsmnt;
241
242         cache_filp->f_dentry = cache_dentry;
243         duplicate_file(cache_filp, filp);
244
245         sfi->c_file = cache_filp;
246
247         if (filp->private_data != NULL)
248                 LBUG();
249
250         filp->private_data = sfi;
251
252         RETURN(rc);
253 err_exit:
254         if (sfi)
255                 OBD_FREE(sfi, sizeof(struct smfs_file_info));
256         if (cache_filp)
257                 put_filp(cache_filp);
258         RETURN(rc);
259 }
260
261 static int smfs_cleanup_cache_file(struct file *filp)
262 {
263         struct smfs_file_info *sfi = NULL;
264         int rc = 0;
265         ENTRY;
266
267         if (!filp)
268                 RETURN(rc);
269         sfi = F2SMFI(filp);
270
271         post_smfs_dentry(sfi->c_file->f_dentry);
272
273         put_filp(sfi->c_file);
274
275         OBD_FREE(sfi, sizeof(struct smfs_file_info));
276
277         filp->private_data = NULL;
278
279         RETURN(rc);
280 }
281
282 int smfs_open(struct inode *inode, struct file *filp)
283 {
284         struct inode *cache_inode = NULL;
285         int rc = 0;
286         ENTRY;
287
288         cache_inode = I2CI(inode);
289         if (!cache_inode)
290                 RETURN(-ENOENT);
291
292         if ((rc = smfs_init_cache_file(inode, filp)))
293                 RETURN(rc);
294
295         pre_smfs_inode(inode, cache_inode);
296         if (cache_inode->i_fop->open)
297                 rc = cache_inode->i_fop->open(cache_inode, F2CF(filp));
298
299         post_smfs_inode(inode, cache_inode);
300         duplicate_file(filp, F2CF(filp));
301         RETURN(rc);
302 }
303
304 int smfs_release(struct inode *inode, struct file *filp)
305 {
306         struct inode *cache_inode = NULL;
307         struct file *cache_file = NULL;
308         struct smfs_file_info *sfi = NULL;
309         int rc = 0;
310         ENTRY;
311
312         cache_inode = I2CI(inode);
313         if (!cache_inode)
314                 RETURN(-ENOENT);
315         if (filp) {
316                 sfi = F2SMFI(filp);
317                 if (sfi->magic != SMFS_FILE_MAGIC)
318                         LBUG();
319                 cache_file = sfi->c_file;
320         }
321         pre_smfs_inode(inode, cache_inode);
322         if (cache_inode->i_fop->release)
323                 rc = cache_inode->i_fop->release(cache_inode, cache_file);
324
325         post_smfs_inode(inode, cache_inode);
326         duplicate_file(filp, cache_file);
327
328         smfs_cleanup_cache_file(filp);
329         RETURN(rc);
330 }
331
332 int smfs_fsync(struct file *file, struct dentry *dentry, int datasync)
333 {
334         struct smfs_file_info *sfi = NULL;
335         struct dentry *cache_dentry = NULL;
336         struct file *cache_file = NULL;
337         struct inode *cache_inode;
338         int rc = 0;
339
340         cache_inode = I2CI(dentry->d_inode);
341         if (!cache_inode)
342                 RETURN(-ENOENT);
343         
344         cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
345         if (!cache_dentry)
346                 RETURN(-ENOMEM);
347
348         if (file) {
349                 sfi = F2SMFI(file);
350                 if (sfi->magic != SMFS_FILE_MAGIC)
351                         LBUG();
352                 cache_file = sfi->c_file;
353         } 
354
355         pre_smfs_inode(dentry->d_inode, cache_inode);
356
357         if (cache_inode->i_fop->fsync) {
358                 rc = cache_inode->i_fop->fsync(cache_file,
359                                                cache_dentry, datasync);
360         
361         }
362         post_smfs_inode(dentry->d_inode, cache_inode);
363         duplicate_file(file, cache_file);
364         post_smfs_dentry(cache_dentry);
365
366         RETURN(rc);
367 }
368
369 struct file_operations smfs_file_fops = {
370         llseek:         smfs_llseek,
371         read:           smfs_read,
372         write:          smfs_write,
373         ioctl:          smfs_ioctl,
374         mmap:           smfs_mmap,
375         open:           smfs_open,
376         release:        smfs_release,
377         fsync:          smfs_fsync,
378 };
379
380 static void smfs_truncate(struct inode *inode)
381 {
382         struct inode *cache_inode;
383
384         cache_inode = I2CI(inode);
385
386         if (!cache_inode)
387                 return;
388
389         if (!cache_inode)
390                 return;
391
392         pre_smfs_inode(inode, cache_inode);
393         if (cache_inode->i_op->truncate)
394                 cache_inode->i_op->truncate(cache_inode);
395
396         post_smfs_inode(inode, cache_inode);
397
398         return;
399 }
400
401 int smfs_setattr(struct dentry *dentry, struct iattr *attr)
402 {
403         struct inode *cache_inode;
404         struct dentry *cache_dentry;
405         void  *handle = NULL;
406         int rc = 0;
407
408         cache_inode = I2CI(dentry->d_inode);
409         if (!cache_inode)
410                 RETURN(-ENOENT);
411
412         cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
413         if (!cache_dentry)
414                 RETURN(-ENOMEM);
415
416         handle = smfs_trans_start(dentry->d_inode, FSFILT_OP_SETATTR, NULL);
417         if (IS_ERR(handle) ) {
418                 CERROR("smfs_do_mkdir: no space for transaction\n");
419                 RETURN(-ENOSPC);
420         }
421
422         pre_smfs_inode(dentry->d_inode, cache_inode);
423
424         if (cache_inode->i_op->setattr)
425                 rc = cache_inode->i_op->setattr(cache_dentry, attr);
426
427         SMFS_KML_POST(dentry->d_inode, dentry, attr, NULL,
428                       REINT_SETATTR, "setattr", rc, exit);
429 exit:
430         post_smfs_inode(dentry->d_inode, cache_inode);
431         post_smfs_dentry(cache_dentry);
432         smfs_trans_commit(dentry->d_inode, handle, 0);
433         RETURN(rc);
434 }
435
436 int smfs_setxattr(struct dentry *dentry, const char *name, const void *value,
437                   size_t size, int flags)
438 {
439         struct inode *cache_inode;
440         struct dentry *cache_dentry;
441         int rc = 0;
442
443         cache_inode = I2CI(dentry->d_inode);
444         if (!cache_inode)
445                 RETURN(-ENOENT);
446
447         cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
448         if (!cache_dentry)
449                 RETURN(-ENOMEM);
450
451         pre_smfs_inode(dentry->d_inode, cache_inode);
452
453         if (cache_inode->i_op->setxattr)
454                 rc = cache_inode->i_op->setxattr(cache_dentry, name, value,
455                                                  size, flags);
456
457         post_smfs_inode(dentry->d_inode, cache_inode);
458         post_smfs_dentry(cache_dentry);
459
460         RETURN(rc);
461 }
462
463 int smfs_getxattr(struct dentry *dentry, const char *name, void *buffer,
464                   size_t size)
465 {
466         struct inode *cache_inode;
467         struct dentry *cache_dentry;
468         int rc = 0;
469
470         cache_inode = I2CI(dentry->d_inode);
471         if (!cache_inode)
472                 RETURN(-ENOENT);
473
474         cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
475         if (!cache_dentry)
476                 RETURN(-ENOMEM);
477
478         pre_smfs_inode(dentry->d_inode, cache_inode);
479
480         if (cache_inode->i_op->getattr)
481                 rc = cache_inode->i_op->getxattr(cache_dentry, name, buffer,
482                                                  size);
483
484         post_smfs_inode(dentry->d_inode, cache_inode);
485         post_smfs_dentry(cache_dentry);
486
487         RETURN(rc);
488 }
489
490 ssize_t smfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
491 {
492         struct inode *cache_inode;
493         struct dentry *cache_dentry;
494         int rc = 0;
495
496         cache_inode = I2CI(dentry->d_inode);
497         if (!cache_inode)
498                 RETURN(-ENOENT);
499
500         cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
501         if (!cache_dentry)
502                 RETURN(-ENOMEM);
503
504         pre_smfs_inode(dentry->d_inode, cache_inode);
505
506         if (cache_inode->i_op->listxattr)
507                 rc = cache_inode->i_op->listxattr(cache_dentry, buffer, size);
508
509         post_smfs_inode(dentry->d_inode, cache_inode);
510         post_smfs_dentry(cache_dentry);
511
512         RETURN(rc);
513 }
514
515 int smfs_removexattr(struct dentry *dentry, const char *name)
516 {
517         struct inode *cache_inode;
518         struct dentry *cache_dentry;
519         int rc = 0;
520
521         cache_inode = I2CI(dentry->d_inode);
522         if (!cache_inode)
523                 RETURN(-ENOENT);
524
525         cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
526         if (!cache_dentry)
527                 RETURN(-ENOMEM);
528
529         pre_smfs_inode(dentry->d_inode, cache_inode);
530
531         if (cache_inode->i_op->removexattr)
532                 rc = cache_inode->i_op->removexattr(cache_dentry, name);
533
534         post_smfs_inode(dentry->d_inode, cache_inode);
535         post_smfs_dentry(cache_dentry);
536
537         RETURN(rc);
538 }
539
540 struct inode_operations smfs_file_iops = {
541         truncate:       smfs_truncate,          /* BKL held */
542         setattr:        smfs_setattr,           /* BKL held */
543         setxattr:       smfs_setxattr,          /* BKL held */
544         getxattr:       smfs_getxattr,          /* BKL held */
545         listxattr:      smfs_listxattr,         /* BKL held */
546         removexattr:    smfs_removexattr,       /* BKL held */
547 };