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