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