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