Whamcloud - gitweb
* make scheduler threads balance rx and tx more evenly
[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 *cache_ppos;
270         ssize_t rc = -EIO;
271         struct hook_msg msg = {
272                 .dentry = file->f_dentry,
273         };
274
275         ENTRY;
276
277         cache_fsfilt = I2FOPS(file->f_dentry->d_inode);
278         if (!cache_fsfilt)
279                 RETURN(rc);
280
281         cache_inode = I2CI(file->f_dentry->d_inode);
282         if (!cache_inode)
283                 RETURN(rc);
284
285         sfi = F2SMFI(file);
286         if (sfi->magic != SMFS_FILE_MAGIC)
287                 BUG();
288
289         pre_smfs_file(file, off, &cache_ppos);
290         SMFS_PRE_HOOK(file->f_dentry->d_inode, HOOK_READDIR, &msg);
291
292 #if CONFIG_SNAPFS
293         /*readdir page*/
294         if (smfs_dotsnap_inode(file->f_dentry->d_inode)) {
295                 struct fsfilt_operations *snapops = 
296                                         I2SNAPOPS(file->f_dentry->d_inode);
297                 
298                 LASSERT(S_ISDIR(file->f_dentry->d_inode->i_mode));
299                 
300                 rc = snapops->fs_read_dotsnap_dir_page(sfi->c_file, buf, count, 
301                                                        cache_ppos); 
302         } else {
303                 if (cache_fsfilt->fs_readpage)
304                         rc = cache_fsfilt->fs_readpage(sfi->c_file, buf, count,
305                                                        cache_ppos);
306         }
307 #else
308         if (cache_fsfilt->fs_readpage)
309                 rc = cache_fsfilt->fs_readpage(sfi->c_file, buf, count,
310                                                cache_ppos);
311
312 #endif
313         SMFS_POST_HOOK(file->f_dentry->d_inode, HOOK_READDIR, &msg, rc);
314         post_smfs_file(file);
315         
316         RETURN(rc);
317 }
318
319
320 static int fsfilt_smfs_add_journal_cb(struct obd_device *obd,
321                                       struct super_block *sb, __u64 last_rcvd,
322                                       void *handle, fsfilt_cb_t cb_func,
323                                       void *cb_data)
324 {
325         struct fsfilt_operations *cache_fsfilt = S2SMI(sb)->sm_cache_fsfilt;
326         struct super_block *csb = S2CSB(sb);
327         int rc = -EIO;
328         
329         ENTRY;
330         
331         if (!cache_fsfilt)
332                  RETURN(rc);
333         if (cache_fsfilt->fs_add_journal_cb)
334                 rc = cache_fsfilt->fs_add_journal_cb(obd, csb, last_rcvd,
335                                                      handle, cb_func, cb_data);
336         RETURN(rc);
337 }
338
339 static int fsfilt_smfs_statfs(struct super_block *sb, struct obd_statfs *osfs)
340 {
341         struct fsfilt_operations *cache_fsfilt = S2SMI(sb)->sm_cache_fsfilt;
342         struct super_block *csb = S2CSB(sb);
343         int rc = -EIO;
344
345         ENTRY;
346         
347         if (!cache_fsfilt)
348                 RETURN(rc);
349
350         if (!cache_fsfilt->fs_statfs)
351                 RETURN(-ENOSYS);
352
353         rc = cache_fsfilt->fs_statfs(csb, osfs);
354         duplicate_sb(csb, sb);
355
356         RETURN(rc);
357 }
358
359 static int fsfilt_smfs_sync(struct super_block *sb)
360 {
361         struct fsfilt_operations *cache_fsfilt = S2SMI(sb)->sm_cache_fsfilt;
362         struct super_block *csb = S2CSB(sb);
363         int    rc = -ENOSYS;
364
365         if (!cache_fsfilt)
366                 RETURN(-EINVAL);
367
368         if (cache_fsfilt->fs_sync)
369                 rc = cache_fsfilt->fs_sync(csb);
370
371         RETURN(rc);
372 }
373
374 int fsfilt_smfs_map_inode_pages(struct inode *inode, struct page **page,
375                                 int pages, unsigned long *blocks, int *created,
376                                 int create, struct semaphore *sem)
377 {
378         struct  fsfilt_operations *cache_fsfilt = I2FOPS(inode);
379         struct  inode *cache_inode = NULL;
380         int     rc = -EIO;
381         struct hook_rw_msg  msg = {
382                 .write = create,
383         };
384         hook_op hook = create ? HOOK_WRITE : HOOK_READ;
385         ENTRY;
386         
387         
388         if (!cache_fsfilt)
389                 RETURN(-EINVAL);
390
391         cache_inode = I2CI(inode);
392
393         if (!cache_inode)
394                 RETURN(rc);
395
396         if (!cache_fsfilt->fs_map_inode_pages)
397                 RETURN(-ENOSYS);
398
399         SMFS_PRE_HOOK(inode, hook, &msg);
400         down(&cache_inode->i_sem);
401
402         rc = cache_fsfilt->fs_map_inode_pages(cache_inode, page, pages, blocks,
403                                               created, create, sem);
404         up(&cache_inode->i_sem);
405         SMFS_POST_HOOK(inode, hook, &msg, rc);
406
407         RETURN(rc);
408 }
409
410 static int fsfilt_smfs_prep_san_write(struct inode *inode, long *blocks,
411                                       int nblocks, loff_t newsize)
412 {
413         struct  fsfilt_operations *cache_fsfilt = I2FOPS(inode);
414         struct  inode *cache_inode = NULL;
415         int     rc = -EIO;
416
417         if (!cache_fsfilt)
418                 RETURN(-EINVAL);
419
420         cache_inode = I2CI(inode);
421
422         if (!cache_inode)
423                 RETURN(-EINVAL);
424
425         if (!cache_fsfilt->fs_prep_san_write)
426                 RETURN(-ENOSYS);
427
428         down(&cache_inode->i_sem);
429         rc = cache_fsfilt->fs_prep_san_write(cache_inode, blocks, nblocks,
430                                              newsize);
431         up(&cache_inode->i_sem);
432
433         RETURN(rc);
434 }
435
436 static int fsfilt_smfs_read_record(struct file * file, void *buf,
437                                    int size, loff_t *offs)
438 {
439         struct  fsfilt_operations *cache_fsfilt;
440         struct  inode *cache_inode;
441         struct  smfs_file_info *sfi;
442         loff_t  *cache_ppos;
443         ssize_t rc;
444
445         ENTRY;
446         cache_fsfilt = I2FOPS(file->f_dentry->d_inode);
447         if (!cache_fsfilt)
448                 RETURN(-EINVAL);
449
450         cache_inode = I2CI(file->f_dentry->d_inode);
451         if (!cache_inode)
452                 RETURN(-EINVAL);
453
454         sfi = F2SMFI(file);
455         LASSERT(sfi->magic == SMFS_FILE_MAGIC);
456
457         if (!cache_fsfilt->fs_read_record)
458                 RETURN(-ENOSYS);
459
460         pre_smfs_file(file, offs, &cache_ppos);
461         rc = cache_fsfilt->fs_read_record(sfi->c_file, buf, size, cache_ppos);
462         post_smfs_file(file);
463
464         RETURN(rc);
465 }
466
467 static int fsfilt_smfs_write_record(struct file *file, void *buf, int bufsize,
468                                     loff_t *offs, int force_sync)
469 {
470         struct  fsfilt_operations *cache_fsfilt;
471         struct  inode *cache_inode;
472         struct  smfs_file_info *sfi;
473         loff_t  *cache_ppos;
474         ssize_t rc = -EIO;
475
476         ENTRY;
477
478         cache_fsfilt = I2FOPS(file->f_dentry->d_inode);
479         if (!cache_fsfilt)
480                 RETURN(-EINVAL);
481
482         cache_inode = I2CI(file->f_dentry->d_inode);
483         if (!cache_inode)
484                 RETURN(-EINVAL);
485
486         sfi = F2SMFI(file);
487         LASSERT(sfi->magic == SMFS_FILE_MAGIC);
488
489         if (!cache_fsfilt->fs_write_record)
490                 RETURN(-ENOSYS);
491         
492         pre_smfs_file(file, offs, &cache_ppos);
493         rc = cache_fsfilt->fs_write_record(sfi->c_file, buf,
494                                            bufsize, cache_ppos, force_sync);
495
496         post_smfs_file(file);
497
498         RETURN(rc);
499 }
500
501 static int fsfilt_smfs_post_setup(struct obd_device *obd, struct vfsmount *mnt,
502                                   struct dentry *root_dentry)//, void *data)
503 {
504         struct super_block *sb = NULL;
505         int rc = 0;
506
507         ENTRY;
508         
509         if (mnt) {
510                 sb = mnt->mnt_sb;
511                 
512                 LASSERT(obd);
513                 S2SMI(sb)->smsi_exp = obd->obd_self_export;
514                
515                 rc = smfs_post_setup(obd, mnt, root_dentry);//, data);
516                 if (rc) {
517                         CERROR("post_setup fails in obd %p rc=%d", obd, rc);
518                 }
519         }
520         
521         RETURN(rc);
522 }
523
524 static int fsfilt_smfs_post_cleanup(struct obd_device *obd,
525                                     struct vfsmount *mnt)
526 {
527         struct super_block *sb = NULL;
528         int rc = 0;
529         ENTRY;
530         
531         if (mnt) {
532                 sb = mnt->mnt_sb;
533                 smfs_post_cleanup(sb);
534         }
535         
536         RETURN(rc);
537 }
538
539 static int fsfilt_smfs_set_fs_flags(struct inode *inode, int flags)
540 {
541         int rc = 0;
542         ENTRY;
543
544         if (flags & SM_ALL_PLG) /* enable all plugins */
545                 SMFS_SET(I2SMI(inode)->smi_flags, SMFS_PLG_ALL);
546 #if 0
547         if (SMFS_DO_COW(S2SMI(inode->i_sb)) && (flags & SM_DO_COW))
548                 SMFS_SET_INODE_COW(inode);
549 #endif
550         RETURN(rc);
551 }
552
553 static int fsfilt_smfs_clear_fs_flags(struct inode *inode, int flags)
554 {
555         int rc = 0;
556         ENTRY;
557         /*
558         if (SMFS_DO_REC(S2SMI(inode->i_sb)) && (flags & SM_DO_REC))
559                 SMFS_CLEAN_INODE_REC(inode);
560         if (SMFS_DO_COW(S2SMI(inode->i_sb)) && (flags & SM_DO_COW))
561                 SMFS_CLEAN_INODE_COW(inode);
562         */
563         if(flags & SM_ALL_PLG) /* disable all plugins */
564                 SMFS_CLEAR(I2SMI(inode)->smi_flags, SMFS_PLG_ALL);
565         RETURN(rc);
566 }
567
568 static int fsfilt_smfs_get_fs_flags(struct dentry *de)
569 {
570         struct inode *inode = de->d_inode;
571         int flags = 0;
572         ENTRY;
573
574         LASSERT(inode);
575         
576         flags = I2SMI(inode)->smi_flags & S2SMI(inode->i_sb)->plg_flags;
577        
578         RETURN(flags); 
579 }
580
581 static int fsfilt_smfs_set_ost_flags(struct super_block *sb)
582 {
583         return 0;
584 }
585
586 static int fsfilt_smfs_set_mds_flags(struct super_block *sb)
587 {
588         return 0;
589 }
590
591 #if 0
592 static int fsfilt_smfs_get_reint_log_ctxt(struct super_block *sb,
593                                           struct llog_ctxt **ctxt)
594 {
595         struct smfs_super_info *smfs_info = S2SMI(sb);
596         int rc = 0;
597
598         *ctxt = smfs_info->smsi_kml_log;
599         RETURN(rc);
600 }
601 #endif
602
603 static int fsfilt_smfs_setup(struct obd_device *obd, struct super_block *sb)
604 {
605         struct smfs_super_info *smfs_info = S2SMI(sb);
606         struct fsfilt_operations *cache_fsfilt;
607         struct super_block *csb;
608         int rc = 0;
609
610         ENTRY;
611         
612         /* It should be initialized olready by smfs_read_super(). */
613         if (!(cache_fsfilt = smfs_info->sm_cache_fsfilt))
614                     cache_fsfilt = fsfilt_get_ops(smfs_info->smsi_cache_ftype);
615
616         if (!cache_fsfilt)
617                 RETURN(-ENOENT);
618
619         csb = S2CSB(sb);
620         if (cache_fsfilt->fs_setup) 
621                 rc = cache_fsfilt->fs_setup(obd, csb);
622         
623         duplicate_sb(sb, csb);
624         
625         RETURN(rc);
626 }
627
628 static int fsfilt_smfs_setattr(struct dentry *dentry, void *handle,
629                                struct iattr *iattr, int do_trunc)
630 {
631         struct fsfilt_operations *cache_fsfilt = I2FOPS(dentry->d_inode);
632         struct dentry *cache_dentry = NULL;
633         struct inode *cache_inode = I2CI(dentry->d_inode);
634         struct smfs_super_info *sbi = S2SMI(dentry->d_inode->i_sb);
635         struct hook_attr_msg msg = {
636                 .dentry = dentry,
637                 .attr = iattr
638         };
639         int    rc = -EIO;
640
641         if (!cache_fsfilt)
642                 RETURN(rc);
643
644         if (!cache_fsfilt->fs_setattr)
645                 RETURN(-ENOSYS);
646
647         cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
648         if (!cache_dentry)
649                 RETURN(-ENOMEM);
650
651         pre_smfs_inode(dentry->d_inode, cache_inode);
652
653         SMFS_PRE_HOOK(dentry->d_inode, HOOK_F_SETATTR, &msg);
654         
655         if (SMFS_DO_HND_IBLOCKS(sbi)) {
656                 /* size-on-mds changes i_blocks directly to reflect
657                  * aggregated i_blocks from all OSTs -bzzz */
658                 cache_inode->i_blocks = dentry->d_inode->i_blocks;
659         }
660
661         rc = cache_fsfilt->fs_setattr(cache_dentry, handle, iattr, do_trunc);
662
663         SMFS_POST_HOOK(dentry->d_inode, HOOK_F_SETATTR, &msg, rc);
664         post_smfs_inode(dentry->d_inode, cache_inode);
665
666         post_smfs_dentry(cache_dentry);
667         RETURN(rc);
668 }
669
670 static int fsfilt_smfs_set_xattr(struct inode *inode, void *handle, char *name,
671                                  void *buffer, int buffer_size)
672 {
673         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
674         struct inode *cache_inode = NULL;
675         struct hook_xattr_msg msg = {
676                 .name = name,
677                 .buffer = buffer,
678                 .buffer_size = buffer_size
679         };
680         int    rc = -EIO;
681         int    lov = 0;
682         
683         ENTRY;
684         
685         if (!cache_fsfilt)
686                 RETURN(-EIO);
687
688         cache_inode = I2CI(inode);
689         if (!cache_inode)
690                 RETURN(rc);
691         
692         lov = (!strcmp(name, XATTR_LUSTRE_MDS_LOV_EA));
693         pre_smfs_inode(inode, cache_inode);
694         SMFS_PRE_HOOK(inode, HOOK_F_SETXATTR, &msg);
695         if (cache_fsfilt->fs_set_xattr)
696                 rc = cache_fsfilt->fs_set_xattr(cache_inode, handle, name,
697                                                 buffer, buffer_size);
698          
699         SMFS_POST_HOOK(inode, HOOK_F_SETXATTR, &msg, rc);
700         post_smfs_inode(inode, cache_inode);
701
702         RETURN(rc);
703 }
704
705 static int fsfilt_smfs_get_xattr(struct inode *inode, char *name,
706                                  void *buffer, int buffer_size)
707 {
708         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
709         struct inode *cache_inode = NULL;
710         int    rc = -EIO;
711
712         if (!cache_fsfilt)
713                 RETURN(rc);
714
715         cache_inode = I2CI(inode);
716         if (!cache_inode)
717                 RETURN(rc);
718
719         pre_smfs_inode(inode, cache_inode);
720         if (cache_fsfilt->fs_get_xattr)
721                 rc = cache_fsfilt->fs_get_xattr(cache_inode, name,
722                                                 buffer, buffer_size);
723         post_smfs_inode(inode, cache_inode);
724         RETURN(rc);
725 }
726
727 static int fsfilt_smfs_set_md(struct inode *inode, void *handle,
728                               void *lmm, int lmm_size, enum ea_type type)
729 {
730         int rc;
731         
732         switch(type) {
733         case EA_LOV:
734                 rc = fsfilt_smfs_set_xattr(inode, handle,
735                                            XATTR_LUSTRE_MDS_LOV_EA,
736                                            lmm, lmm_size);
737                 break;
738         case EA_MEA:
739                 rc = fsfilt_smfs_set_xattr(inode, handle,
740                                            XATTR_LUSTRE_MDS_MEA_EA,
741                                            lmm, lmm_size);
742                 break;
743         case EA_SID:
744                 rc = fsfilt_smfs_set_xattr(inode, handle,
745                                            XATTR_LUSTRE_MDS_SID_EA,
746                                            lmm, lmm_size);
747                 break;
748         case EA_PID:
749                 rc = fsfilt_smfs_set_xattr(inode, handle,
750                                            XATTR_LUSTRE_MDS_PID_EA,
751                                            lmm, lmm_size);
752                 break;
753         case EA_KEY:
754                 rc = fsfilt_smfs_set_xattr(inode, handle,
755                                            XATTR_LUSTRE_MDS_KEY_EA,
756                                            lmm, lmm_size);
757                 break;
758         default:
759                 rc = -EINVAL;
760         }
761
762         return rc;
763 }
764
765 static int fsfilt_smfs_get_md(struct inode *inode, void *lmm,
766                               int lmm_size, enum ea_type type)
767 {
768         int rc;
769         
770         switch (type) {
771         case EA_LOV:
772                 rc = fsfilt_smfs_get_xattr(inode,
773                                            XATTR_LUSTRE_MDS_LOV_EA,
774                                            lmm, lmm_size);
775                 break;
776         case EA_MEA:
777                 rc = fsfilt_smfs_get_xattr(inode,
778                                            XATTR_LUSTRE_MDS_MEA_EA,
779                                            lmm, lmm_size);
780                 break;
781         case EA_SID:
782                 rc = fsfilt_smfs_get_xattr(inode,
783                                            XATTR_LUSTRE_MDS_SID_EA,
784                                            lmm, lmm_size);
785                 break;
786         case EA_PID:
787                 rc = fsfilt_smfs_get_xattr(inode,
788                                            XATTR_LUSTRE_MDS_PID_EA,
789                                            lmm, lmm_size);
790                 break;
791         case EA_KEY:
792                 rc = fsfilt_smfs_get_xattr(inode,
793                                            XATTR_LUSTRE_MDS_KEY_EA,
794                                            lmm, lmm_size);
795                 break;
796         default:
797                 rc = -EINVAL;
798         }
799         
800         return rc;
801 }
802
803 static int fsfilt_smfs_insert_extents_ea(struct inode *inode,
804                                          unsigned long from, unsigned long num)
805 {
806         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
807         struct inode *cache_inode = NULL;
808         int    rc = -EIO;
809
810         if (!cache_fsfilt)
811                 RETURN(rc);
812
813         cache_inode = I2CI(inode);
814         if (!cache_inode)
815                 RETURN(rc);
816
817         pre_smfs_inode(inode, cache_inode);
818
819         if (cache_fsfilt->fs_insert_extents_ea)
820                 rc = cache_fsfilt->fs_insert_extents_ea(cache_inode, from, num);
821
822         post_smfs_inode(inode, cache_inode);
823         return rc;
824 }
825
826 static int fsfilt_smfs_remove_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_remove_extents_ea)
843                 rc = cache_fsfilt->fs_remove_extents_ea(cache_inode, from, num);
844
845         post_smfs_inode(inode, cache_inode);
846         return rc;
847 }
848
849 static int fsfilt_smfs_init_extents_ea(struct inode *inode)
850 {
851         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
852         struct inode *cache_inode = NULL;
853         int    rc = -EIO;
854         ENTRY;
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_init_extents_ea)
866                 rc = cache_fsfilt->fs_init_extents_ea(cache_inode);
867
868         post_smfs_inode(inode, cache_inode);
869         return rc;
870 }
871
872 static int fsfilt_smfs_free_extents(struct super_block *sb, ino_t ino,
873                                     char *pbuf, int size)
874 {
875         OBD_FREE(pbuf, size * (sizeof(struct ldlm_extent)));
876         return 0;
877 }
878
879 static int fsfilt_smfs_write_extents(struct dentry *dentry,
880                                      unsigned long from, unsigned long num)
881 {
882         /* TODO: fix this later */
883 #if 0
884         int rc = 0;
885         struct inode * cache_inode = I2CI(dentry->d_inode);
886         struct hook_write_msg msg = {
887                 .dentry = dentry,
888                 .count = num,
889                 .pos = from
890         };
891
892         ENTRY;
893         
894         pre_smfs_inode(dentry->d_inode, cache_inode);
895  
896         SMFS_PRE_HOOK(dentry->d_inode, HOOK_WRITE, &msg);
897         
898         rc = smfs_write_extents(dentry->d_inode, dentry, from, num);
899         SMFS_POST_HOOK(dentry->d_inode, HOOK_WRITE, &msg, rc);
900         post_smfs_inode(dentry->d_inode, cache_inode);
901         
902         RETURN(rc);
903 #endif
904         ENTRY;
905         RETURN(0);
906 }
907
908 static int fsfilt_smfs_precreate_rec(struct dentry *dentry, int *count, 
909                                      struct obdo *oa)
910 {
911         int rc = 0;
912         /* Why to log precreate?? MDS will do this in any case
913         if (SMFS_DO_REC(S2SMI(dentry->d_inode->i_sb)))
914                 rc = smfs_rec_precreate(dentry, count, oa);
915         */
916         return rc;
917 }
918
919 // should be rewrote when needed
920 static int fsfilt_smfs_get_ino_write_extents(struct super_block *sb, ino_t ino,
921                                              char **pbuf, int *size)
922 {
923         int rc = 0;
924 #if 0
925         struct fs_extent *fs_extents;
926         struct ldlm_extent *extents = NULL;
927         struct inode *inode;
928         struct inode *cache_inode;
929         struct fsfilt_operations *cache_fsfilt = NULL;
930         struct lvfs_run_ctxt saved;
931         int    fs_ex_size, ex_num, flags;
932         char   *buf = NULL, *ex_buf = NULL;
933         ENTRY;
934
935         push_ctxt(&saved, S2SMI(sb)->smsi_ctxt, NULL);
936
937         inode = iget(sb, ino);
938
939         if (!inode || is_bad_inode(inode)) {
940                 CWARN("Can not get inode %lu ino\n", ino);
941                 GOTO(out, rc = 0);
942         }
943         cache_inode = I2CI(inode);
944         cache_fsfilt = I2FOPS(inode);
945
946         rc = cache_fsfilt->fs_get_xattr(cache_inode, REINT_EXTENTS_FLAGS,
947                                         &flags, sizeof(int));
948         if (!(flags & SMFS_OVER_WRITE) && !(flags & SMFS_DIRTY_WRITE)) {
949                 GOTO(out, rc = 0);
950         } else if (flags & SMFS_OVER_WRITE) {
951                 *size = 1;
952                 OBD_ALLOC(ex_buf, sizeof(struct ldlm_extent));
953                 if (!ex_buf)
954                         GOTO(out, rc=-ENOMEM);
955                 extents = (struct ldlm_extent*)(ex_buf);
956                 extents->start = 0;
957                 extents->end = 0xffffffff;
958         }
959         if (rc < 0)
960                 GOTO(out, rc);
961         rc = cache_fsfilt->fs_get_write_extents_num(cache_inode, &fs_ex_size);
962         if (rc)
963                 GOTO(out, rc);
964         OBD_ALLOC(buf, fs_ex_size);
965         if (!buf)
966                 GOTO(out, rc=-ENOMEM);
967
968         rc = cache_fsfilt->fs_get_inode_write_extents(cache_inode, &buf,
969                                                       &fs_ex_size);
970         if (rc < 0)
971                 GOTO(out, rc);
972         rc = 0;
973         ex_num = fs_ex_size / sizeof(struct fs_extent);
974         *size =  ex_num;
975         OBD_ALLOC(ex_buf, ex_num* sizeof(struct ldlm_extent));
976         if (!ex_buf)
977                 GOTO(out, rc=-ENOMEM);
978
979         fs_extents = (struct fs_extent*)(buf);
980         extents = (struct ldlm_extent*)(ex_buf);
981         while (ex_num > 0) {
982                 int blk_size = I2CI(inode)->i_blksize;
983
984                 extents->start = fs_extents->e_block * blk_size;
985                 extents->end = extents->start + fs_extents->e_num * blk_size;
986                 fs_extents++;
987                 extents++;
988                 ex_num--;
989         }
990         *pbuf = ex_buf;
991 out:
992         iput(inode);
993         if (buf)
994                 OBD_FREE(buf, fs_ex_size);
995         if (rc && extents)
996                 OBD_FREE(ex_buf, (*size) * (sizeof(struct ldlm_extent)));
997         pop_ctxt(&saved, S2SMI(sb)->smsi_ctxt, NULL);
998 #endif
999         return rc;
1000 }
1001
1002 static int fsfilt_smfs_set_snap_item(struct super_block *sb, char *name)
1003 {
1004         int rc = 0;
1005
1006         ENTRY;
1007 #if CONFIG_SNAPFS
1008 #warning "still not implement for add snap item -wangdi"         
1009 #endif
1010         RETURN(rc);        
1011 }
1012 static int fsfilt_smfs_do_write_cow(struct dentry *de, void *extents,
1013                                     int num_extents)
1014 {
1015         int rc = 0;
1016 #if CONFIG_SNAPFS
1017         struct write_extents *w_ext = (struct write_extents *)extents;
1018         int i = 0;
1019         ENTRY;
1020         for (i = 0; i < num_extents; i++) {
1021                size_t count = w_ext->w_count;
1022                loff_t off = w_ext->w_pos;
1023                rc = smfs_cow_write_pre(de->d_inode, de, &count, &off);
1024                if (rc)
1025                         RETURN(rc);  
1026                w_ext ++;
1027         }
1028 #endif
1029         RETURN(rc);
1030 }
1031
1032 static int fsfilt_smfs_add_dir_entry(struct obd_device * obd,
1033                                      struct dentry * parent, char* name,
1034                                      int namelen, unsigned long ino,
1035                                      unsigned long generation,
1036                                      unsigned long mds,
1037                                      unsigned long fid) 
1038 {
1039         struct fsfilt_operations *cache_fsfilt = I2FOPS(parent->d_inode);
1040         struct dentry *cache_dentry = NULL, *dentry = NULL;
1041         struct inode *cache_parent = I2CI(parent->d_inode);
1042         int    rc = -EIO;
1043
1044         ENTRY;
1045         
1046         if (!cache_fsfilt)
1047                 RETURN(rc);
1048
1049         if (!cache_fsfilt->fs_add_dir_entry)
1050                 RETURN(-ENOSYS);
1051
1052         dentry = ll_lookup_one_len(name, parent, namelen);
1053         if (IS_ERR(dentry)) {
1054                 CERROR("can't lookup %*s in %lu/%lu: %d\n", namelen,
1055                        name, parent->d_inode->i_ino,
1056                        (unsigned long) parent->d_inode->i_generation,
1057                        (int) PTR_ERR(dentry));
1058                 RETURN(PTR_ERR(dentry));
1059         }
1060         if (dentry->d_inode != NULL || dentry->d_flags & DCACHE_CROSS_REF) {
1061                 CERROR("dentry %*s(0x%p) found\n", dentry->d_name.len,
1062                        dentry->d_name.name, dentry);
1063                 l_dput(dentry);
1064                 RETURN(-EEXIST);
1065         }
1066         /* mds_reint_rename() may use this method to add dir entry 
1067          * that points onto local inode. and we don't want to find
1068          * it cross-ref by subsequent lookups */
1069         d_drop(dentry);
1070
1071         dentry->d_flags |= DCACHE_CROSS_REF;
1072         dentry->d_inum = ino;
1073         dentry->d_mdsnum = mds;
1074         dentry->d_generation = generation;
1075         dentry->d_fid = fid;
1076         l_dput(dentry);
1077
1078         cache_dentry = pre_smfs_dentry(NULL, cache_parent, parent);
1079         if (!cache_dentry) {
1080                 RETURN(-ENOMEM);
1081         }
1082
1083         pre_smfs_inode(parent->d_inode, cache_parent);
1084         
1085         rc = cache_fsfilt->fs_add_dir_entry(obd, cache_dentry, name, namelen,
1086                                             ino, generation, mds, fid);
1087
1088         post_smfs_inode(parent->d_inode, cache_parent);
1089         
1090         post_smfs_dentry(cache_dentry);
1091         
1092         RETURN(rc);
1093         
1094 }
1095
1096 static int fsfilt_smfs_del_dir_entry(struct obd_device * obd,
1097                                      struct dentry * dentry) 
1098 {
1099         struct fsfilt_operations *cache_fsfilt = I2FOPS(dentry->d_parent->d_inode);
1100         struct dentry *cache_dentry = NULL, *cache_parent = NULL;
1101         struct inode * cache_dir = I2CI(dentry->d_parent->d_inode);
1102         struct inode * cache_inode = NULL;
1103         int    rc = -EIO;
1104
1105         ENTRY;
1106         
1107         if (!cache_fsfilt)
1108                 RETURN(rc);
1109
1110         if (!cache_fsfilt->fs_del_dir_entry)
1111                 RETURN(-ENOSYS);
1112
1113         if (dentry->d_inode)
1114                 cache_inode = I2CI(dentry->d_inode);
1115         
1116         cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry->d_parent);
1117         cache_dentry = pre_smfs_dentry(cache_parent, cache_inode, dentry);
1118         if (!cache_parent || !cache_dentry) {
1119                 rc = (-ENOMEM);
1120                 goto exit;
1121         }
1122
1123         pre_smfs_inode(dentry->d_parent->d_inode, cache_dir);
1124         pre_smfs_inode(dentry->d_inode, cache_inode);
1125         
1126         rc = cache_fsfilt->fs_del_dir_entry(obd, cache_dentry);
1127
1128         if (!rc) {
1129                 d_drop(dentry);
1130                 if (cache_inode) {
1131                         post_smfs_inode(dentry->d_inode, cache_inode);
1132                         if (S_ISDIR(dentry->d_inode->i_mode))
1133                                 dentry->d_parent->d_inode->i_nlink--;
1134                 }
1135                 post_smfs_inode(dentry->d_parent->d_inode, cache_dir);                        
1136         }
1137 exit:
1138         post_smfs_dentry(cache_dentry);
1139         post_smfs_dentry(cache_parent);
1140         RETURN(rc);
1141         
1142 }
1143
1144 static int fsfilt_smfs_set_info (struct super_block *sb, struct inode * inode,
1145                                  __u32 keylen, void *key,
1146                                  __u32 valsize, void *val)
1147 {
1148         int rc = 0;
1149         struct plg_info_msg msg = {
1150                 .key = key,
1151                 .val = val,
1152         };       
1153         ENTRY;
1154         
1155         if (keylen >= 9 && memcmp(key, "file_read", 9) == 0) {
1156                 /* 
1157                  * this key used to inform smfs on OST about incoming r/w
1158                  */
1159                 struct lustre_id * id = val;
1160                 struct hook_rw_msg msg = {
1161                         .write = 0,
1162                         .id = id,
1163                 };
1164                 if (inode)
1165                         SMFS_POST_HOOK(inode, HOOK_SI_READ, &msg, rc);
1166         }
1167         else if (keylen >= 10 && memcmp(key, "file_write", 10) == 0) {
1168                 /* 
1169                  * this key used to inform smfs on OST about incoming r/w
1170                  */
1171                 struct lustre_id * id = val;
1172                 struct hook_rw_msg msg = {
1173                         .write = 1,
1174                         .id = id,
1175                 };
1176                 if (inode)
1177                         SMFS_POST_HOOK(inode, HOOK_SI_WRITE, &msg, rc);
1178         }
1179         else if (keylen >= 10 && memcmp(key, "audit_info", 10) == 0) {
1180                 /* this key used to pass audit data on MDS */
1181                 struct audit_info * info = val;
1182                                 
1183                 SMFS_POST_HOOK(inode, HOOK_SPECIAL, info, info->m.result);
1184         }
1185         else if (keylen >= 8 && memcmp(key, "auditlog", 8) == 0) {
1186                 /* 
1187                  * this key used to inform smfs on OST about client audit data
1188                  */
1189
1190                 audit_client_log(sb, val);
1191         }
1192         else if (keylen == 5 && memcmp(key, "audit", 5) == 0) {
1193                 smfs_set_audit(sb, inode, (__u64 *)val);
1194         }   
1195         else if (keylen == 7 && memcmp(key, "id2name", 7) == 0) {
1196                 rc = SMFS_PLG_HELP(sb, PLG_SET_INFO, &msg);
1197         }
1198         else
1199                 rc = -ENOENT;
1200                 
1201         RETURN(rc);
1202 }
1203
1204 static int fsfilt_smfs_get_info (struct super_block *sb, struct inode * inode,
1205                                  __u32 keylen, void *key,
1206                                  __u32 *valsize, void *val)
1207 {
1208         int rc = -ENOENT;
1209         
1210         ENTRY;
1211         
1212         if (keylen == 5 && strcmp(key, "audit") == 0) {
1213                 __u64 * mask = val;
1214                 rc = smfs_get_audit(sb, inode, NULL, mask);
1215         }
1216                         
1217         RETURN(rc);
1218 }
1219
1220 static struct fsfilt_operations fsfilt_smfs_ops = {
1221         .fs_type                = "smfs",
1222         .fs_owner               = THIS_MODULE,
1223         .fs_start               = fsfilt_smfs_start,
1224         .fs_brw_start           = fsfilt_smfs_brw_start,
1225         .fs_commit              = fsfilt_smfs_commit,
1226         .fs_commit_async        = fsfilt_smfs_commit_async,
1227         .fs_commit_wait         = fsfilt_smfs_commit_wait,
1228         .fs_setattr             = fsfilt_smfs_setattr,
1229         .fs_iocontrol           = fsfilt_smfs_iocontrol,
1230         .fs_set_md              = fsfilt_smfs_set_md,
1231         .fs_get_md              = fsfilt_smfs_get_md,
1232         .fs_readpage            = fsfilt_smfs_readpage,
1233         .fs_getpage             = fsfilt_smfs_getpage,
1234         .fs_add_journal_cb      = fsfilt_smfs_add_journal_cb,
1235         .fs_statfs              = fsfilt_smfs_statfs,
1236         .fs_sync                = fsfilt_smfs_sync,
1237         .fs_map_inode_pages     = fsfilt_smfs_map_inode_pages,
1238         .fs_prep_san_write      = fsfilt_smfs_prep_san_write,
1239         .fs_write_record        = fsfilt_smfs_write_record,
1240         .fs_read_record         = fsfilt_smfs_read_record,
1241         .fs_setup               = fsfilt_smfs_setup,
1242         .fs_send_bio            = fsfilt_smfs_send_bio,
1243         .fs_set_xattr           = fsfilt_smfs_set_xattr,
1244         .fs_get_xattr           = fsfilt_smfs_get_xattr,
1245         .fs_get_op_len          = NULL,
1246         .fs_del_dir_entry       = fsfilt_smfs_del_dir_entry,
1247         .fs_add_dir_entry       = fsfilt_smfs_add_dir_entry,
1248         .fs_insert_extents_ea   = fsfilt_smfs_insert_extents_ea,
1249         .fs_remove_extents_ea   = fsfilt_smfs_remove_extents_ea,
1250         .fs_init_extents_ea     = fsfilt_smfs_init_extents_ea,
1251         .fs_get_ino_write_extents = fsfilt_smfs_get_ino_write_extents,
1252         .fs_get_write_extents_num = NULL,
1253
1254         .fs_free_write_extents  = fsfilt_smfs_free_extents,
1255         .fs_write_extents       = fsfilt_smfs_write_extents,
1256         .fs_post_setup          = fsfilt_smfs_post_setup,
1257         .fs_post_cleanup        = fsfilt_smfs_post_cleanup,
1258         .fs_set_fs_flags        = fsfilt_smfs_set_fs_flags,
1259         .fs_clear_fs_flags      = fsfilt_smfs_clear_fs_flags,
1260         .fs_get_fs_flags        = fsfilt_smfs_get_fs_flags,
1261         .fs_set_ost_flags       = fsfilt_smfs_set_ost_flags,
1262         .fs_set_mds_flags       = fsfilt_smfs_set_mds_flags,
1263         .fs_precreate_rec       = fsfilt_smfs_precreate_rec,
1264         .fs_set_info            = fsfilt_smfs_set_info,
1265         .fs_get_info            = fsfilt_smfs_get_info,
1266         .fs_set_snap_item       = fsfilt_smfs_set_snap_item,
1267         .fs_do_write_cow        = fsfilt_smfs_do_write_cow,
1268 };
1269
1270 struct fsfilt_operations *get_smfs_fs_ops(void)
1271 {
1272         return (&fsfilt_smfs_ops);
1273 }
1274 EXPORT_SYMBOL(get_smfs_fs_ops);
1275
1276