Whamcloud - gitweb
- landing b_fid.
[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         if (cache_inode->i_fop->open)
305                 rc = cache_inode->i_fop->open(cache_inode, F2CF(filp));
306
307         duplicate_file(filp, F2CF(filp));
308         RETURN(rc);
309 }
310
311 int smfs_release(struct inode *inode, struct file *filp)
312 {
313         struct inode *cache_inode = NULL;
314         struct file *cache_file = NULL;
315         struct smfs_file_info *sfi = NULL;
316         int rc = 0;
317         ENTRY;
318
319         cache_inode = I2CI(inode);
320         if (!cache_inode)
321                 RETURN(-ENOENT);
322         if (filp) {
323                 sfi = F2SMFI(filp);
324                 if (sfi->magic != SMFS_FILE_MAGIC)
325                         LBUG();
326                 cache_file = sfi->c_file;
327         }
328         if (cache_inode->i_fop->release)
329                 rc = cache_inode->i_fop->release(cache_inode, cache_file);
330
331         post_smfs_inode(inode, cache_inode);
332
333         smfs_cleanup_cache_file(filp);
334         RETURN(rc);
335 }
336
337 int smfs_fsync(struct file *file, struct dentry *dentry, int datasync)
338 {
339         struct smfs_file_info *sfi = NULL;
340         struct dentry *cache_dentry = NULL;
341         struct file *cache_file = NULL;
342         struct inode *cache_inode;
343         int rc = 0;
344
345         cache_inode = I2CI(dentry->d_inode);
346         if (!cache_inode)
347                 RETURN(-ENOENT);
348         
349         cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
350         if (!cache_dentry)
351                 RETURN(-ENOMEM);
352
353         if (file) {
354                 sfi = F2SMFI(file);
355                 if (sfi->magic != SMFS_FILE_MAGIC)
356                         LBUG();
357                 cache_file = sfi->c_file;
358         } 
359
360         pre_smfs_inode(dentry->d_inode, cache_inode);
361
362         if (cache_inode->i_fop->fsync) {
363                 rc = cache_inode->i_fop->fsync(cache_file,
364                                                cache_dentry, datasync);
365         
366         }
367         post_smfs_inode(dentry->d_inode, cache_inode);
368         duplicate_file(file, cache_file);
369         post_smfs_dentry(cache_dentry);
370
371         RETURN(rc);
372 }
373
374 struct file_operations smfs_file_fops = {
375         llseek:         smfs_llseek,
376         read:           smfs_read,
377         write:          smfs_write,
378         ioctl:          smfs_ioctl,
379         mmap:           smfs_mmap,
380         open:           smfs_open,
381         release:        smfs_release,
382         fsync:          smfs_fsync,
383 };
384
385 static void smfs_truncate(struct inode *inode)
386 {
387         struct inode *cache_inode;
388
389         cache_inode = I2CI(inode);
390
391         if (!cache_inode)
392                 return;
393
394         if (!cache_inode)
395                 return;
396
397         pre_smfs_inode(inode, cache_inode);
398         if (cache_inode->i_op->truncate)
399                 cache_inode->i_op->truncate(cache_inode);
400
401         post_smfs_inode(inode, cache_inode);
402
403         return;
404 }
405
406 int smfs_setattr(struct dentry *dentry, struct iattr *attr)
407 {
408         struct inode *cache_inode;
409         struct dentry *cache_dentry;
410         void  *handle = NULL;
411         int rc = 0;
412
413         cache_inode = I2CI(dentry->d_inode);
414         if (!cache_inode)
415                 RETURN(-ENOENT);
416
417         cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
418         if (!cache_dentry)
419                 RETURN(-ENOMEM);
420
421         handle = smfs_trans_start(dentry->d_inode, FSFILT_OP_SETATTR, NULL);
422         if (IS_ERR(handle) ) {
423                 CERROR("smfs_do_mkdir: no space for transaction\n");
424                 RETURN(-ENOSPC);
425         }
426
427         pre_smfs_inode(dentry->d_inode, cache_inode);
428
429         if (cache_inode->i_op->setattr)
430                 rc = cache_inode->i_op->setattr(cache_dentry, attr);
431
432         SMFS_HOOK(dentry->d_inode, dentry, attr, NULL, HOOK_SETATTR, NULL, 
433                   POST_HOOK, rc, exit); 
434                   
435 exit:
436         post_smfs_inode(dentry->d_inode, cache_inode);
437         post_smfs_dentry(cache_dentry);
438         smfs_trans_commit(dentry->d_inode, handle, 0);
439         RETURN(rc);
440 }
441
442 int smfs_setxattr(struct dentry *dentry, const char *name, const void *value,
443                   size_t size, int flags)
444 {
445         struct inode *cache_inode;
446         struct dentry *cache_dentry;
447         int rc = 0;
448
449         cache_inode = I2CI(dentry->d_inode);
450         if (!cache_inode)
451                 RETURN(-ENOENT);
452
453         cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
454         if (!cache_dentry)
455                 RETURN(-ENOMEM);
456
457         pre_smfs_inode(dentry->d_inode, cache_inode);
458
459         if (cache_inode->i_op->setxattr)
460                 rc = cache_inode->i_op->setxattr(cache_dentry, name, value,
461                                                  size, flags);
462
463         post_smfs_inode(dentry->d_inode, cache_inode);
464         post_smfs_dentry(cache_dentry);
465
466         RETURN(rc);
467 }
468
469 int smfs_getxattr(struct dentry *dentry, const char *name, void *buffer,
470                   size_t size)
471 {
472         struct inode *cache_inode;
473         struct dentry *cache_dentry;
474         int rc = 0;
475
476         cache_inode = I2CI(dentry->d_inode);
477         if (!cache_inode)
478                 RETURN(-ENOENT);
479
480         cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
481         if (!cache_dentry)
482                 RETURN(-ENOMEM);
483
484         pre_smfs_inode(dentry->d_inode, cache_inode);
485
486         if (cache_inode->i_op->getattr)
487                 rc = cache_inode->i_op->getxattr(cache_dentry, name, buffer,
488                                                  size);
489
490         post_smfs_inode(dentry->d_inode, cache_inode);
491         post_smfs_dentry(cache_dentry);
492
493         RETURN(rc);
494 }
495
496 ssize_t smfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
497 {
498         struct inode *cache_inode;
499         struct dentry *cache_dentry;
500         int rc = 0;
501
502         cache_inode = I2CI(dentry->d_inode);
503         if (!cache_inode)
504                 RETURN(-ENOENT);
505
506         cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
507         if (!cache_dentry)
508                 RETURN(-ENOMEM);
509
510         pre_smfs_inode(dentry->d_inode, cache_inode);
511
512         if (cache_inode->i_op->listxattr)
513                 rc = cache_inode->i_op->listxattr(cache_dentry, buffer, size);
514
515         post_smfs_inode(dentry->d_inode, cache_inode);
516         post_smfs_dentry(cache_dentry);
517
518         RETURN(rc);
519 }
520
521 int smfs_removexattr(struct dentry *dentry, const char *name)
522 {
523         struct inode *cache_inode;
524         struct dentry *cache_dentry;
525         int rc = 0;
526
527         cache_inode = I2CI(dentry->d_inode);
528         if (!cache_inode)
529                 RETURN(-ENOENT);
530
531         cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
532         if (!cache_dentry)
533                 RETURN(-ENOMEM);
534
535         pre_smfs_inode(dentry->d_inode, cache_inode);
536
537         if (cache_inode->i_op->removexattr)
538                 rc = cache_inode->i_op->removexattr(cache_dentry, name);
539
540         post_smfs_inode(dentry->d_inode, cache_inode);
541         post_smfs_dentry(cache_dentry);
542
543         RETURN(rc);
544 }
545
546 struct inode_operations smfs_file_iops = {
547         .truncate       = smfs_truncate,          /* BKL held */
548         .setattr        = smfs_setattr,           /* BKL held */
549         .setxattr       = smfs_setxattr,          /* BKL held */
550         .getxattr       = smfs_getxattr,          /* BKL held */
551         .listxattr      = smfs_listxattr,         /* BKL held */
552         .removexattr    = smfs_removexattr,       /* BKL held */
553 };