Whamcloud - gitweb
landing smfs.
[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  *  Copyright (C) 2004 Cluster File Systems, Inc.
5  *
6  *   This file is part of Lustre, http://www.lustre.org.
7  *
8  *   Lustre is free software; you can redistribute it and/or
9  *   modify it under the terms of version 2 of the GNU General Public
10  *   License as published by the Free Software Foundation.
11  *
12  *   Lustre is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *   GNU General Public License for more details.
16  *
17  *   You should have received a copy of the GNU General Public License
18  *   along with Lustre; if not, write to the Free Software
19  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  *
21  */
22
23 #define DEBUG_SUBSYSTEM S_SM
24
25 #include <linux/module.h>
26 #include <linux/kernel.h>
27 #include <linux/string.h>
28 #include <linux/slab.h>
29 #include <linux/stat.h>
30 #include <linux/unistd.h>
31 #include <linux/pagemap.h>
32 #include <linux/file.h>
33 #include <linux/fs.h>
34 #include <linux/obd_class.h>
35 #include <linux/obd_support.h>
36 #include <linux/lustre_lib.h>
37 #include <linux/lustre_idl.h>
38 #include <linux/lustre_fsfilt.h>
39 #include <linux/lustre_smfs.h>
40
41 #include "smfs_internal.h"
42
43 static ssize_t smfs_write(struct file *filp, const char *buf, size_t count,
44                           loff_t *ppos)
45 {
46         struct inode *cache_inode;
47         struct smfs_file_info *sfi;
48         loff_t tmp_ppos;
49         loff_t *cache_ppos;
50         int rc = 0;
51         ENTRY;
52
53         cache_inode = I2CI(filp->f_dentry->d_inode);
54
55         if (!cache_inode)
56                 RETURN(-ENOENT);
57
58         sfi = F2SMFI(filp);
59
60         if (sfi->magic != SMFS_FILE_MAGIC)
61                 BUG();
62
63         if (ppos != &(filp->f_pos))
64                 cache_ppos = &tmp_ppos;
65         else
66                 cache_ppos = &sfi->c_file->f_pos;
67         *cache_ppos = *ppos;
68
69         pre_smfs_inode(filp->f_dentry->d_inode, cache_inode);
70
71         if (cache_inode->i_fop->write)
72                 rc = cache_inode->i_fop->write(sfi->c_file, buf, count,
73                                                cache_ppos);
74
75         post_smfs_inode(filp->f_dentry->d_inode, cache_inode);
76         SMFS_KML_POST(filp->f_dentry->d_inode, filp->f_dentry,
77                       &count ,ppos, REINT_WRITE, "write", rc, exit);
78 exit:
79         *ppos = *cache_ppos;
80         duplicate_file(filp, sfi->c_file);
81         RETURN(rc);
82 }
83
84 int smfs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
85                unsigned long arg)
86 {
87         struct inode *cache_inode;
88         struct smfs_file_info *sfi;
89         ssize_t rc = 0;
90         ENTRY;
91
92         cache_inode = I2CI(filp->f_dentry->d_inode);
93         if (!cache_inode)
94                 RETURN(-ENOENT);
95
96         sfi = F2SMFI(filp);
97         if (sfi->magic != SMFS_FILE_MAGIC)
98                 BUG();
99
100         pre_smfs_inode(inode, cache_inode);
101
102         if (cache_inode->i_fop->ioctl)
103                 rc = cache_inode->i_fop->ioctl(cache_inode, sfi->c_file, cmd,
104                                                arg);
105
106         post_smfs_inode(inode, cache_inode);
107         duplicate_file(filp, sfi->c_file);
108
109         RETURN(rc);
110 }
111
112 static ssize_t smfs_read(struct file *filp, char *buf, size_t count,
113                          loff_t *ppos)
114 {
115         struct inode *cache_inode;
116         struct smfs_file_info *sfi;
117         loff_t tmp_ppos;
118         loff_t *cache_ppos;
119         ssize_t rc = 0;
120         ENTRY;
121
122         cache_inode = I2CI(filp->f_dentry->d_inode);
123         if (!cache_inode)
124                 RETURN(-ENOENT);
125
126         sfi = F2SMFI(filp);
127         if (sfi->magic != SMFS_FILE_MAGIC)
128                 BUG();
129
130         if (ppos != &(filp->f_pos))
131                 cache_ppos = &tmp_ppos;
132         else
133                 cache_ppos = &sfi->c_file->f_pos;
134         *cache_ppos = *ppos;
135
136         pre_smfs_inode(filp->f_dentry->d_inode, cache_inode);
137
138         if (cache_inode->i_fop->read)
139                 rc = cache_inode->i_fop->read(sfi->c_file, buf, count,
140                                               cache_ppos);
141
142         *ppos = *cache_ppos;
143         post_smfs_inode(filp->f_dentry->d_inode, cache_inode);
144         duplicate_file(filp, sfi->c_file);
145
146         RETURN(rc);
147 }
148
149 static loff_t smfs_llseek(struct file *file, loff_t offset, int origin)
150 {
151         struct inode *cache_inode;
152         struct smfs_file_info *sfi;
153         ssize_t rc = 0;
154         ENTRY;
155
156         cache_inode = I2CI(file->f_dentry->d_inode);
157         if (!cache_inode)
158                 RETURN(-ENOENT);
159
160         sfi = F2SMFI(file);
161         if (sfi->magic != SMFS_FILE_MAGIC)
162                 BUG();
163
164         pre_smfs_inode(file->f_dentry->d_inode, cache_inode);
165
166         if (cache_inode->i_fop->llseek)
167                 rc = cache_inode->i_fop->llseek(sfi->c_file, offset, origin);
168
169         post_smfs_inode(file->f_dentry->d_inode, cache_inode);
170         duplicate_file(file, sfi->c_file);
171
172         RETURN(rc);
173 }
174
175 static int smfs_mmap(struct file *file, struct vm_area_struct *vma)
176 {
177         struct inode *inode = file->f_dentry->d_inode;
178         struct smfs_file_info *sfi;
179         struct inode *cache_inode = NULL;
180         int rc = 0;
181         ENTRY;
182
183         cache_inode = I2CI(inode);
184         if (!cache_inode)
185                 RETURN(-ENOENT);
186
187         sfi = F2SMFI(file);
188         if (sfi->magic != SMFS_FILE_MAGIC)
189                 BUG();
190
191         if (cache_inode->i_mapping == &cache_inode->i_data)
192                 inode->i_mapping = cache_inode->i_mapping;
193
194         pre_smfs_inode(inode, cache_inode);
195         if (cache_inode->i_fop->mmap)
196                 rc = cache_inode->i_fop->mmap(sfi->c_file, vma);
197
198         post_smfs_inode(inode, cache_inode);
199         duplicate_file(file, sfi->c_file);
200
201         RETURN(rc);
202 }
203
204 static int smfs_init_cache_file(struct inode *inode, struct file *filp)
205 {
206         struct smfs_file_info *sfi = NULL;
207         struct file *cache_filp = NULL;
208         struct dentry *cache_dentry = NULL;
209         int rc = 0;
210         ENTRY;
211
212         OBD_ALLOC(sfi, sizeof(struct smfs_file_info));
213         if (!sfi)
214                 RETURN(-ENOMEM);
215
216         cache_filp = get_empty_filp();
217         if (!cache_filp)
218                 GOTO(err_exit, rc = -ENOMEM);
219
220         sfi->magic = SMFS_FILE_MAGIC;
221
222         cache_dentry = pre_smfs_dentry(NULL, I2CI(inode), filp->f_dentry);
223         if (!cache_dentry)
224                 GOTO(err_exit, rc = -ENOMEM);
225
226         cache_filp->f_vfsmnt = filp->f_vfsmnt;
227
228         cache_filp->f_dentry = cache_dentry;
229         duplicate_file(cache_filp, filp);
230
231         sfi->c_file = cache_filp;
232
233         if (filp->private_data != NULL)
234                 BUG();
235
236         filp->private_data = sfi;
237
238         RETURN(rc);
239 err_exit:
240         if (sfi)
241                 OBD_FREE(sfi, sizeof(struct smfs_file_info));
242         if (cache_filp)
243                 put_filp(cache_filp);
244         RETURN(rc);
245 }
246
247 static int smfs_cleanup_cache_file(struct file *filp)
248 {
249         struct smfs_file_info *sfi = NULL;
250         int rc = 0;
251         ENTRY;
252
253         sfi = F2SMFI(filp);
254
255         post_smfs_dentry(sfi->c_file->f_dentry);
256
257         put_filp(sfi->c_file);
258
259         OBD_FREE(sfi, sizeof(struct smfs_file_info));
260
261         filp->private_data = NULL;
262
263         RETURN(rc);
264 }
265
266 int smfs_open(struct inode *inode, struct file *filp)
267 {
268         struct inode *cache_inode = NULL;
269         int rc = 0, flag = 1;
270         ENTRY;
271
272         cache_inode = I2CI(inode);
273         if (!cache_inode)
274                 RETURN(-ENOENT);
275
276         if ((rc = smfs_init_cache_file(inode, filp)))
277                 RETURN(rc);
278
279         pre_smfs_inode(inode, cache_inode);
280         if (cache_inode->i_fop->open)
281                 rc = cache_inode->i_fop->open(cache_inode, F2CF(filp));
282
283         post_smfs_inode(inode, cache_inode);
284         duplicate_file(filp, F2CF(filp));
285
286         SMFS_KML_POST(filp->f_dentry->d_inode, filp->f_dentry, &flag, NULL,
287                       REINT_OPEN, "open", rc, exit);
288 exit:
289         RETURN(rc);
290 }
291
292 int smfs_release(struct inode *inode, struct file *filp)
293 {
294         struct inode *cache_inode = NULL;
295         struct smfs_file_info *sfi = NULL;
296         int rc = 0, flag = 0;
297         ENTRY;
298
299         cache_inode = I2CI(inode);
300         if (!cache_inode)
301                 RETURN(-ENOENT);
302
303         sfi = F2SMFI(filp);
304         if (sfi->magic != SMFS_FILE_MAGIC)
305                 BUG();
306
307         pre_smfs_inode(inode, cache_inode);
308         if (cache_inode->i_fop->release)
309                 rc = cache_inode->i_fop->release(cache_inode, sfi->c_file);
310
311         post_smfs_inode(inode, cache_inode);
312         duplicate_file(filp, sfi->c_file);
313
314         smfs_cleanup_cache_file(filp);
315
316         SMFS_KML_POST(filp->f_dentry->d_inode, filp->f_dentry, &flag, NULL,
317                       REINT_CLOSE, "close", rc, exit);
318 exit:
319         RETURN(rc);
320 }
321
322 int smfs_fsync(struct file *file, struct dentry *dentry, int datasync)
323 {
324         struct smfs_file_info *sfi = NULL;
325         struct inode *cache_inode;
326         int rc = 0;
327
328         cache_inode = I2CI(file->f_dentry->d_inode);
329         if (!cache_inode)
330                 RETURN(-ENOENT);
331
332         sfi = F2SMFI(file);
333         if (sfi->magic != SMFS_FILE_MAGIC)
334                 BUG();
335
336         pre_smfs_inode(file->f_dentry->d_inode, cache_inode);
337
338         if (cache_inode->i_fop->fsync)
339                 rc = cache_inode->i_fop->fsync(sfi->c_file,
340                                                sfi->c_file->f_dentry, datasync);
341
342         post_smfs_inode(file->f_dentry->d_inode, cache_inode);
343         duplicate_file(file, sfi->c_file);
344
345         RETURN(rc);
346 }
347
348 struct file_operations smfs_file_fops = {
349         llseek:         smfs_llseek,
350         read:           smfs_read,
351         write:          smfs_write,
352         ioctl:          smfs_ioctl,
353         mmap:           smfs_mmap,
354         open:           smfs_open,
355         release:        smfs_release,
356         fsync:          smfs_fsync,
357 };
358
359 static void smfs_truncate(struct inode *inode)
360 {
361         struct inode *cache_inode;
362
363         cache_inode = I2CI(inode);
364
365         if (!cache_inode)
366                 return;
367
368         pre_smfs_inode(inode, cache_inode);
369         if (cache_inode->i_op->truncate)
370                 cache_inode->i_op->truncate(cache_inode);
371
372         post_smfs_inode(inode, cache_inode);
373 }
374
375 int smfs_setattr(struct dentry *dentry, struct iattr *attr)
376 {
377         struct inode *cache_inode;
378         struct dentry *cache_dentry;
379         void  *handle = NULL;
380         int rc = 0;
381
382         cache_inode = I2CI(dentry->d_inode);
383         if (!cache_inode)
384                 RETURN(-ENOENT);
385
386         cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
387         if (!cache_dentry)
388                 RETURN(-ENOMEM);
389
390         handle = smfs_trans_start(dentry->d_inode, FSFILT_OP_SETATTR, NULL);
391         if (IS_ERR(handle) ) {
392                 CERROR("smfs_do_mkdir: no space for transaction\n");
393                 RETURN(-ENOSPC);
394         }
395
396         pre_smfs_inode(dentry->d_inode, cache_inode);
397
398         if (cache_inode->i_op->setattr)
399                 rc = cache_inode->i_op->setattr(cache_dentry, attr);
400
401         SMFS_KML_POST(dentry->d_inode, dentry, attr, NULL,
402                       REINT_SETATTR, "setattr", rc, exit);
403 exit:
404         post_smfs_inode(dentry->d_inode, cache_inode);
405         post_smfs_dentry(cache_dentry);
406         smfs_trans_commit(dentry->d_inode, handle, 0);
407         RETURN(rc);
408 }
409
410 int smfs_setxattr(struct dentry *dentry, const char *name, const void *value,
411                   size_t size, int flags)
412 {
413         struct inode *cache_inode;
414         struct dentry *cache_dentry;
415         int rc = 0;
416
417         cache_inode = I2CI(dentry->d_inode);
418         if (!cache_inode)
419                 RETURN(-ENOENT);
420
421         cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
422         if (!cache_dentry)
423                 RETURN(-ENOMEM);
424
425         pre_smfs_inode(dentry->d_inode, cache_inode);
426
427         if (cache_inode->i_op->setxattr)
428                 rc = cache_inode->i_op->setxattr(cache_dentry, name, value,
429                                                  size, flags);
430
431         post_smfs_inode(dentry->d_inode, cache_inode);
432         post_smfs_dentry(cache_dentry);
433
434         RETURN(rc);
435 }
436
437 int smfs_getxattr(struct dentry *dentry, const char *name, void *buffer,
438                   size_t size)
439 {
440         struct inode *cache_inode;
441         struct dentry *cache_dentry;
442         int rc = 0;
443
444         cache_inode = I2CI(dentry->d_inode);
445         if (!cache_inode)
446                 RETURN(-ENOENT);
447
448         cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
449         if (!cache_dentry)
450                 RETURN(-ENOMEM);
451
452         pre_smfs_inode(dentry->d_inode, cache_inode);
453
454         if (cache_inode->i_op->getattr)
455                 rc = cache_inode->i_op->getxattr(cache_dentry, name, buffer,
456                                                  size);
457
458         post_smfs_inode(dentry->d_inode, cache_inode);
459         post_smfs_dentry(cache_dentry);
460
461         RETURN(rc);
462 }
463
464 ssize_t smfs_listxattr(struct dentry *dentry, char *buffer, 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->listxattr)
481                 rc = cache_inode->i_op->listxattr(cache_dentry, buffer, size);
482
483         post_smfs_inode(dentry->d_inode, cache_inode);
484         post_smfs_dentry(cache_dentry);
485
486         RETURN(rc);
487 }
488
489 int smfs_removexattr(struct dentry *dentry, const char *name)
490 {
491         struct inode *cache_inode;
492         struct dentry *cache_dentry;
493         int rc = 0;
494
495         cache_inode = I2CI(dentry->d_inode);
496         if (!cache_inode)
497                 RETURN(-ENOENT);
498
499         cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
500         if (!cache_dentry)
501                 RETURN(-ENOMEM);
502
503         pre_smfs_inode(dentry->d_inode, cache_inode);
504
505         if (cache_inode->i_op->removexattr)
506                 rc = cache_inode->i_op->removexattr(cache_dentry, name);
507
508         post_smfs_inode(dentry->d_inode, cache_inode);
509         post_smfs_dentry(cache_dentry);
510
511         RETURN(rc);
512 }
513
514 struct inode_operations smfs_file_iops = {
515         truncate:       smfs_truncate,          /* BKL held */
516         setattr:        smfs_setattr,           /* BKL held */
517         setxattr:       smfs_setxattr,          /* BKL held */
518         getxattr:       smfs_getxattr,          /* BKL held */
519         listxattr:      smfs_listxattr,         /* BKL held */
520         removexattr:    smfs_removexattr,       /* BKL held */
521 };