Whamcloud - gitweb
Update snap
[fs/lustre-release.git] / lustre / lvfs / fsfilt_smfs.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  lustre/lib/fsfilt_smfs.c
5  *  Lustre filesystem abstraction routines
6  *
7  *  Copyright (C) 2004 Cluster File Systems, Inc.
8  *   Author: Wang Di <wangdi@clusterfs.com>
9  *
10  *   This file is part of Lustre, http://www.lustre.org.
11  *
12  *   Lustre is free software; you can redistribute it and/or
13  *   modify it under the terms of version 2 of the GNU General Public
14  *   License as published by the Free Software Foundation.
15  *
16  *   Lustre is distributed in the hope that it will be useful,
17  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *   GNU General Public License for more details.
20  *
21  *   You should have received a copy of the GNU General Public License
22  *   along with Lustre; if not, write to the Free Software
23  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  */
25
26 #define DEBUG_SUBSYSTEM S_FILTER
27
28 #include <linux/fs.h>
29 #include <linux/jbd.h>
30 #include <linux/slab.h>
31 #include <linux/pagemap.h>
32 #include <linux/quotaops.h>
33 #include <linux/version.h>
34 #include <linux/kp30.h>
35 #include <linux/lustre_fsfilt.h>
36 #include <linux/lustre_smfs.h>
37 #include <linux/obd.h>
38 #include <linux/obd_class.h>
39 #include <linux/module.h>
40 #include <linux/init.h>
41
42 #include <linux/lustre_snap.h>
43 #include <linux/lustre_smfs.h>
44 static void *fsfilt_smfs_start(struct inode *inode, int op,
45                                void *desc_private, int logs)
46 {
47         void *handle;
48         struct inode *cache_inode = I2CI(inode);
49         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
50
51         if (cache_fsfilt == NULL)
52                 return NULL;
53
54         SMFS_TRANS_OP(inode, op);
55
56         if (!cache_fsfilt->fs_start)
57                 return ERR_PTR(-ENOSYS);
58
59         handle = cache_fsfilt->fs_start(cache_inode, op, desc_private, logs);
60         return handle;
61 }
62
63 static void *fsfilt_smfs_brw_start(int objcount, struct fsfilt_objinfo *fso,
64                                    int niocount, struct niobuf_local *nb,
65                                    void *desc_private, int logs)
66 {
67         struct fsfilt_operations *cache_fsfilt;
68         struct dentry *cache_dentry = NULL;
69         struct inode *cache_inode = NULL;
70         struct fsfilt_objinfo cache_fso;
71         void   *rc = NULL;
72
73         ENTRY;
74         cache_fsfilt = I2FOPS(fso->fso_dentry->d_inode);
75         if (cache_fsfilt == NULL)
76                 return NULL;
77
78         cache_inode = I2CI(fso->fso_dentry->d_inode);
79          cache_dentry = pre_smfs_dentry(NULL, cache_inode, fso->fso_dentry);
80
81         if (!cache_dentry)
82                 GOTO(exit, rc = ERR_PTR(-ENOMEM));
83
84         cache_fso.fso_dentry = cache_dentry;
85         cache_fso.fso_bufcnt = fso->fso_bufcnt;
86
87         if (!cache_fsfilt->fs_brw_start)
88                 return ERR_PTR(-ENOSYS);
89
90         rc = cache_fsfilt->fs_brw_start(objcount, &cache_fso, niocount, nb,
91                                         desc_private, logs);
92 exit:
93         post_smfs_dentry(cache_dentry);
94         return rc;
95 }
96
97 /* FIXME-WANGDI: here we can easily have inode == NULL due to
98    mds_open() behavior. It passes NULL inode to mds_finish_transno()
99    sometimes. Probably we should have spare way to get cache fsfilt
100    operations. */
101 static int fsfilt_smfs_commit(struct super_block *sb, struct inode *inode, 
102                               void *h, int force_sync)
103 {
104         struct fsfilt_operations *cache_fsfilt = S2SMI(sb)->sm_cache_fsfilt;
105         struct super_block *csb = S2CSB(sb); 
106         struct inode *cache_inode = NULL;
107         int    rc = -EIO;
108
109         if (inode)
110                 cache_inode = I2CI(inode);
111
112         if (cache_fsfilt == NULL)
113                 RETURN(rc);
114
115         if (!cache_fsfilt->fs_commit)
116                 RETURN(-ENOSYS);
117
118         rc = cache_fsfilt->fs_commit(csb, cache_inode, h, force_sync);
119
120         RETURN(rc);
121 }
122
123 static int fsfilt_smfs_commit_async(struct inode *inode, void *h,
124                                     void **wait_handle)
125 {
126         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
127         struct inode *cache_inode = NULL;
128         int    rc = -EIO;
129
130         cache_inode = I2CI(inode);
131         if (cache_fsfilt == NULL)
132                 RETURN(-EINVAL);
133
134         if (!cache_fsfilt->fs_commit_async)
135                 RETURN(-ENOSYS);
136
137         rc = cache_fsfilt->fs_commit_async(cache_inode, h, wait_handle);
138
139         RETURN(rc);
140 }
141
142 static int fsfilt_smfs_commit_wait(struct inode *inode, void *h)
143 {
144         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
145         struct inode *cache_inode = NULL;
146         int    rc = -EIO;
147
148         cache_inode = I2CI(inode);
149         if (cache_fsfilt == NULL)
150                 RETURN(-EINVAL);
151
152         if (!cache_fsfilt->fs_commit_wait)
153                 RETURN(-ENOSYS);
154
155         rc = cache_fsfilt->fs_commit_wait(cache_inode, h);
156
157         RETURN(rc);
158 }
159
160 static int fsfilt_smfs_setattr(struct dentry *dentry, void *handle,
161                                struct iattr *iattr, int do_trunc)
162 {
163         struct fsfilt_operations *cache_fsfilt = I2FOPS(dentry->d_inode);
164         struct dentry *cache_dentry = NULL;
165         struct inode *cache_inode = NULL;
166         int    rc = -EIO;
167
168         if (!cache_fsfilt)
169                 RETURN(rc);
170
171         cache_inode = I2CI(dentry->d_inode);
172
173         cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
174         if (!cache_dentry)
175                 GOTO(exit, rc = -ENOMEM);
176
177         pre_smfs_inode(dentry->d_inode, cache_inode);
178
179         if (!cache_fsfilt->fs_setattr)
180                 RETURN(-ENOSYS);
181
182         rc = cache_fsfilt->fs_setattr(cache_dentry, handle, iattr, do_trunc);
183
184         post_smfs_inode(dentry->d_inode, cache_inode);
185
186         if (rc == 0) {
187                 struct super_block *sb = dentry->d_inode->i_sb;
188
189                 if (SMFS_DO_REC(S2SMI(sb)) && 
190                     SMFS_DO_INODE_REC(dentry->d_inode)) {
191                         rc = smfs_rec_setattr(dentry->d_inode, dentry, iattr);
192                 }
193         }
194 exit:
195         post_smfs_dentry(cache_dentry);
196         RETURN(rc);
197 }
198
199 static int fsfilt_smfs_iocontrol(struct inode *inode, struct file *file,
200                                  unsigned int cmd, unsigned long arg)
201 {
202         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
203         struct inode *cache_inode = NULL;
204         struct smfs_file_info *sfi = NULL;
205         int    rc = -EIO;
206         ENTRY;
207
208         if (!cache_fsfilt)
209                 RETURN(rc);
210
211         cache_inode = I2CI(inode);
212
213         if (!cache_inode)
214                 RETURN(rc);
215
216         if (file != NULL) {
217                 sfi = F2SMFI(file);
218
219                 if (sfi->magic != SMFS_FILE_MAGIC)
220                         BUG();
221         } else {
222                 sfi = NULL;
223         }
224
225         if (!cache_fsfilt->fs_iocontrol)
226                 RETURN(-ENOSYS);
227
228         if (sfi) {
229                 rc = cache_fsfilt->fs_iocontrol(cache_inode, sfi->c_file, cmd,
230                                                 arg);
231         } else {
232                 rc = cache_fsfilt->fs_iocontrol(cache_inode, NULL, cmd, arg);
233         }
234
235         /* FIXME-UMKA: Should this be in duplicate_inode()? */
236         if (rc == 0 && cmd == EXT3_IOC_SETFLAGS)
237                 inode->i_flags = cache_inode->i_flags;
238
239         post_smfs_inode(inode, cache_inode);
240
241         RETURN(rc);
242 }
243
244 static int fsfilt_smfs_set_md(struct inode *inode, void *handle,
245                               void *lmm, int lmm_size)
246 {
247         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
248         struct inode *cache_inode = NULL;
249         int    rc = -EIO;
250
251         if (!cache_fsfilt)
252                 RETURN(-EINVAL);
253
254         cache_inode = I2CI(inode);
255
256         if (!cache_inode)
257                 RETURN(-ENOENT);
258
259         pre_smfs_inode(inode, cache_inode);
260
261         if (!cache_fsfilt->fs_set_md)
262                 RETURN(-ENOSYS);
263
264         down(&cache_inode->i_sem);
265         rc = cache_fsfilt->fs_set_md(cache_inode, handle, lmm, lmm_size);
266         up(&cache_inode->i_sem);
267
268         post_smfs_inode(inode, cache_inode);
269
270         smfs_rec_md(inode, lmm, lmm_size);
271
272         RETURN(rc);
273 }
274
275 /* Must be called with i_sem held */
276 static int fsfilt_smfs_get_md(struct inode *inode, void *lmm, int lmm_size)
277 {
278         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
279         struct inode *cache_inode = NULL;
280         int    rc = -EIO;
281
282         if (!cache_fsfilt)
283                 RETURN(-EINVAL);
284
285         cache_inode = I2CI(inode);
286
287         if (!cache_inode)
288                 RETURN(-ENOENT);
289
290         pre_smfs_inode(inode, cache_inode);
291
292         if (!cache_fsfilt->fs_get_md)
293                 RETURN(-ENOSYS);
294
295         down(&cache_inode->i_sem);
296         rc = cache_fsfilt->fs_get_md(cache_inode, lmm, lmm_size);
297         up(&cache_inode->i_sem);
298
299         post_smfs_inode(inode, cache_inode);
300
301         RETURN(rc);
302 }
303
304 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
305 static int fsfilt_smfs_send_bio(struct inode *inode, struct bio *bio)
306 #else
307 static int fsfilt_smfs_send_bio(struct inode *inode, struct kiobuf *bio)
308 #endif
309 {
310         struct inode *cache_inode;
311         struct fsfilt_operations *cache_fsfilt;
312
313         cache_fsfilt = I2FOPS(inode);
314         if (!cache_fsfilt)
315                 RETURN(-EINVAL);
316
317         cache_inode = I2CI(inode);
318         if (!cache_inode)
319                 RETURN(-EINVAL);
320
321         if (!cache_fsfilt->fs_send_bio)
322                 RETURN(-ENOSYS);
323
324         return cache_fsfilt->fs_send_bio(cache_inode, bio);
325 }
326
327 static struct page *
328 fsfilt_smfs_getpage(struct inode *inode, long int index)
329 {
330         struct  fsfilt_operations *cache_fsfilt;
331         struct  inode *cache_inode;
332
333         cache_fsfilt = I2FOPS(inode);
334         if (!cache_fsfilt)
335                 RETURN(ERR_PTR(-EINVAL));
336
337         cache_inode = I2CI(inode);
338         if (!cache_inode)
339                 RETURN(ERR_PTR(-EINVAL));
340
341         if (!cache_fsfilt->fs_getpage)
342                 RETURN(ERR_PTR(-ENOSYS));
343
344         return cache_fsfilt->fs_getpage(cache_inode, index);
345 }
346
347 static ssize_t fsfilt_smfs_readpage(struct file *file, char *buf,
348                                     size_t count, loff_t *off)
349 {
350         struct fsfilt_operations *cache_fsfilt;
351         struct smfs_file_info *sfi;
352         struct inode *cache_inode;
353         loff_t tmp_ppos;
354         loff_t *cache_ppos;
355         ssize_t rc = -EIO;
356
357         ENTRY;
358
359         cache_fsfilt = I2FOPS(file->f_dentry->d_inode);
360         if (!cache_fsfilt)
361                 RETURN(rc);
362
363         cache_inode = I2CI(file->f_dentry->d_inode);
364         if (!cache_inode)
365                 RETURN(rc);
366
367         sfi = F2SMFI(file);
368         if (sfi->magic != SMFS_FILE_MAGIC)
369                 BUG();
370
371         if (off != &(file->f_pos))
372                 cache_ppos = &tmp_ppos;
373         else
374                 cache_ppos = &sfi->c_file->f_pos;
375         *cache_ppos = *off;
376
377         pre_smfs_inode(file->f_dentry->d_inode, cache_inode);
378
379         if (cache_fsfilt->fs_readpage)
380                 rc = cache_fsfilt->fs_readpage(sfi->c_file, buf, count,
381                                                cache_ppos);
382
383         *off = *cache_ppos;
384         post_smfs_inode(file->f_dentry->d_inode, cache_inode);
385         duplicate_file(file, sfi->c_file);
386
387         RETURN(rc);
388 }
389
390
391 static int fsfilt_smfs_add_journal_cb(struct obd_device *obd,
392                                       struct super_block *sb, __u64 last_rcvd,
393                                       void *handle, fsfilt_cb_t cb_func,
394                                       void *cb_data)
395 {
396         struct fsfilt_operations *cache_fsfilt = S2SMI(sb)->sm_cache_fsfilt;
397         struct super_block *csb = S2CSB(sb);
398         int rc = -EIO;
399
400         if (!cache_fsfilt)
401                  RETURN(rc);
402         if (cache_fsfilt->fs_add_journal_cb)
403                 rc = cache_fsfilt->fs_add_journal_cb(obd, csb, last_rcvd,
404                                                      handle, cb_func, cb_data);
405         RETURN(rc);
406 }
407
408 static int fsfilt_smfs_statfs(struct super_block *sb, struct obd_statfs *osfs)
409 {
410         struct fsfilt_operations *cache_fsfilt = S2SMI(sb)->sm_cache_fsfilt;
411         struct super_block *csb = S2CSB(sb);
412         int rc = -EIO;
413
414         if (!cache_fsfilt)
415                 RETURN(rc);
416
417         if (!cache_fsfilt->fs_statfs)
418                 RETURN(-ENOSYS);
419
420         rc = cache_fsfilt->fs_statfs(csb, osfs);
421         duplicate_sb(csb, sb);
422
423         RETURN(rc);
424 }
425
426 static int fsfilt_smfs_sync(struct super_block *sb)
427 {
428         struct fsfilt_operations *cache_fsfilt = S2SMI(sb)->sm_cache_fsfilt;
429         struct super_block *csb = S2CSB(sb);
430         int    rc = -EIO;
431
432         if (!cache_fsfilt)
433                 RETURN(-EINVAL);
434
435         if (!cache_fsfilt->fs_sync)
436                 RETURN(-ENOSYS);
437
438         rc = cache_fsfilt->fs_sync(csb);
439
440         RETURN(rc);
441 }
442
443 int fsfilt_smfs_map_inode_pages(struct inode *inode, struct page **page,
444                                 int pages, unsigned long *blocks, int *created,
445                                 int create, struct semaphore *sem)
446 {
447         struct  fsfilt_operations *cache_fsfilt = I2FOPS(inode);
448         struct  inode *cache_inode = NULL;
449         int     rc = -EIO;
450
451         if (!cache_fsfilt)
452                 RETURN(-EINVAL);
453
454         cache_inode = I2CI(inode);
455
456         if (!cache_inode)
457                 RETURN(rc);
458
459         if (!cache_fsfilt->fs_map_inode_pages)
460                 RETURN(-ENOSYS);
461
462         down(&cache_inode->i_sem);
463         rc = cache_fsfilt->fs_map_inode_pages(cache_inode, page, pages, blocks,
464                                               created, create, sem);
465         up(&cache_inode->i_sem);
466
467         RETURN(rc);
468 }
469
470 static int fsfilt_smfs_prep_san_write(struct inode *inode, long *blocks,
471                                       int nblocks, loff_t newsize)
472 {
473         struct  fsfilt_operations *cache_fsfilt = I2FOPS(inode);
474         struct  inode *cache_inode = NULL;
475         int     rc = -EIO;
476
477         if (!cache_fsfilt)
478                 RETURN(-EINVAL);
479
480         cache_inode = I2CI(inode);
481
482         if (!cache_inode)
483                 RETURN(-EINVAL);
484
485         if (!cache_fsfilt->fs_prep_san_write)
486                 RETURN(-ENOSYS);
487
488         down(&cache_inode->i_sem);
489         rc = cache_fsfilt->fs_prep_san_write(cache_inode, blocks, nblocks,
490                                              newsize);
491         up(&cache_inode->i_sem);
492
493         RETURN(rc);
494 }
495
496 static int fsfilt_smfs_read_record(struct file * file, void *buf,
497                                    int size, loff_t *offs)
498 {
499         struct  fsfilt_operations *cache_fsfilt;
500         struct  inode *cache_inode;
501         struct  smfs_file_info *sfi;
502         loff_t  tmp_ppos;
503         loff_t  *cache_ppos;
504         ssize_t rc;
505
506         ENTRY;
507         cache_fsfilt = I2FOPS(file->f_dentry->d_inode);
508         if (!cache_fsfilt)
509                 RETURN(-EINVAL);
510
511         cache_inode = I2CI(file->f_dentry->d_inode);
512
513         if (!cache_inode)
514                 RETURN(-EINVAL);
515
516         sfi = F2SMFI(file);
517         if (sfi->magic != SMFS_FILE_MAGIC) BUG();
518
519         if (offs != &(file->f_pos))
520                 cache_ppos = &tmp_ppos;
521         else
522                 cache_ppos = &sfi->c_file->f_pos;
523         *cache_ppos = *offs;
524
525         pre_smfs_inode(file->f_dentry->d_inode, cache_inode);
526
527         if (!cache_fsfilt->fs_read_record)
528                 RETURN(-ENOSYS);
529
530         rc = cache_fsfilt->fs_read_record(sfi->c_file, buf, size, cache_ppos);
531
532         *offs = *cache_ppos;
533         post_smfs_inode(file->f_dentry->d_inode, cache_inode);
534         duplicate_file(file, sfi->c_file);
535
536         RETURN(rc);
537 }
538
539 static int fsfilt_smfs_write_record(struct file *file, void *buf, int bufsize,
540                                     loff_t *offs, int force_sync)
541 {
542         struct  fsfilt_operations *cache_fsfilt;
543         struct  inode *cache_inode;
544         struct  smfs_file_info *sfi;
545         loff_t  tmp_ppos;
546         loff_t  *cache_ppos;
547         ssize_t rc = -EIO;
548
549         ENTRY;
550
551         cache_fsfilt = I2FOPS(file->f_dentry->d_inode);
552         if (!cache_fsfilt)
553                 RETURN(-EINVAL);
554
555         cache_inode = I2CI(file->f_dentry->d_inode);
556
557         if (!cache_inode)
558                 RETURN(-EINVAL);
559
560         sfi = F2SMFI(file);
561         if (sfi->magic != SMFS_FILE_MAGIC)
562                 BUG();
563
564         if (offs != &(file->f_pos))
565                 cache_ppos = &tmp_ppos;
566         else
567                 cache_ppos = &sfi->c_file->f_pos;
568         *cache_ppos = *offs;
569
570         pre_smfs_inode(file->f_dentry->d_inode, cache_inode);
571
572         if (!cache_fsfilt->fs_write_record)
573                 RETURN(-ENOSYS);
574
575         rc = cache_fsfilt->fs_write_record(sfi->c_file, buf,
576                                            bufsize, cache_ppos, force_sync);
577         *offs = *cache_ppos;
578         post_smfs_inode(file->f_dentry->d_inode, cache_inode);
579         duplicate_file(file, sfi->c_file);
580
581         RETURN(rc);
582 }
583
584 static int fsfilt_smfs_post_setup(struct obd_device *obd, struct vfsmount *mnt)
585 {
586         struct super_block *sb = NULL;
587         int rc = 0;
588
589         if (mnt) {
590                 sb = mnt->mnt_sb;
591                 S2SMI(sb)->smsi_exp = obd->obd_self_export;
592                 if (SMFS_DO_REC(S2SMI(sb)))
593                         rc = smfs_start_rec(sb, mnt);
594                 if (rc)
595                         GOTO(exit, rc);
596                 if (obd)
597                         obd->obd_llog_ctxt[LLOG_REINT_ORIG_CTXT] =
598                                         S2SMI(sb)->smsi_rec_log;
599         }
600 exit:
601         if (rc)
602                 CERROR("can not do post setup in obd %p rc=%d", obd, rc);
603
604         RETURN(rc);
605 }
606
607 static int fsfilt_smfs_post_cleanup(struct obd_device *obd,
608                                     struct vfsmount *mnt)
609 {
610         struct super_block *sb = NULL;
611         int rc = 0;
612
613         if (mnt) {
614                 sb = mnt->mnt_sb;
615                 if (SMFS_DO_REC(S2SMI(sb)))
616                         rc = smfs_stop_rec(sb);
617         }
618         RETURN(rc);
619 }
620
621 static int fsfilt_smfs_set_kml_flags(struct inode *inode)
622 {
623         int rc = 0;
624         if (SMFS_DO_REC(S2SMI(inode->i_sb)))
625                 SMFS_SET_INODE_REC(inode);
626         RETURN(rc);
627 }
628
629 static int fsfilt_smfs_clear_kml_flags(struct inode *inode)
630 {
631         int rc = 0;
632         if (SMFS_DO_REC(S2SMI(inode->i_sb)))
633                 SMFS_CLEAN_INODE_REC(inode);
634         RETURN(rc);
635 }
636
637 static int fsfilt_smfs_set_ost_flags(struct super_block *sb)
638 {
639         int rc = 0;
640         SET_REC_PACK_TYPE_INDEX(S2SMI(sb)->smsi_flags, PACK_OST);
641         RETURN(rc);
642 }
643
644 static int fsfilt_smfs_set_mds_flags(struct super_block *sb)
645 {
646         int rc = 0;
647         SET_REC_PACK_TYPE_INDEX(S2SMI(sb)->smsi_flags, PACK_MDS);
648         RETURN(rc);
649 }
650
651 static int fsfilt_smfs_get_reint_log_ctxt(struct super_block *sb,
652                                           struct llog_ctxt **ctxt)
653 {
654         struct smfs_super_info *smfs_info = S2SMI(sb);
655         int rc = 0;
656
657         *ctxt = smfs_info->smsi_rec_log;
658         RETURN(rc);
659 }
660
661 static int fsfilt_smfs_setup(struct obd_device *obd, struct super_block *sb)
662 {
663         struct smfs_super_info *smfs_info = S2SMI(sb);
664         struct fsfilt_operations *cache_fsfilt;
665         struct super_block *csb;
666         int rc = 0;
667
668         /* It should be initialized olready by smfs_read_super(). */
669         if (!(cache_fsfilt = smfs_info->sm_cache_fsfilt))
670                     cache_fsfilt = fsfilt_get_ops(smfs_info->smsi_cache_ftype);
671
672         if (!cache_fsfilt)
673                 RETURN(-ENOENT);
674
675         csb = S2CSB(sb);
676         if (cache_fsfilt->fs_setup) 
677                 rc = cache_fsfilt->fs_setup(obd, csb);
678         RETURN(rc);
679 }
680
681 static int fsfilt_smfs_set_xattr(struct inode *inode, void *handle, char *name,
682                                  void *buffer, int buffer_size)
683 {
684         struct  fsfilt_operations *cache_fsfilt = I2FOPS(inode);
685         struct  inode *cache_inode = NULL;
686         int     rc = -EIO;
687
688         if (!cache_fsfilt)
689                 RETURN(rc);
690
691         cache_inode = I2CI(inode);
692         if (!cache_inode)
693                 RETURN(rc);
694
695         pre_smfs_inode(inode, cache_inode);
696
697         if (cache_fsfilt->fs_set_xattr)
698                 rc = cache_fsfilt->fs_set_xattr(cache_inode, handle, name,
699                                                 buffer, buffer_size);
700         post_smfs_inode(inode, cache_inode);
701
702         RETURN(rc);
703 }
704
705 static int fsfilt_smfs_get_xattr(struct inode *inode, char *name,
706                                  void *buffer, int buffer_size)
707 {
708         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
709         struct inode *cache_inode = NULL;
710         int    rc = -EIO;
711
712         if (!cache_fsfilt)
713                 RETURN(rc);
714
715         cache_inode = I2CI(inode);
716         if (!cache_inode)
717                 RETURN(rc);
718
719         pre_smfs_inode(inode, cache_inode);
720
721         if (cache_fsfilt->fs_get_xattr)
722                 rc = cache_fsfilt->fs_get_xattr(cache_inode, name,
723                                                 buffer, buffer_size);
724         post_smfs_inode(inode, cache_inode);
725
726         RETURN(rc);
727 }
728
729 static int fsfilt_smfs_insert_extents_ea(struct inode *inode,
730                                          unsigned long from, unsigned long num)
731 {
732         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
733         struct inode *cache_inode = NULL;
734         int    rc = -EIO;
735
736         if (!cache_fsfilt)
737                 RETURN(rc);
738
739         cache_inode = I2CI(inode);
740         if (!cache_inode)
741                 RETURN(rc);
742
743         pre_smfs_inode(inode, cache_inode);
744
745         if (cache_fsfilt->fs_insert_extents_ea)
746                 rc = cache_fsfilt->fs_insert_extents_ea(cache_inode, from, num);
747
748         post_smfs_inode(inode, cache_inode);
749         return rc;
750 }
751
752 static int fsfilt_smfs_remove_extents_ea(struct inode *inode,
753                                          unsigned long from, unsigned long num)
754 {
755         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
756         struct inode *cache_inode = NULL;
757         int    rc = -EIO;
758
759         if (!cache_fsfilt)
760                 RETURN(rc);
761
762         cache_inode = I2CI(inode);
763         if (!cache_inode)
764                 RETURN(rc);
765
766         pre_smfs_inode(inode, cache_inode);
767
768         if (cache_fsfilt->fs_remove_extents_ea)
769                 rc = cache_fsfilt->fs_remove_extents_ea(cache_inode, from, num);
770
771         post_smfs_inode(inode, cache_inode);
772         return rc;
773 }
774
775 static int fsfilt_smfs_init_extents_ea(struct inode *inode)
776 {
777         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
778         struct inode *cache_inode = NULL;
779         int    rc = -EIO;
780
781         if (!cache_fsfilt)
782                 RETURN(rc);
783
784         cache_inode = I2CI(inode);
785         if (!cache_inode)
786                 RETURN(rc);
787
788         pre_smfs_inode(inode, cache_inode);
789
790         if (cache_fsfilt->fs_init_extents_ea)
791                 rc = cache_fsfilt->fs_init_extents_ea(cache_inode);
792
793         post_smfs_inode(inode, cache_inode);
794         return rc;
795 }
796
797 static int fsfilt_smfs_free_extents(struct super_block *sb, ino_t ino,
798                                     char *pbuf, int size)
799 {
800         OBD_FREE(pbuf, size * (sizeof(struct ldlm_extent)));
801         return 0;
802 }
803
804 static int fsfilt_smfs_write_extents(struct dentry *dentry,
805                                      unsigned long from, unsigned long num)
806 {
807         int rc = 0;
808
809         if (SMFS_DO_REC(S2SMI(dentry->d_inode->i_sb)))
810                 rc = smfs_write_extents(dentry->d_inode, dentry, from, num);
811
812         return rc;
813 }
814
815 static int fsfilt_smfs_precreate_rec(struct dentry *dentry, int *count, 
816                                      struct obdo *oa)
817 {
818         int rc = 0;
819
820         if (SMFS_DO_REC(S2SMI(dentry->d_inode->i_sb)))
821                 rc = smfs_rec_precreate(dentry, count, oa);
822
823         return rc;
824 }
825
826 static int fsfilt_smfs_get_ino_write_extents(struct super_block *sb, ino_t ino,
827                                              char **pbuf, int *size)
828 {
829         struct fs_extent *fs_extents;
830         struct ldlm_extent *extents = NULL;
831         struct inode *inode;
832         struct inode *cache_inode;
833         struct fsfilt_operations *cache_fsfilt = NULL;
834         struct lvfs_run_ctxt saved;
835         int    rc = 0, fs_ex_size, ex_num, flags;
836         char   *buf = NULL, *ex_buf = NULL;
837
838         push_ctxt(&saved, S2SMI(sb)->smsi_ctxt, NULL);
839
840         inode = iget(sb, ino);
841
842         if (!inode || is_bad_inode(inode)) {
843                 CWARN("Can not get inode %lu ino\n", ino);
844                 GOTO(out, rc = 0);
845         }
846         cache_inode = I2CI(inode);
847         cache_fsfilt = I2FOPS(inode);
848
849         rc = cache_fsfilt->fs_get_xattr(cache_inode, REINT_EXTENTS_FLAGS,
850                                         &flags, sizeof(int));
851         if (!(flags & SMFS_OVER_WRITE) && !(flags & SMFS_DIRTY_WRITE)) {
852                 GOTO(out, rc = 0);
853         } else if (flags & SMFS_OVER_WRITE) {
854                 *size = 1;
855                 OBD_ALLOC(ex_buf, sizeof(struct ldlm_extent));
856                 if (!ex_buf)
857                         GOTO(out, rc=-ENOMEM);
858                 extents = (struct ldlm_extent*)(ex_buf);
859                 extents->start = 0;
860                 extents->end = 0xffffffff;
861         }
862         if (rc < 0)
863                 GOTO(out, rc);
864         rc = cache_fsfilt->fs_get_write_extents_num(cache_inode, &fs_ex_size);
865         if (rc)
866                 GOTO(out, rc);
867         OBD_ALLOC(buf, fs_ex_size);
868         if (!buf)
869                 GOTO(out, rc=-ENOMEM);
870
871         rc = cache_fsfilt->fs_get_inode_write_extents(cache_inode, &buf,
872                                                       &fs_ex_size);
873         if (rc < 0)
874                 GOTO(out, rc);
875         rc = 0;
876         ex_num = fs_ex_size / sizeof(struct fs_extent);
877         *size =  ex_num;
878         OBD_ALLOC(ex_buf, ex_num* sizeof(struct ldlm_extent));
879         if (!ex_buf)
880                 GOTO(out, rc=-ENOMEM);
881
882         fs_extents = (struct fs_extent*)(buf);
883         extents = (struct ldlm_extent*)(ex_buf);
884         while (ex_num > 0) {
885                 int blk_size = I2CI(inode)->i_blksize;
886
887                 extents->start = fs_extents->e_block * blk_size;
888                 extents->end = extents->start + fs_extents->e_num * blk_size;
889                 fs_extents++;
890                 extents++;
891                 ex_num--;
892         }
893         *pbuf = ex_buf;
894 out:
895         iput(inode);
896         if (buf)
897                 OBD_FREE(buf, fs_ex_size);
898         if (rc && extents)
899                 OBD_FREE(ex_buf, (*size) * (sizeof(struct ldlm_extent)));
900         pop_ctxt(&saved, S2SMI(sb)->smsi_ctxt, NULL);
901         return rc;
902 }
903
904 static int fsfilt_smfs_set_snap_item(struct super_block *sb, char *name)
905 {
906         int rc = 0;
907
908         ENTRY;
909 #if CONFIG_SNAPFS
910         rc = smfs_add_snap_item(sb, name);
911 #endif
912         RETURN(rc);        
913 }
914
915 static struct fsfilt_operations fsfilt_smfs_ops = {
916         .fs_type                = "smfs",
917         .fs_owner               = THIS_MODULE,
918         .fs_start               = fsfilt_smfs_start,
919         .fs_brw_start           = fsfilt_smfs_brw_start,
920         .fs_commit              = fsfilt_smfs_commit,
921         .fs_commit_async        = fsfilt_smfs_commit_async,
922         .fs_commit_wait         = fsfilt_smfs_commit_wait,
923         .fs_setattr             = fsfilt_smfs_setattr,
924         .fs_iocontrol           = fsfilt_smfs_iocontrol,
925         .fs_set_md              = fsfilt_smfs_set_md,
926         .fs_get_md              = fsfilt_smfs_get_md,
927         .fs_readpage            = fsfilt_smfs_readpage,
928         .fs_getpage             = fsfilt_smfs_getpage,
929         .fs_add_journal_cb      = fsfilt_smfs_add_journal_cb,
930         .fs_statfs              = fsfilt_smfs_statfs,
931         .fs_sync                = fsfilt_smfs_sync,
932         .fs_map_inode_pages     = fsfilt_smfs_map_inode_pages,
933         .fs_prep_san_write      = fsfilt_smfs_prep_san_write,
934         .fs_write_record        = fsfilt_smfs_write_record,
935         .fs_read_record         = fsfilt_smfs_read_record,
936         .fs_setup               = fsfilt_smfs_setup,
937         .fs_post_setup          = fsfilt_smfs_post_setup,
938         .fs_post_cleanup        = fsfilt_smfs_post_cleanup,
939         .fs_set_kml_flags       = fsfilt_smfs_set_kml_flags,
940         .fs_clear_kml_flags     = fsfilt_smfs_clear_kml_flags,
941         .fs_set_ost_flags       = fsfilt_smfs_set_ost_flags,
942         .fs_set_mds_flags       = fsfilt_smfs_set_mds_flags,
943         .fs_precreate_rec       = fsfilt_smfs_precreate_rec,
944         .fs_get_reint_log_ctxt  = fsfilt_smfs_get_reint_log_ctxt,
945         .fs_send_bio            = fsfilt_smfs_send_bio,
946         .fs_set_xattr           = fsfilt_smfs_set_xattr,
947         .fs_get_xattr           = fsfilt_smfs_get_xattr,
948         .fs_init_extents_ea     = fsfilt_smfs_init_extents_ea,
949         .fs_insert_extents_ea   = fsfilt_smfs_insert_extents_ea,
950         .fs_remove_extents_ea   = fsfilt_smfs_remove_extents_ea,
951         .fs_get_ino_write_extents = fsfilt_smfs_get_ino_write_extents,
952         .fs_free_write_extents  = fsfilt_smfs_free_extents,
953         .fs_write_extents       = fsfilt_smfs_write_extents,
954         .fs_set_snap_item       = fsfilt_smfs_set_snap_item,
955         
956         /* FIXME-UMKA: probably fsfilt_smfs_get_op_len() should be
957          * put here too. */
958 };
959
960 static int __init fsfilt_smfs_init(void)
961 {
962         int rc;
963
964         rc = fsfilt_register_ops(&fsfilt_smfs_ops);
965         return rc;
966 }
967
968 static void __exit fsfilt_smfs_exit(void)
969 {
970         fsfilt_unregister_ops(&fsfilt_smfs_ops);
971 }
972
973 module_init(fsfilt_smfs_init);
974 module_exit(fsfilt_smfs_exit);
975
976 MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
977 MODULE_DESCRIPTION("Lustre SMFS Filesystem Helper v0.1");
978 MODULE_LICENSE("GPL");