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