Whamcloud - gitweb
b=3869,1742
[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
72         SMFS_PRE_COW(filp->f_dentry->d_inode, filp->f_dentry, &count, &tmp_ppos, 
73                      REINT_WRITE, "write", 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         *cache_ppos = *ppos;
81
82         pre_smfs_inode(filp->f_dentry->d_inode, cache_inode);
83
84         if (cache_inode->i_fop->write) {
85                 rc = cache_inode->i_fop->write(sfi->c_file, buf,
86                                                count, cache_ppos);
87         }
88
89         SMFS_KML_POST(filp->f_dentry->d_inode, filp->f_dentry,
90                       ppos, &count, REINT_WRITE, "write", rc, exit);
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)
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         if (cache_inode->i_fop->ioctl) {
118                 rc = cache_inode->i_fop->ioctl(cache_inode,
119                                                sfi->c_file, cmd, arg);
120         }
121
122         post_smfs_inode(inode, cache_inode);
123         duplicate_file(filp, sfi->c_file);
124
125         RETURN(rc);
126 }
127
128 static ssize_t smfs_read(struct file *filp, char *buf,
129                          size_t count, loff_t *ppos)
130 {
131         struct        inode *cache_inode;
132         struct  smfs_file_info *sfi;
133         loff_t  tmp_ppos;
134         loff_t  *cache_ppos;
135         ssize_t rc = 0;
136
137         ENTRY;
138
139         cache_inode = I2CI(filp->f_dentry->d_inode);
140         if (!cache_inode)
141                 RETURN(-ENOENT);
142
143         sfi = F2SMFI(filp);
144         if (sfi->magic != SMFS_FILE_MAGIC) 
145                 LBUG();
146
147         if (ppos != &(filp->f_pos)) {
148                 cache_ppos = &tmp_ppos;
149         } else {
150                 cache_ppos = &sfi->c_file->f_pos;
151         }
152         *cache_ppos = *ppos;
153
154         pre_smfs_inode(filp->f_dentry->d_inode, cache_inode);
155
156         if (cache_inode->i_fop->read) {
157                 rc = cache_inode->i_fop->read(sfi->c_file, buf,
158                                               count, cache_ppos);
159         }
160
161         *ppos = *cache_ppos;
162         post_smfs_inode(filp->f_dentry->d_inode, cache_inode);
163         duplicate_file(filp, sfi->c_file);
164
165         RETURN(rc);
166 }
167
168 static loff_t smfs_llseek(struct file *file,
169                           loff_t offset,
170                           int origin)
171 {
172         struct        inode *cache_inode;
173         struct  smfs_file_info *sfi;
174         ssize_t rc = 0;
175
176         ENTRY;
177
178         cache_inode = I2CI(file->f_dentry->d_inode);
179         if (!cache_inode)
180                 RETURN(-ENOENT);
181
182         sfi = F2SMFI(file);
183         if (sfi->magic != SMFS_FILE_MAGIC) 
184                 LBUG();
185
186         pre_smfs_inode(file->f_dentry->d_inode, cache_inode);
187
188         if (cache_inode->i_fop->llseek) {
189                 rc = cache_inode->i_fop->llseek(sfi->c_file,
190                                                 offset, origin);
191         }
192
193         post_smfs_inode(file->f_dentry->d_inode, cache_inode);
194         duplicate_file(file, sfi->c_file);
195
196         RETURN(rc);
197 }
198
199 static int smfs_mmap(struct file *file, struct vm_area_struct *vma)
200 {
201         struct inode *inode = file->f_dentry->d_inode;
202         struct smfs_file_info *sfi;
203         struct inode *cache_inode = NULL;
204         int rc = 0;
205         ENTRY;
206
207         cache_inode = I2CI(inode);
208         if (!cache_inode)
209                 RETURN(-ENOENT);
210
211         sfi = F2SMFI(file);
212         if (sfi->magic != SMFS_FILE_MAGIC)
213                 LBUG();
214
215         if (cache_inode->i_mapping == &cache_inode->i_data)
216                 inode->i_mapping = cache_inode->i_mapping;
217
218         pre_smfs_inode(inode, cache_inode);
219         if (cache_inode->i_fop->mmap)
220                 rc = cache_inode->i_fop->mmap(sfi->c_file, vma);
221
222         post_smfs_inode(inode, cache_inode);
223         duplicate_file(file, sfi->c_file);
224
225         RETURN(rc);
226 }
227
228 static int smfs_init_cache_file(struct inode *inode, struct file *filp)
229 {
230         struct smfs_file_info *sfi = NULL;
231         struct file *cache_filp = NULL;
232         struct dentry *cache_dentry = NULL;
233         int rc = 0;
234         ENTRY;
235
236         OBD_ALLOC(sfi, sizeof(struct smfs_file_info));
237         if (!sfi)
238                 RETURN(-ENOMEM);
239
240         cache_filp = get_empty_filp();
241         if (!cache_filp)
242                 GOTO(err_exit, rc = -ENOMEM);
243
244         sfi->magic = SMFS_FILE_MAGIC;
245
246         cache_dentry = pre_smfs_dentry(NULL, I2CI(inode), filp->f_dentry);
247         if (!cache_dentry)
248                 GOTO(err_exit, rc = -ENOMEM);
249
250         cache_filp->f_vfsmnt = filp->f_vfsmnt;
251
252         cache_filp->f_dentry = cache_dentry;
253         duplicate_file(cache_filp, filp);
254
255         sfi->c_file = cache_filp;
256
257         if (filp->private_data != NULL)
258                 LBUG();
259
260         filp->private_data = sfi;
261
262         RETURN(rc);
263 err_exit:
264         if (sfi)
265                 OBD_FREE(sfi, sizeof(struct smfs_file_info));
266         if (cache_filp)
267                 put_filp(cache_filp);
268         RETURN(rc);
269 }
270
271 static int smfs_cleanup_cache_file(struct file *filp)
272 {
273         struct smfs_file_info *sfi = NULL;
274         int rc = 0;
275         ENTRY;
276
277         if (!filp)
278                 RETURN(rc);
279         sfi = F2SMFI(filp);
280
281         post_smfs_dentry(sfi->c_file->f_dentry);
282
283         put_filp(sfi->c_file);
284
285         OBD_FREE(sfi, sizeof(struct smfs_file_info));
286
287         filp->private_data = NULL;
288
289         RETURN(rc);
290 }
291
292 int smfs_open(struct inode *inode, struct file *filp)
293 {
294         struct inode *cache_inode = NULL;
295         int rc = 0;
296         ENTRY;
297
298         cache_inode = I2CI(inode);
299         if (!cache_inode)
300                 RETURN(-ENOENT);
301
302         if ((rc = smfs_init_cache_file(inode, filp)))
303                 RETURN(rc);
304
305         pre_smfs_inode(inode, cache_inode);
306         if (cache_inode->i_fop->open)
307                 rc = cache_inode->i_fop->open(cache_inode, F2CF(filp));
308
309         post_smfs_inode(inode, cache_inode);
310         duplicate_file(filp, F2CF(filp));
311         RETURN(rc);
312 }
313
314 int smfs_release(struct inode *inode, struct file *filp)
315 {
316         struct inode *cache_inode = NULL;
317         struct file *cache_file = NULL;
318         struct smfs_file_info *sfi = NULL;
319         int rc = 0;
320         ENTRY;
321
322         cache_inode = I2CI(inode);
323         if (!cache_inode)
324                 RETURN(-ENOENT);
325         if (filp) {
326                 sfi = F2SMFI(filp);
327                 if (sfi->magic != SMFS_FILE_MAGIC)
328                         LBUG();
329                 cache_file = sfi->c_file;
330         }
331         pre_smfs_inode(inode, cache_inode);
332         if (cache_inode->i_fop->release)
333                 rc = cache_inode->i_fop->release(cache_inode, cache_file);
334
335         post_smfs_inode(inode, cache_inode);
336         duplicate_file(filp, cache_file);
337
338         smfs_cleanup_cache_file(filp);
339         RETURN(rc);
340 }
341
342 int smfs_fsync(struct file *file, struct dentry *dentry, int datasync)
343 {
344         struct smfs_file_info *sfi = NULL;
345         struct dentry *cache_dentry = NULL;
346         struct file *cache_file = NULL;
347         struct inode *cache_inode;
348         int rc = 0;
349
350         cache_inode = I2CI(dentry->d_inode);
351         if (!cache_inode)
352                 RETURN(-ENOENT);
353         
354         cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
355         if (!cache_dentry)
356                 RETURN(-ENOMEM);
357
358         if (file) {
359                 sfi = F2SMFI(file);
360                 if (sfi->magic != SMFS_FILE_MAGIC)
361                         LBUG();
362                 cache_file = sfi->c_file;
363         } 
364
365         pre_smfs_inode(dentry->d_inode, cache_inode);
366
367         if (cache_inode->i_fop->fsync) {
368                 rc = cache_inode->i_fop->fsync(cache_file,
369                                                cache_dentry, datasync);
370         
371         }
372         post_smfs_inode(dentry->d_inode, cache_inode);
373         duplicate_file(file, cache_file);
374         post_smfs_dentry(cache_dentry);
375
376         RETURN(rc);
377 }
378
379 struct file_operations smfs_file_fops = {
380         llseek:         smfs_llseek,
381         read:           smfs_read,
382         write:          smfs_write,
383         ioctl:          smfs_ioctl,
384         mmap:           smfs_mmap,
385         open:           smfs_open,
386         release:        smfs_release,
387         fsync:          smfs_fsync,
388 };
389
390 static void smfs_truncate(struct inode *inode)
391 {
392         struct inode *cache_inode;
393
394         cache_inode = I2CI(inode);
395
396         if (!cache_inode)
397                 return;
398
399         if (!cache_inode)
400                 return;
401
402         pre_smfs_inode(inode, cache_inode);
403         if (cache_inode->i_op->truncate)
404                 cache_inode->i_op->truncate(cache_inode);
405
406         post_smfs_inode(inode, cache_inode);
407
408         return;
409 }
410
411 int smfs_setattr(struct dentry *dentry, struct iattr *attr)
412 {
413         struct inode *cache_inode;
414         struct dentry *cache_dentry;
415         void  *handle = NULL;
416         int rc = 0;
417
418         cache_inode = I2CI(dentry->d_inode);
419         if (!cache_inode)
420                 RETURN(-ENOENT);
421
422         cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
423         if (!cache_dentry)
424                 RETURN(-ENOMEM);
425
426         handle = smfs_trans_start(dentry->d_inode, FSFILT_OP_SETATTR, NULL);
427         if (IS_ERR(handle) ) {
428                 CERROR("smfs_do_mkdir: no space for transaction\n");
429                 RETURN(-ENOSPC);
430         }
431
432         pre_smfs_inode(dentry->d_inode, cache_inode);
433
434         if (cache_inode->i_op->setattr)
435                 rc = cache_inode->i_op->setattr(cache_dentry, attr);
436
437         SMFS_KML_POST(dentry->d_inode, dentry, attr, NULL,
438                       REINT_SETATTR, "setattr", rc, exit);
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 };