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