Whamcloud - gitweb
acbc93ae1581bcddf6efb59f6cbb210bc78ac896
[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 #if 0
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 #endif
239         post_smfs_inode(inode, cache_inode);
240
241         RETURN(rc);
242 }
243
244 typedef int (*set_ea_func_t) (struct inode *, void *, void *, int);
245 typedef int (*get_ea_func_t) (struct inode *, void *, int);
246
247 static int fsfilt_smfs_set_ea(struct inode *inode, void *handle,
248                               void *ea, int ea_size, 
249                               set_ea_func_t set_ea_func)
250 {
251         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
252         struct inode *cache_inode = NULL;
253         int    rc = -EIO;
254
255         if (!cache_fsfilt)
256                 RETURN(-EINVAL);
257
258         cache_inode = I2CI(inode);
259
260         if (!cache_inode)
261                 RETURN(-ENOENT);
262
263         if (!set_ea_func)
264                 RETURN(-ENOSYS);
265
266         pre_smfs_inode(inode, cache_inode);
267
268         down(&cache_inode->i_sem);
269         rc = set_ea_func(cache_inode, handle, ea, ea_size);
270         up(&cache_inode->i_sem);
271
272         post_smfs_inode(inode, cache_inode);
273
274         RETURN(rc);
275 }
276
277 static int fsfilt_smfs_get_ea(struct inode *inode, void *ea, 
278                               int ea_size, get_ea_func_t get_ea_func)
279 {
280         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
281         struct inode *cache_inode = NULL;
282         int    rc = -EIO;
283
284         if (!cache_fsfilt)
285                 RETURN(-EINVAL);
286
287         cache_inode = I2CI(inode);
288
289         if (!cache_inode)
290                 RETURN(-ENOENT);
291
292         if (!get_ea_func)
293                 RETURN(-ENOSYS);
294
295         pre_smfs_inode(inode, cache_inode);
296
297         down(&cache_inode->i_sem);
298         rc = get_ea_func(cache_inode, ea, ea_size);
299         up(&cache_inode->i_sem);
300
301         post_smfs_inode(inode, cache_inode);
302
303         RETURN(rc);
304 }
305
306 static int fsfilt_smfs_set_md(struct inode *inode, void *handle,
307                               void *lmm, int lmm_size)
308 {
309         int rc = 0;
310         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
311         
312         rc = fsfilt_smfs_set_ea(inode, handle, lmm, lmm_size,
313                                 cache_fsfilt->fs_set_md);
314         if (rc)
315                 return rc;
316                 
317         smfs_rec_md(inode, lmm, lmm_size);
318         return rc;
319 }
320
321 static int fsfilt_smfs_get_md(struct inode *inode, void *lmm, int
322                               lmm_size)
323 {
324         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
325         return fsfilt_smfs_get_ea(inode, lmm, lmm_size,
326                                   cache_fsfilt->fs_get_md);
327 }
328
329 static int fsfilt_smfs_set_mid(struct inode *inode, void *handle,
330                                void *mid, int mid_size)
331 {
332         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
333         return fsfilt_smfs_set_ea(inode, handle, mid, mid_size,
334                                   cache_fsfilt->fs_set_mid);
335 }
336
337 static int fsfilt_smfs_get_mid(struct inode *inode, void *mid,
338                                int mid_size)
339 {
340         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
341         return fsfilt_smfs_get_ea(inode, mid, mid_size,
342                                   cache_fsfilt->fs_get_mid);
343 }
344
345 static int fsfilt_smfs_set_sid(struct inode *inode, void *handle,
346                                void *sid, int sid_size)
347 {
348         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
349         return fsfilt_smfs_set_ea(inode, handle, sid, sid_size,
350                                   cache_fsfilt->fs_set_sid);
351 }
352
353 static int fsfilt_smfs_get_sid(struct inode *inode, void *sid,
354                                int sid_size)
355 {
356         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
357         return fsfilt_smfs_get_ea(inode, sid, sid_size,
358                                   cache_fsfilt->fs_get_sid);
359 }
360
361 static int fsfilt_smfs_send_bio(int rw, struct inode *inode, void *bio)
362 {
363         struct inode *cache_inode;
364         struct fsfilt_operations *cache_fsfilt;
365
366         cache_fsfilt = I2FOPS(inode);
367         if (!cache_fsfilt)
368                 RETURN(-EINVAL);
369
370         cache_inode = I2CI(inode);
371         if (!cache_inode)
372                 RETURN(-EINVAL);
373
374         if (!cache_fsfilt->fs_send_bio)
375                 RETURN(-ENOSYS);
376
377         return cache_fsfilt->fs_send_bio(rw, cache_inode, bio);
378 }
379
380 static struct page *
381 fsfilt_smfs_getpage(struct inode *inode, long int index)
382 {
383         struct  fsfilt_operations *cache_fsfilt;
384         struct  inode *cache_inode;
385
386         cache_fsfilt = I2FOPS(inode);
387         if (!cache_fsfilt)
388                 RETURN(ERR_PTR(-EINVAL));
389
390         cache_inode = I2CI(inode);
391         if (!cache_inode)
392                 RETURN(ERR_PTR(-EINVAL));
393
394         if (!cache_fsfilt->fs_getpage)
395                 RETURN(ERR_PTR(-ENOSYS));
396 #if CONFIG_SNAPFS
397         if (SMFS_DO_COW(S2SMI(inode->i_sb))) {
398                 struct address_space_operations *aops = 
399                                 cache_inode->i_mapping->a_ops;
400                 if (aops->bmap(cache_inode->i_mapping, index)) {
401                         struct inode *ind_inode = NULL;
402                         struct inode *cache_ind = NULL;
403                         struct page  *page = NULL;
404                         
405                         ind_inode = smfs_cow_get_ind(inode, index);
406                         if (!ind_inode) {
407                                 RETURN(ERR_PTR(-EIO));
408                         }
409                         cache_ind = I2CI(ind_inode);
410                         /*FIXME cow inode should be bottom fs inode */         
411                         page = cache_fsfilt->fs_getpage(cache_ind, index);
412                         iput(ind_inode); 
413                         RETURN(page);
414                 } 
415         }
416 #endif
417         return cache_fsfilt->fs_getpage(cache_inode, index);
418 }
419
420 static ssize_t fsfilt_smfs_readpage(struct file *file, char *buf,
421                                     size_t count, loff_t *off)
422 {
423         struct fsfilt_operations *cache_fsfilt;
424         struct smfs_file_info *sfi;
425         struct inode *cache_inode;
426         loff_t tmp_ppos;
427         loff_t *cache_ppos;
428         ssize_t rc = -EIO;
429
430         ENTRY;
431
432         cache_fsfilt = I2FOPS(file->f_dentry->d_inode);
433         if (!cache_fsfilt)
434                 RETURN(rc);
435
436         cache_inode = I2CI(file->f_dentry->d_inode);
437         if (!cache_inode)
438                 RETURN(rc);
439
440         sfi = F2SMFI(file);
441         if (sfi->magic != SMFS_FILE_MAGIC)
442                 BUG();
443
444         if (off != &(file->f_pos))
445                 cache_ppos = &tmp_ppos;
446         else
447                 cache_ppos = &sfi->c_file->f_pos;
448         *cache_ppos = *off;
449
450         pre_smfs_inode(file->f_dentry->d_inode, cache_inode);
451 #if CONFIG_SNAPFS
452         /*readdir page*/
453         if (smfs_dotsnap_inode(file->f_dentry->d_inode)) {
454                 struct fsfilt_operations *snapops = 
455                                         I2SNAPOPS(file->f_dentry->d_inode);
456                 
457                 LASSERT(S_ISDIR(file->f_dentry->d_inode->i_mode));
458                 
459                 rc = snapops->fs_read_dotsnap_dir_page(sfi->c_file, buf, count, 
460                                                        cache_ppos); 
461         } else {
462                 if (cache_fsfilt->fs_readpage)
463                         rc = cache_fsfilt->fs_readpage(sfi->c_file, buf, count,
464                                                        cache_ppos);
465         }
466 #else
467         if (cache_fsfilt->fs_readpage)
468                 rc = cache_fsfilt->fs_readpage(sfi->c_file, buf, count,
469                                                cache_ppos);
470
471 #endif
472         *off = *cache_ppos;
473         post_smfs_inode(file->f_dentry->d_inode, cache_inode);
474         duplicate_file(file, sfi->c_file);
475
476         RETURN(rc);
477 }
478
479
480 static int fsfilt_smfs_add_journal_cb(struct obd_device *obd,
481                                       struct super_block *sb, __u64 last_rcvd,
482                                       void *handle, fsfilt_cb_t cb_func,
483                                       void *cb_data)
484 {
485         struct fsfilt_operations *cache_fsfilt = S2SMI(sb)->sm_cache_fsfilt;
486         struct super_block *csb = S2CSB(sb);
487         int rc = -EIO;
488
489         if (!cache_fsfilt)
490                  RETURN(rc);
491         if (cache_fsfilt->fs_add_journal_cb)
492                 rc = cache_fsfilt->fs_add_journal_cb(obd, csb, last_rcvd,
493                                                      handle, cb_func, cb_data);
494         RETURN(rc);
495 }
496
497 static int fsfilt_smfs_statfs(struct super_block *sb, struct obd_statfs *osfs)
498 {
499         struct fsfilt_operations *cache_fsfilt = S2SMI(sb)->sm_cache_fsfilt;
500         struct super_block *csb = S2CSB(sb);
501         int rc = -EIO;
502
503         if (!cache_fsfilt)
504                 RETURN(rc);
505
506         if (!cache_fsfilt->fs_statfs)
507                 RETURN(-ENOSYS);
508
509         rc = cache_fsfilt->fs_statfs(csb, osfs);
510         duplicate_sb(csb, sb);
511
512         RETURN(rc);
513 }
514
515 static int fsfilt_smfs_sync(struct super_block *sb)
516 {
517         struct fsfilt_operations *cache_fsfilt = S2SMI(sb)->sm_cache_fsfilt;
518         struct super_block *csb = S2CSB(sb);
519         int    rc = -EIO;
520
521         if (!cache_fsfilt)
522                 RETURN(-EINVAL);
523
524         if (!cache_fsfilt->fs_sync)
525                 RETURN(-ENOSYS);
526
527         rc = cache_fsfilt->fs_sync(csb);
528
529         RETURN(rc);
530 }
531
532 int fsfilt_smfs_map_inode_pages(struct inode *inode, struct page **page,
533                                 int pages, unsigned long *blocks, int *created,
534                                 int create, struct semaphore *sem)
535 {
536         struct  fsfilt_operations *cache_fsfilt = I2FOPS(inode);
537         struct  inode *cache_inode = NULL;
538         int     rc = -EIO;
539
540         if (!cache_fsfilt)
541                 RETURN(-EINVAL);
542
543         cache_inode = I2CI(inode);
544
545         if (!cache_inode)
546                 RETURN(rc);
547
548         if (!cache_fsfilt->fs_map_inode_pages)
549                 RETURN(-ENOSYS);
550
551         down(&cache_inode->i_sem);
552         rc = cache_fsfilt->fs_map_inode_pages(cache_inode, page, pages, blocks,
553                                               created, create, sem);
554         up(&cache_inode->i_sem);
555
556         RETURN(rc);
557 }
558
559 static int fsfilt_smfs_prep_san_write(struct inode *inode, long *blocks,
560                                       int nblocks, loff_t newsize)
561 {
562         struct  fsfilt_operations *cache_fsfilt = I2FOPS(inode);
563         struct  inode *cache_inode = NULL;
564         int     rc = -EIO;
565
566         if (!cache_fsfilt)
567                 RETURN(-EINVAL);
568
569         cache_inode = I2CI(inode);
570
571         if (!cache_inode)
572                 RETURN(-EINVAL);
573
574         if (!cache_fsfilt->fs_prep_san_write)
575                 RETURN(-ENOSYS);
576
577         down(&cache_inode->i_sem);
578         rc = cache_fsfilt->fs_prep_san_write(cache_inode, blocks, nblocks,
579                                              newsize);
580         up(&cache_inode->i_sem);
581
582         RETURN(rc);
583 }
584
585 static int fsfilt_smfs_read_record(struct file * file, void *buf,
586                                    int size, loff_t *offs)
587 {
588         struct  fsfilt_operations *cache_fsfilt;
589         struct  inode *cache_inode;
590         struct  smfs_file_info *sfi;
591         loff_t  tmp_ppos;
592         loff_t  *cache_ppos;
593         ssize_t rc;
594
595         ENTRY;
596         cache_fsfilt = I2FOPS(file->f_dentry->d_inode);
597         if (!cache_fsfilt)
598                 RETURN(-EINVAL);
599
600         cache_inode = I2CI(file->f_dentry->d_inode);
601
602         if (!cache_inode)
603                 RETURN(-EINVAL);
604
605         sfi = F2SMFI(file);
606         if (sfi->magic != SMFS_FILE_MAGIC) BUG();
607
608         if (offs != &(file->f_pos))
609                 cache_ppos = &tmp_ppos;
610         else
611                 cache_ppos = &sfi->c_file->f_pos;
612         *cache_ppos = *offs;
613
614         pre_smfs_inode(file->f_dentry->d_inode, cache_inode);
615
616         if (!cache_fsfilt->fs_read_record)
617                 RETURN(-ENOSYS);
618
619         rc = cache_fsfilt->fs_read_record(sfi->c_file, buf, size, cache_ppos);
620
621         *offs = *cache_ppos;
622         post_smfs_inode(file->f_dentry->d_inode, cache_inode);
623         duplicate_file(file, sfi->c_file);
624
625         RETURN(rc);
626 }
627
628 static int fsfilt_smfs_write_record(struct file *file, void *buf, int bufsize,
629                                     loff_t *offs, int force_sync)
630 {
631         struct  fsfilt_operations *cache_fsfilt;
632         struct  inode *cache_inode;
633         struct  smfs_file_info *sfi;
634         loff_t  tmp_ppos;
635         loff_t  *cache_ppos;
636         ssize_t rc = -EIO;
637
638         ENTRY;
639
640         cache_fsfilt = I2FOPS(file->f_dentry->d_inode);
641         if (!cache_fsfilt)
642                 RETURN(-EINVAL);
643
644         cache_inode = I2CI(file->f_dentry->d_inode);
645
646         if (!cache_inode)
647                 RETURN(-EINVAL);
648
649         sfi = F2SMFI(file);
650         if (sfi->magic != SMFS_FILE_MAGIC)
651                 BUG();
652
653         if (offs != &(file->f_pos))
654                 cache_ppos = &tmp_ppos;
655         else
656                 cache_ppos = &sfi->c_file->f_pos;
657         *cache_ppos = *offs;
658
659         pre_smfs_inode(file->f_dentry->d_inode, cache_inode);
660
661         if (!cache_fsfilt->fs_write_record)
662                 RETURN(-ENOSYS);
663
664         rc = cache_fsfilt->fs_write_record(sfi->c_file, buf,
665                                            bufsize, cache_ppos, force_sync);
666         *offs = *cache_ppos;
667         post_smfs_inode(file->f_dentry->d_inode, cache_inode);
668         duplicate_file(file, sfi->c_file);
669
670         RETURN(rc);
671 }
672
673 static int fsfilt_smfs_post_setup(struct obd_device *obd, struct vfsmount *mnt,
674                                   struct dentry *root_dentry)
675 {
676         struct super_block *sb = NULL;
677         int rc = 0;
678
679         if (mnt) {
680                 sb = mnt->mnt_sb;
681                 S2SMI(sb)->smsi_exp = obd->obd_self_export;
682                 smfs_post_setup(sb, mnt);
683                 if (SMFS_DO_REC(S2SMI(sb)))
684                         rc = smfs_start_rec(sb, mnt);
685                 if (rc)
686                         GOTO(exit, rc);
687                 if (obd)
688                         obd->obd_llog_ctxt[LLOG_REINT_ORIG_CTXT] =
689                                         S2SMI(sb)->smsi_rec_log;
690         }
691 exit:
692         if (rc)
693                 CERROR("can not do post setup in obd %p rc=%d", obd, rc);
694
695         RETURN(rc);
696 }
697
698 static int fsfilt_smfs_post_cleanup(struct obd_device *obd,
699                                     struct vfsmount *mnt)
700 {
701         struct super_block *sb = NULL;
702         int rc = 0;
703         ENTRY;
704         
705         if (mnt) {
706                 sb = mnt->mnt_sb;
707                 if (SMFS_DO_REC(S2SMI(sb)))
708                         rc = smfs_stop_rec(sb);
709                 smfs_post_cleanup(sb);
710         }
711         RETURN(rc);
712 }
713
714 static int fsfilt_smfs_set_fs_flags(struct inode *inode, int flags)
715 {
716         int rc = 0;
717         ENTRY;
718
719         if (SMFS_DO_REC(S2SMI(inode->i_sb)) && (flags & SM_DO_REC))
720                 SMFS_SET_INODE_REC(inode);
721         if (SMFS_DO_COW(S2SMI(inode->i_sb)) && (flags & SM_DO_COW))
722                 SMFS_SET_INODE_COW(inode);
723         RETURN(rc);
724 }
725
726 static int fsfilt_smfs_clear_fs_flags(struct inode *inode, int flags)
727 {
728         int rc = 0;
729         ENTRY;
730         
731         if (SMFS_DO_REC(S2SMI(inode->i_sb)) && (flags & SM_DO_REC))
732                 SMFS_CLEAN_INODE_REC(inode);
733         if (SMFS_DO_COW(S2SMI(inode->i_sb)) && (flags & SM_DO_COW))
734                 SMFS_CLEAN_INODE_COW(inode);
735         RETURN(rc);
736 }
737
738 static int fsfilt_smfs_get_fs_flags(struct dentry *de)
739 {
740         struct inode *inode = de->d_inode;
741         int flags = 0;
742         ENTRY;
743
744         LASSERT(inode);
745
746         if (SMFS_DO_REC(S2SMI(inode->i_sb)) && SMFS_DO_INODE_REC(inode))
747                 flags |= SM_DO_REC;
748         if (SMFS_DO_COW(S2SMI(inode->i_sb)) && SMFS_DO_INODE_COW(inode))
749                 flags |= SM_DO_COW;
750        
751         RETURN(flags); 
752 }
753 static int fsfilt_smfs_set_ost_flags(struct super_block *sb)
754 {
755         int rc = 0;
756         SET_REC_PACK_TYPE_INDEX(S2SMI(sb)->smsi_flags, PACK_OST);
757         RETURN(rc);
758 }
759
760 static int fsfilt_smfs_set_mds_flags(struct super_block *sb)
761 {
762         int rc = 0;
763         SET_REC_PACK_TYPE_INDEX(S2SMI(sb)->smsi_flags, PACK_MDS);
764         RETURN(rc);
765 }
766
767 static int fsfilt_smfs_get_reint_log_ctxt(struct super_block *sb,
768                                           struct llog_ctxt **ctxt)
769 {
770         struct smfs_super_info *smfs_info = S2SMI(sb);
771         int rc = 0;
772
773         *ctxt = smfs_info->smsi_rec_log;
774         RETURN(rc);
775 }
776
777 static int fsfilt_smfs_setup(struct obd_device *obd, struct super_block *sb)
778 {
779         struct smfs_super_info *smfs_info = S2SMI(sb);
780         struct fsfilt_operations *cache_fsfilt;
781         struct super_block *csb;
782         int rc = 0;
783
784         /* It should be initialized olready by smfs_read_super(). */
785         if (!(cache_fsfilt = smfs_info->sm_cache_fsfilt))
786                     cache_fsfilt = fsfilt_get_ops(smfs_info->smsi_cache_ftype);
787
788         if (!cache_fsfilt)
789                 RETURN(-ENOENT);
790
791         csb = S2CSB(sb);
792         if (cache_fsfilt->fs_setup) 
793                 rc = cache_fsfilt->fs_setup(obd, csb);
794         
795         duplicate_sb(sb, csb);
796         
797         RETURN(rc);
798 }
799
800 static int fsfilt_smfs_set_xattr(struct inode *inode, void *handle, char *name,
801                                  void *buffer, int buffer_size)
802 {
803         struct  fsfilt_operations *cache_fsfilt = I2FOPS(inode);
804         struct  inode *cache_inode = NULL;
805         int     rc = -EIO;
806
807         if (!cache_fsfilt)
808                 RETURN(rc);
809
810         cache_inode = I2CI(inode);
811         if (!cache_inode)
812                 RETURN(rc);
813
814         pre_smfs_inode(inode, cache_inode);
815
816         if (cache_fsfilt->fs_set_xattr)
817                 rc = cache_fsfilt->fs_set_xattr(cache_inode, handle, name,
818                                                 buffer, buffer_size);
819         post_smfs_inode(inode, cache_inode);
820
821         RETURN(rc);
822 }
823
824 static int fsfilt_smfs_get_xattr(struct inode *inode, char *name,
825                                  void *buffer, int buffer_size)
826 {
827         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
828         struct inode *cache_inode = NULL;
829         int    rc = -EIO;
830
831         if (!cache_fsfilt)
832                 RETURN(rc);
833
834         cache_inode = I2CI(inode);
835         if (!cache_inode)
836                 RETURN(rc);
837
838         pre_smfs_inode(inode, cache_inode);
839
840         if (cache_fsfilt->fs_get_xattr)
841                 rc = cache_fsfilt->fs_get_xattr(cache_inode, name,
842                                                 buffer, buffer_size);
843         post_smfs_inode(inode, cache_inode);
844
845         RETURN(rc);
846 }
847
848 static int fsfilt_smfs_insert_extents_ea(struct inode *inode,
849                                          unsigned long from, unsigned long num)
850 {
851         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
852         struct inode *cache_inode = NULL;
853         int    rc = -EIO;
854
855         if (!cache_fsfilt)
856                 RETURN(rc);
857
858         cache_inode = I2CI(inode);
859         if (!cache_inode)
860                 RETURN(rc);
861
862         pre_smfs_inode(inode, cache_inode);
863
864         if (cache_fsfilt->fs_insert_extents_ea)
865                 rc = cache_fsfilt->fs_insert_extents_ea(cache_inode, from, num);
866
867         post_smfs_inode(inode, cache_inode);
868         return rc;
869 }
870
871 static int fsfilt_smfs_remove_extents_ea(struct inode *inode,
872                                          unsigned long from, unsigned long num)
873 {
874         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
875         struct inode *cache_inode = NULL;
876         int    rc = -EIO;
877
878         if (!cache_fsfilt)
879                 RETURN(rc);
880
881         cache_inode = I2CI(inode);
882         if (!cache_inode)
883                 RETURN(rc);
884
885         pre_smfs_inode(inode, cache_inode);
886
887         if (cache_fsfilt->fs_remove_extents_ea)
888                 rc = cache_fsfilt->fs_remove_extents_ea(cache_inode, from, num);
889
890         post_smfs_inode(inode, cache_inode);
891         return rc;
892 }
893
894 static int fsfilt_smfs_init_extents_ea(struct inode *inode)
895 {
896         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
897         struct inode *cache_inode = NULL;
898         int    rc = -EIO;
899
900         if (!cache_fsfilt)
901                 RETURN(rc);
902
903         cache_inode = I2CI(inode);
904         if (!cache_inode)
905                 RETURN(rc);
906
907         pre_smfs_inode(inode, cache_inode);
908
909         if (cache_fsfilt->fs_init_extents_ea)
910                 rc = cache_fsfilt->fs_init_extents_ea(cache_inode);
911
912         post_smfs_inode(inode, cache_inode);
913         return rc;
914 }
915
916 static int fsfilt_smfs_free_extents(struct super_block *sb, ino_t ino,
917                                     char *pbuf, int size)
918 {
919         OBD_FREE(pbuf, size * (sizeof(struct ldlm_extent)));
920         return 0;
921 }
922
923 static int fsfilt_smfs_write_extents(struct dentry *dentry,
924                                      unsigned long from, unsigned long num)
925 {
926         int rc = 0;
927
928         if (SMFS_DO_REC(S2SMI(dentry->d_inode->i_sb)))
929                 rc = smfs_write_extents(dentry->d_inode, dentry, from, num);
930
931         return rc;
932 }
933
934 static int fsfilt_smfs_precreate_rec(struct dentry *dentry, int *count, 
935                                      struct obdo *oa)
936 {
937         int rc = 0;
938
939         if (SMFS_DO_REC(S2SMI(dentry->d_inode->i_sb)))
940                 rc = smfs_rec_precreate(dentry, count, oa);
941
942         return rc;
943 }
944
945 static int fsfilt_smfs_get_ino_write_extents(struct super_block *sb, ino_t ino,
946                                              char **pbuf, int *size)
947 {
948         struct fs_extent *fs_extents;
949         struct ldlm_extent *extents = NULL;
950         struct inode *inode;
951         struct inode *cache_inode;
952         struct fsfilt_operations *cache_fsfilt = NULL;
953         struct lvfs_run_ctxt saved;
954         int    rc = 0, fs_ex_size, ex_num, flags;
955         char   *buf = NULL, *ex_buf = NULL;
956
957         push_ctxt(&saved, S2SMI(sb)->smsi_ctxt, NULL);
958
959         inode = iget(sb, ino);
960
961         if (!inode || is_bad_inode(inode)) {
962                 CWARN("Can not get inode %lu ino\n", ino);
963                 GOTO(out, rc = 0);
964         }
965         cache_inode = I2CI(inode);
966         cache_fsfilt = I2FOPS(inode);
967
968         rc = cache_fsfilt->fs_get_xattr(cache_inode, REINT_EXTENTS_FLAGS,
969                                         &flags, sizeof(int));
970         if (!(flags & SMFS_OVER_WRITE) && !(flags & SMFS_DIRTY_WRITE)) {
971                 GOTO(out, rc = 0);
972         } else if (flags & SMFS_OVER_WRITE) {
973                 *size = 1;
974                 OBD_ALLOC(ex_buf, sizeof(struct ldlm_extent));
975                 if (!ex_buf)
976                         GOTO(out, rc=-ENOMEM);
977                 extents = (struct ldlm_extent*)(ex_buf);
978                 extents->start = 0;
979                 extents->end = 0xffffffff;
980         }
981         if (rc < 0)
982                 GOTO(out, rc);
983         rc = cache_fsfilt->fs_get_write_extents_num(cache_inode, &fs_ex_size);
984         if (rc)
985                 GOTO(out, rc);
986         OBD_ALLOC(buf, fs_ex_size);
987         if (!buf)
988                 GOTO(out, rc=-ENOMEM);
989
990         rc = cache_fsfilt->fs_get_inode_write_extents(cache_inode, &buf,
991                                                       &fs_ex_size);
992         if (rc < 0)
993                 GOTO(out, rc);
994         rc = 0;
995         ex_num = fs_ex_size / sizeof(struct fs_extent);
996         *size =  ex_num;
997         OBD_ALLOC(ex_buf, ex_num* sizeof(struct ldlm_extent));
998         if (!ex_buf)
999                 GOTO(out, rc=-ENOMEM);
1000
1001         fs_extents = (struct fs_extent*)(buf);
1002         extents = (struct ldlm_extent*)(ex_buf);
1003         while (ex_num > 0) {
1004                 int blk_size = I2CI(inode)->i_blksize;
1005
1006                 extents->start = fs_extents->e_block * blk_size;
1007                 extents->end = extents->start + fs_extents->e_num * blk_size;
1008                 fs_extents++;
1009                 extents++;
1010                 ex_num--;
1011         }
1012         *pbuf = ex_buf;
1013 out:
1014         iput(inode);
1015         if (buf)
1016                 OBD_FREE(buf, fs_ex_size);
1017         if (rc && extents)
1018                 OBD_FREE(ex_buf, (*size) * (sizeof(struct ldlm_extent)));
1019         pop_ctxt(&saved, S2SMI(sb)->smsi_ctxt, NULL);
1020         return rc;
1021 }
1022
1023 static int fsfilt_smfs_set_snap_item(struct super_block *sb, char *name)
1024 {
1025         int rc = 0;
1026
1027         ENTRY;
1028 #if CONFIG_SNAPFS
1029 #warning "still not implement for add snap item -wangdi"         
1030 #endif
1031         RETURN(rc);        
1032 }
1033 static int fsfilt_smfs_do_write_cow(struct dentry *de, void *extents,
1034                                     int num_extents)
1035 {
1036         int rc = 0;
1037 #if CONFIG_SNAPFS
1038         struct write_extents *w_ext = (struct write_extents *)extents;
1039         int i = 0;
1040         ENTRY;
1041         for (i = 0; i < num_extents; i++) {
1042                size_t count = w_ext->w_count;
1043                loff_t off = w_ext->w_pos;
1044                rc = smfs_cow_write_pre(de->d_inode, de, &count, &off);
1045                if (rc)
1046                         RETURN(rc);  
1047                w_ext ++;
1048         }
1049 #endif
1050         RETURN(rc);
1051 }
1052 static struct fsfilt_operations fsfilt_smfs_ops = {
1053         .fs_type                = "smfs",
1054         .fs_owner               = THIS_MODULE,
1055         .fs_start               = fsfilt_smfs_start,
1056         .fs_brw_start           = fsfilt_smfs_brw_start,
1057         .fs_commit              = fsfilt_smfs_commit,
1058         .fs_commit_async        = fsfilt_smfs_commit_async,
1059         .fs_commit_wait         = fsfilt_smfs_commit_wait,
1060         .fs_setattr             = fsfilt_smfs_setattr,
1061         .fs_iocontrol           = fsfilt_smfs_iocontrol,
1062         .fs_set_md              = fsfilt_smfs_set_md,
1063         .fs_get_md              = fsfilt_smfs_get_md,
1064         .fs_set_mid             = fsfilt_smfs_set_mid,
1065         .fs_get_mid             = fsfilt_smfs_get_mid,
1066         .fs_set_sid             = fsfilt_smfs_set_sid,
1067         .fs_get_sid             = fsfilt_smfs_get_sid,
1068         .fs_readpage            = fsfilt_smfs_readpage,
1069         .fs_getpage             = fsfilt_smfs_getpage,
1070         .fs_add_journal_cb      = fsfilt_smfs_add_journal_cb,
1071         .fs_statfs              = fsfilt_smfs_statfs,
1072         .fs_sync                = fsfilt_smfs_sync,
1073         .fs_map_inode_pages     = fsfilt_smfs_map_inode_pages,
1074         .fs_prep_san_write      = fsfilt_smfs_prep_san_write,
1075         .fs_write_record        = fsfilt_smfs_write_record,
1076         .fs_read_record         = fsfilt_smfs_read_record,
1077         .fs_setup               = fsfilt_smfs_setup,
1078         .fs_post_setup          = fsfilt_smfs_post_setup,
1079         .fs_post_cleanup        = fsfilt_smfs_post_cleanup,
1080         .fs_set_fs_flags        = fsfilt_smfs_set_fs_flags,
1081         .fs_clear_fs_flags      = fsfilt_smfs_clear_fs_flags,
1082         .fs_get_fs_flags        = fsfilt_smfs_get_fs_flags,
1083         .fs_set_ost_flags       = fsfilt_smfs_set_ost_flags,
1084         .fs_set_mds_flags       = fsfilt_smfs_set_mds_flags,
1085         .fs_precreate_rec       = fsfilt_smfs_precreate_rec,
1086         .fs_get_reint_log_ctxt  = fsfilt_smfs_get_reint_log_ctxt,
1087         .fs_send_bio            = fsfilt_smfs_send_bio,
1088         .fs_set_xattr           = fsfilt_smfs_set_xattr,
1089         .fs_get_xattr           = fsfilt_smfs_get_xattr,
1090         .fs_init_extents_ea     = fsfilt_smfs_init_extents_ea,
1091         .fs_insert_extents_ea   = fsfilt_smfs_insert_extents_ea,
1092         .fs_remove_extents_ea   = fsfilt_smfs_remove_extents_ea,
1093         .fs_get_ino_write_extents = fsfilt_smfs_get_ino_write_extents,
1094         .fs_free_write_extents  = fsfilt_smfs_free_extents,
1095         .fs_write_extents       = fsfilt_smfs_write_extents,
1096         .fs_set_snap_item       = fsfilt_smfs_set_snap_item,
1097         .fs_do_write_cow        = fsfilt_smfs_do_write_cow,
1098 };
1099
1100 static int __init fsfilt_smfs_init(void)
1101 {
1102         int rc;
1103
1104         rc = fsfilt_register_ops(&fsfilt_smfs_ops);
1105         return rc;
1106 }
1107
1108 static void __exit fsfilt_smfs_exit(void)
1109 {
1110         fsfilt_unregister_ops(&fsfilt_smfs_ops);
1111 }
1112
1113 module_init(fsfilt_smfs_init);
1114 module_exit(fsfilt_smfs_exit);
1115
1116 MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
1117 MODULE_DESCRIPTION("Lustre SMFS Filesystem Helper v0.1");
1118 MODULE_LICENSE("GPL");