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