Whamcloud - gitweb
1)do precreate record in obdfilter
[fs/lustre-release.git] / lustre / lvfs / fsfilt_smfs.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  lustre/lib/fsfilt_smfs.c
5  *  Lustre filesystem abstraction routines
6  *
7  *  Copyright (C) 2004 Cluster File Systems, Inc.
8  *   Author: Wang Di <wangdi@clusterfs.com>
9  *
10  *   This file is part of Lustre, http://www.lustre.org.
11  *
12  *   Lustre is free software; you can redistribute it and/or
13  *   modify it under the terms of version 2 of the GNU General Public
14  *   License as published by the Free Software Foundation.
15  *
16  *   Lustre is distributed in the hope that it will be useful,
17  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *   GNU General Public License for more details.
20  *
21  *   You should have received a copy of the GNU General Public License
22  *   along with Lustre; if not, write to the Free Software
23  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  */
25
26 #define DEBUG_SUBSYSTEM S_FILTER
27
28 #include <linux/fs.h>
29 #include <linux/jbd.h>
30 #include <linux/slab.h>
31 #include <linux/pagemap.h>
32 #include <linux/quotaops.h>
33 #include <linux/version.h>
34 #include <linux/kp30.h>
35 #include <linux/lustre_fsfilt.h>
36 #include <linux/lustre_smfs.h>
37 #include <linux/obd.h>
38 #include <linux/obd_class.h>
39 #include <linux/module.h>
40 #include <linux/init.h>
41
42 static void *fsfilt_smfs_start(struct inode *inode, int op,
43                                void *desc_private, int logs)
44 {
45         void *handle;
46         struct inode *cache_inode = I2CI(inode);
47         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
48
49         if (cache_fsfilt == NULL)
50                 return NULL;
51
52         SMFS_TRANS_OP(inode, op);
53
54         if (!cache_fsfilt->fs_start)
55                 return ERR_PTR(-ENOSYS);
56
57         handle = cache_fsfilt->fs_start(cache_inode, op, desc_private, logs);
58         return handle;
59 }
60
61 static void *fsfilt_smfs_brw_start(int objcount, struct fsfilt_objinfo *fso,
62                                    int niocount, struct niobuf_local *nb,
63                                    void *desc_private, int logs)
64 {
65         struct fsfilt_operations *cache_fsfilt;
66         struct dentry *cache_dentry = NULL;
67         struct inode *cache_inode = NULL;
68         struct fsfilt_objinfo cache_fso;
69         void   *rc = NULL;
70
71         ENTRY;
72         cache_fsfilt = I2FOPS(fso->fso_dentry->d_inode);
73         if (cache_fsfilt == NULL)
74                 return NULL;
75
76         cache_inode = I2CI(fso->fso_dentry->d_inode);
77          cache_dentry = pre_smfs_dentry(NULL, cache_inode, fso->fso_dentry);
78
79         if (!cache_dentry)
80                 GOTO(exit, rc = ERR_PTR(-ENOMEM));
81
82         cache_fso.fso_dentry = cache_dentry;
83         cache_fso.fso_bufcnt = fso->fso_bufcnt;
84
85         if (!cache_fsfilt->fs_brw_start)
86                 return ERR_PTR(-ENOSYS);
87
88         rc = cache_fsfilt->fs_brw_start(objcount, &cache_fso, niocount, nb,
89                                         desc_private, logs);
90 exit:
91         post_smfs_dentry(cache_dentry);
92         return rc;
93 }
94
95 /* FIXME-WANGDI: here we can easily have inode == NULL due to
96    mds_open() behavior. It passes NULL inode to mds_finish_transno()
97    sometimes. Probably we should have spare way to get cache fsfilt
98    operations. */
99 static int fsfilt_smfs_commit(struct super_block *sb, struct inode *inode, 
100                               void *h, int force_sync)
101 {
102         struct fsfilt_operations *cache_fsfilt = S2SMI(sb)->sm_cache_fsfilt;
103         struct super_block *csb = S2CSB(sb); 
104         struct inode *cache_inode = NULL;
105         int    rc = -EIO;
106
107         if (inode)
108                 cache_inode = I2CI(inode);
109
110         if (cache_fsfilt == NULL)
111                 RETURN(rc);
112
113         if (!cache_fsfilt->fs_commit)
114                 RETURN(-ENOSYS);
115
116         rc = cache_fsfilt->fs_commit(csb, cache_inode, h, force_sync);
117
118         RETURN(rc);
119 }
120
121 static int fsfilt_smfs_commit_async(struct inode *inode, void *h,
122                                     void **wait_handle)
123 {
124         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
125         struct inode *cache_inode = NULL;
126         int    rc = -EIO;
127
128         cache_inode = I2CI(inode);
129         if (cache_fsfilt == NULL)
130                 RETURN(-EINVAL);
131
132         if (!cache_fsfilt->fs_commit_async)
133                 RETURN(-ENOSYS);
134
135         rc = cache_fsfilt->fs_commit_async(cache_inode, h, wait_handle);
136
137         RETURN(rc);
138 }
139
140 static int fsfilt_smfs_commit_wait(struct inode *inode, void *h)
141 {
142         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
143         struct inode *cache_inode = NULL;
144         int    rc = -EIO;
145
146         cache_inode = I2CI(inode);
147         if (cache_fsfilt == NULL)
148                 RETURN(-EINVAL);
149
150         if (!cache_fsfilt->fs_commit_wait)
151                 RETURN(-ENOSYS);
152
153         rc = cache_fsfilt->fs_commit_wait(cache_inode, h);
154
155         RETURN(rc);
156 }
157
158 static int fsfilt_smfs_setattr(struct dentry *dentry, void *handle,
159                                struct iattr *iattr, int do_trunc)
160 {
161         struct fsfilt_operations *cache_fsfilt = I2FOPS(dentry->d_inode);
162         struct dentry *cache_dentry = NULL;
163         struct inode *cache_inode = NULL;
164         int    rc = -EIO;
165
166         if (!cache_fsfilt)
167                 RETURN(rc);
168
169         cache_inode = I2CI(dentry->d_inode);
170
171         cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
172         if (!cache_dentry)
173                 GOTO(exit, rc = -ENOMEM);
174
175         pre_smfs_inode(dentry->d_inode, cache_inode);
176
177         if (!cache_fsfilt->fs_setattr)
178                 RETURN(-ENOSYS);
179
180         rc = cache_fsfilt->fs_setattr(cache_dentry, handle, iattr, do_trunc);
181
182         post_smfs_inode(dentry->d_inode, cache_inode);
183
184         if (rc == 0) {
185                 struct super_block *sb = dentry->d_inode->i_sb;
186
187                 if (SMFS_DO_REC(S2SMI(sb)) && 
188                     SMFS_DO_INODE_REC(dentry->d_inode)) {
189                         rc = smfs_rec_setattr(dentry->d_inode, dentry, iattr);
190                 }
191         }
192 exit:
193         post_smfs_dentry(cache_dentry);
194         RETURN(rc);
195 }
196
197 static int fsfilt_smfs_iocontrol(struct inode *inode, struct file *file,
198                                  unsigned int cmd, unsigned long arg)
199 {
200         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
201         struct inode *cache_inode = NULL;
202         struct smfs_file_info *sfi = NULL;
203         int    rc = -EIO;
204         ENTRY;
205
206         if (!cache_fsfilt)
207                 RETURN(rc);
208
209         cache_inode = I2CI(inode);
210
211         if (!cache_inode)
212                 RETURN(rc);
213
214         if (file != NULL) {
215                 sfi = F2SMFI(file);
216
217                 if (sfi->magic != SMFS_FILE_MAGIC)
218                         BUG();
219         } else {
220                 sfi = NULL;
221         }
222
223         if (!cache_fsfilt->fs_iocontrol)
224                 RETURN(-ENOSYS);
225
226         if (sfi) {
227                 rc = cache_fsfilt->fs_iocontrol(cache_inode, sfi->c_file, cmd,
228                                                 arg);
229         } else {
230                 rc = cache_fsfilt->fs_iocontrol(cache_inode, NULL, cmd, arg);
231         }
232
233         /* FIXME-UMKA: Should this be in duplicate_inode()? */
234         if (rc == 0 && cmd == EXT3_IOC_SETFLAGS)
235                 inode->i_flags = cache_inode->i_flags;
236
237         post_smfs_inode(inode, cache_inode);
238
239         RETURN(rc);
240 }
241
242 static int fsfilt_smfs_set_md(struct inode *inode, void *handle,
243                               void *lmm, int lmm_size)
244 {
245         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
246         struct inode *cache_inode = NULL;
247         int    rc = -EIO;
248
249         if (!cache_fsfilt)
250                 RETURN(-EINVAL);
251
252         cache_inode = I2CI(inode);
253
254         if (!cache_inode)
255                 RETURN(-ENOENT);
256
257         pre_smfs_inode(inode, cache_inode);
258
259         if (!cache_fsfilt->fs_set_md)
260                 RETURN(-ENOSYS);
261
262         down(&cache_inode->i_sem);
263         rc = cache_fsfilt->fs_set_md(cache_inode, handle, lmm, lmm_size);
264         up(&cache_inode->i_sem);
265
266         post_smfs_inode(inode, cache_inode);
267
268         smfs_rec_md(inode, lmm, lmm_size);
269
270         RETURN(rc);
271 }
272
273 /* Must be called with i_sem held */
274 static int fsfilt_smfs_get_md(struct inode *inode, void *lmm, int lmm_size)
275 {
276         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
277         struct inode *cache_inode = NULL;
278         int    rc = -EIO;
279
280         if (!cache_fsfilt)
281                 RETURN(-EINVAL);
282
283         cache_inode = I2CI(inode);
284
285         if (!cache_inode)
286                 RETURN(-ENOENT);
287
288         pre_smfs_inode(inode, cache_inode);
289
290         if (!cache_fsfilt->fs_get_md)
291                 RETURN(-ENOSYS);
292
293         down(&cache_inode->i_sem);
294         rc = cache_fsfilt->fs_get_md(cache_inode, lmm, lmm_size);
295         up(&cache_inode->i_sem);
296
297         post_smfs_inode(inode, cache_inode);
298
299         RETURN(rc);
300 }
301
302 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
303 static int fsfilt_smfs_send_bio(struct inode *inode, struct bio *bio)
304 #else
305 static int fsfilt_smfs_send_bio(struct inode *inode, struct kiobuf *bio)
306 #endif
307 {
308         struct inode *cache_inode;
309         struct fsfilt_operations *cache_fsfilt;
310
311         cache_fsfilt = I2FOPS(inode);
312         if (!cache_fsfilt)
313                 RETURN(-EINVAL);
314
315         cache_inode = I2CI(inode);
316         if (!cache_inode)
317                 RETURN(-EINVAL);
318
319         if (!cache_fsfilt->fs_send_bio)
320                 RETURN(-ENOSYS);
321
322         return cache_fsfilt->fs_send_bio(cache_inode, bio);
323 }
324
325 static struct page *
326 fsfilt_smfs_getpage(struct inode *inode, long int index)
327 {
328         struct  fsfilt_operations *cache_fsfilt;
329         struct  inode *cache_inode;
330
331         cache_fsfilt = I2FOPS(inode);
332         if (!cache_fsfilt)
333                 RETURN(ERR_PTR(-EINVAL));
334
335         cache_inode = I2CI(inode);
336         if (!cache_inode)
337                 RETURN(ERR_PTR(-EINVAL));
338
339         if (!cache_fsfilt->fs_getpage)
340                 RETURN(ERR_PTR(-ENOSYS));
341
342         return cache_fsfilt->fs_getpage(cache_inode, index);
343 }
344
345 static ssize_t fsfilt_smfs_readpage(struct file *file, char *buf,
346                                     size_t count, loff_t *off)
347 {
348         struct fsfilt_operations *cache_fsfilt;
349         struct smfs_file_info *sfi;
350         struct inode *cache_inode;
351         loff_t tmp_ppos;
352         loff_t *cache_ppos;
353         ssize_t rc = -EIO;
354
355         ENTRY;
356
357         cache_fsfilt = I2FOPS(file->f_dentry->d_inode);
358         if (!cache_fsfilt)
359                 RETURN(rc);
360
361         cache_inode = I2CI(file->f_dentry->d_inode);
362         if (!cache_inode)
363                 RETURN(rc);
364
365         sfi = F2SMFI(file);
366         if (sfi->magic != SMFS_FILE_MAGIC)
367                 BUG();
368
369         if (off != &(file->f_pos))
370                 cache_ppos = &tmp_ppos;
371         else
372                 cache_ppos = &sfi->c_file->f_pos;
373         *cache_ppos = *off;
374
375         pre_smfs_inode(file->f_dentry->d_inode, cache_inode);
376
377         if (cache_fsfilt->fs_readpage)
378                 rc = cache_fsfilt->fs_readpage(sfi->c_file, buf, count,
379                                                cache_ppos);
380
381         *off = *cache_ppos;
382         post_smfs_inode(file->f_dentry->d_inode, cache_inode);
383         duplicate_file(file, sfi->c_file);
384
385         RETURN(rc);
386 }
387
388
389 static int fsfilt_smfs_add_journal_cb(struct obd_device *obd,
390                                       struct super_block *sb, __u64 last_rcvd,
391                                       void *handle, fsfilt_cb_t cb_func,
392                                       void *cb_data)
393 {
394         struct fsfilt_operations *cache_fsfilt = S2SMI(sb)->sm_cache_fsfilt;
395         struct super_block *csb = S2CSB(sb);
396         int rc = -EIO;
397
398         if (!cache_fsfilt)
399                  RETURN(rc);
400         if (cache_fsfilt->fs_add_journal_cb)
401                 rc = cache_fsfilt->fs_add_journal_cb(obd, csb, last_rcvd,
402                                                      handle, cb_func, cb_data);
403         RETURN(rc);
404 }
405
406 static int fsfilt_smfs_statfs(struct super_block *sb, struct obd_statfs *osfs)
407 {
408         struct fsfilt_operations *cache_fsfilt = S2SMI(sb)->sm_cache_fsfilt;
409         struct super_block *csb = S2CSB(sb);
410         int rc = -EIO;
411
412         if (!cache_fsfilt)
413                 RETURN(rc);
414
415         if (!cache_fsfilt->fs_statfs)
416                 RETURN(-ENOSYS);
417
418         rc = cache_fsfilt->fs_statfs(csb, osfs);
419         duplicate_sb(csb, sb);
420
421         RETURN(rc);
422 }
423
424 static int fsfilt_smfs_sync(struct super_block *sb)
425 {
426         struct fsfilt_operations *cache_fsfilt = S2SMI(sb)->sm_cache_fsfilt;
427         struct super_block *csb = S2CSB(sb);
428         int    rc = -EIO;
429
430         if (!cache_fsfilt)
431                 RETURN(-EINVAL);
432
433         if (!cache_fsfilt->fs_sync)
434                 RETURN(-ENOSYS);
435
436         rc = cache_fsfilt->fs_sync(csb);
437
438         RETURN(rc);
439 }
440
441 int fsfilt_smfs_map_inode_pages(struct inode *inode, struct page **page,
442                                 int pages, unsigned long *blocks, int *created,
443                                 int create, struct semaphore *sem)
444 {
445         struct  fsfilt_operations *cache_fsfilt = I2FOPS(inode);
446         struct  inode *cache_inode = NULL;
447         int     rc = -EIO;
448
449         if (!cache_fsfilt)
450                 RETURN(-EINVAL);
451
452         cache_inode = I2CI(inode);
453
454         if (!cache_inode)
455                 RETURN(rc);
456
457         if (!cache_fsfilt->fs_map_inode_pages)
458                 RETURN(-ENOSYS);
459
460         down(&cache_inode->i_sem);
461         rc = cache_fsfilt->fs_map_inode_pages(cache_inode, page, pages, blocks,
462                                               created, create, sem);
463         up(&cache_inode->i_sem);
464
465         RETURN(rc);
466 }
467
468 static int fsfilt_smfs_prep_san_write(struct inode *inode, long *blocks,
469                                       int nblocks, loff_t newsize)
470 {
471         struct  fsfilt_operations *cache_fsfilt = I2FOPS(inode);
472         struct  inode *cache_inode = NULL;
473         int     rc = -EIO;
474
475         if (!cache_fsfilt)
476                 RETURN(-EINVAL);
477
478         cache_inode = I2CI(inode);
479
480         if (!cache_inode)
481                 RETURN(-EINVAL);
482
483         if (!cache_fsfilt->fs_prep_san_write)
484                 RETURN(-ENOSYS);
485
486         down(&cache_inode->i_sem);
487         rc = cache_fsfilt->fs_prep_san_write(cache_inode, blocks, nblocks,
488                                              newsize);
489         up(&cache_inode->i_sem);
490
491         RETURN(rc);
492 }
493
494 static int fsfilt_smfs_read_record(struct file * file, void *buf,
495                                    int size, loff_t *offs)
496 {
497         struct  fsfilt_operations *cache_fsfilt;
498         struct  inode *cache_inode;
499         struct  smfs_file_info *sfi;
500         loff_t  tmp_ppos;
501         loff_t  *cache_ppos;
502         ssize_t rc;
503
504         ENTRY;
505         cache_fsfilt = I2FOPS(file->f_dentry->d_inode);
506         if (!cache_fsfilt)
507                 RETURN(-EINVAL);
508
509         cache_inode = I2CI(file->f_dentry->d_inode);
510
511         if (!cache_inode)
512                 RETURN(-EINVAL);
513
514         sfi = F2SMFI(file);
515         if (sfi->magic != SMFS_FILE_MAGIC) BUG();
516
517         if (offs != &(file->f_pos))
518                 cache_ppos = &tmp_ppos;
519         else
520                 cache_ppos = &sfi->c_file->f_pos;
521         *cache_ppos = *offs;
522
523         pre_smfs_inode(file->f_dentry->d_inode, cache_inode);
524
525         if (!cache_fsfilt->fs_read_record)
526                 RETURN(-ENOSYS);
527
528         rc = cache_fsfilt->fs_read_record(sfi->c_file, buf, size, cache_ppos);
529
530         *offs = *cache_ppos;
531         post_smfs_inode(file->f_dentry->d_inode, cache_inode);
532         duplicate_file(file, sfi->c_file);
533
534         RETURN(rc);
535 }
536
537 static int fsfilt_smfs_write_record(struct file *file, void *buf, int bufsize,
538                                     loff_t *offs, int force_sync)
539 {
540         struct  fsfilt_operations *cache_fsfilt;
541         struct  inode *cache_inode;
542         struct  smfs_file_info *sfi;
543         loff_t  tmp_ppos;
544         loff_t  *cache_ppos;
545         ssize_t rc = -EIO;
546
547         ENTRY;
548
549         cache_fsfilt = I2FOPS(file->f_dentry->d_inode);
550         if (!cache_fsfilt)
551                 RETURN(-EINVAL);
552
553         cache_inode = I2CI(file->f_dentry->d_inode);
554
555         if (!cache_inode)
556                 RETURN(-EINVAL);
557
558         sfi = F2SMFI(file);
559         if (sfi->magic != SMFS_FILE_MAGIC)
560                 BUG();
561
562         if (offs != &(file->f_pos))
563                 cache_ppos = &tmp_ppos;
564         else
565                 cache_ppos = &sfi->c_file->f_pos;
566         *cache_ppos = *offs;
567
568         pre_smfs_inode(file->f_dentry->d_inode, cache_inode);
569
570         if (!cache_fsfilt->fs_write_record)
571                 RETURN(-ENOSYS);
572
573         rc = cache_fsfilt->fs_write_record(sfi->c_file, buf,
574                                            bufsize, cache_ppos, force_sync);
575         *offs = *cache_ppos;
576         post_smfs_inode(file->f_dentry->d_inode, cache_inode);
577         duplicate_file(file, sfi->c_file);
578
579         RETURN(rc);
580 }
581
582 static int fsfilt_smfs_post_setup(struct obd_device *obd, struct vfsmount *mnt)
583 {
584         struct super_block *sb = NULL;
585         int rc = 0;
586
587         if (mnt) {
588                 sb = mnt->mnt_sb;
589                 S2SMI(sb)->smsi_exp = obd->obd_self_export;
590                 if (SMFS_DO_REC(S2SMI(sb)))
591                         rc = smfs_start_rec(sb, mnt);
592                 if (rc)
593                         GOTO(exit, rc);
594                 if (obd)
595                         obd->obd_llog_ctxt[LLOG_REINT_ORIG_CTXT] =
596                                         S2SMI(sb)->smsi_rec_log;
597         }
598 exit:
599         if (rc)
600                 CERROR("can not do post setup in obd %p rc=%d", obd, rc);
601
602         RETURN(rc);
603 }
604
605 static int fsfilt_smfs_post_cleanup(struct obd_device *obd,
606                                     struct vfsmount *mnt)
607 {
608         struct super_block *sb = NULL;
609         int rc = 0;
610
611         if (mnt) {
612                 sb = mnt->mnt_sb;
613                 if (SMFS_DO_REC(S2SMI(sb)))
614                         rc = smfs_stop_rec(sb);
615         }
616         RETURN(rc);
617 }
618
619 static int fsfilt_smfs_set_kml_flags(struct inode *inode)
620 {
621         int rc = 0;
622         if (SMFS_DO_REC(S2SMI(inode->i_sb)))
623                 SMFS_SET_INODE_REC(inode);
624         RETURN(rc);
625 }
626
627 static int fsfilt_smfs_clear_kml_flags(struct inode *inode)
628 {
629         int rc = 0;
630         if (SMFS_DO_REC(S2SMI(inode->i_sb)))
631                 SMFS_CLEAN_INODE_REC(inode);
632         RETURN(rc);
633 }
634
635 static int fsfilt_smfs_set_ost_flags(struct super_block *sb)
636 {
637         int rc = 0;
638         SET_REC_PACK_TYPE_INDEX(S2SMI(sb)->smsi_flags, PACK_OST);
639         RETURN(rc);
640 }
641
642 static int fsfilt_smfs_set_mds_flags(struct super_block *sb)
643 {
644         int rc = 0;
645         SET_REC_PACK_TYPE_INDEX(S2SMI(sb)->smsi_flags, PACK_MDS);
646         RETURN(rc);
647 }
648
649 static int fsfilt_smfs_get_reint_log_ctxt(struct super_block *sb,
650                                           struct llog_ctxt **ctxt)
651 {
652         struct smfs_super_info *smfs_info = S2SMI(sb);
653         int rc = 0;
654
655         *ctxt = smfs_info->smsi_rec_log;
656         RETURN(rc);
657 }
658
659 static int fsfilt_smfs_setup(struct obd_device *obd, struct super_block *sb)
660 {
661         struct smfs_super_info *smfs_info = S2SMI(sb);
662         struct fsfilt_operations *cache_fsfilt;
663         struct super_block *csb;
664         int rc = 0;
665
666         /* It should be initialized olready by smfs_read_super(). */
667         if (!(cache_fsfilt = smfs_info->sm_cache_fsfilt))
668                     cache_fsfilt = fsfilt_get_ops(smfs_info->smsi_cache_ftype);
669
670         if (!cache_fsfilt)
671                 RETURN(-ENOENT);
672
673         csb = S2CSB(sb);
674         if (cache_fsfilt->fs_setup) 
675                 rc = cache_fsfilt->fs_setup(obd, csb);
676         RETURN(rc);
677 }
678
679 static int fsfilt_smfs_set_xattr(struct inode *inode, void *handle, char *name,
680                                  void *buffer, int buffer_size)
681 {
682         struct  fsfilt_operations *cache_fsfilt = I2FOPS(inode);
683         struct  inode *cache_inode = NULL;
684         int     rc = -EIO;
685
686         if (!cache_fsfilt)
687                 RETURN(rc);
688
689         cache_inode = I2CI(inode);
690         if (!cache_inode)
691                 RETURN(rc);
692
693         pre_smfs_inode(inode, cache_inode);
694
695         if (cache_fsfilt->fs_set_xattr)
696                 rc = cache_fsfilt->fs_set_xattr(cache_inode, handle, name,
697                                                 buffer, buffer_size);
698         post_smfs_inode(inode, cache_inode);
699
700         RETURN(rc);
701 }
702
703 static int fsfilt_smfs_get_xattr(struct inode *inode, char *name,
704                                  void *buffer, int buffer_size)
705 {
706         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
707         struct inode *cache_inode = NULL;
708         int    rc = -EIO;
709
710         if (!cache_fsfilt)
711                 RETURN(rc);
712
713         cache_inode = I2CI(inode);
714         if (!cache_inode)
715                 RETURN(rc);
716
717         pre_smfs_inode(inode, cache_inode);
718
719         if (cache_fsfilt->fs_get_xattr)
720                 rc = cache_fsfilt->fs_get_xattr(cache_inode, name,
721                                                 buffer, buffer_size);
722         post_smfs_inode(inode, cache_inode);
723
724         RETURN(rc);
725 }
726
727 static int fsfilt_smfs_insert_extents_ea(struct inode *inode,
728                                          unsigned long from, unsigned long num)
729 {
730         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
731         struct inode *cache_inode = NULL;
732         int    rc = -EIO;
733
734         if (!cache_fsfilt)
735                 RETURN(rc);
736
737         cache_inode = I2CI(inode);
738         if (!cache_inode)
739                 RETURN(rc);
740
741         pre_smfs_inode(inode, cache_inode);
742
743         if (cache_fsfilt->fs_insert_extents_ea)
744                 rc = cache_fsfilt->fs_insert_extents_ea(cache_inode, from, num);
745
746         post_smfs_inode(inode, cache_inode);
747         return rc;
748 }
749
750 static int fsfilt_smfs_remove_extents_ea(struct inode *inode,
751                                          unsigned long from, unsigned long num)
752 {
753         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
754         struct inode *cache_inode = NULL;
755         int    rc = -EIO;
756
757         if (!cache_fsfilt)
758                 RETURN(rc);
759
760         cache_inode = I2CI(inode);
761         if (!cache_inode)
762                 RETURN(rc);
763
764         pre_smfs_inode(inode, cache_inode);
765
766         if (cache_fsfilt->fs_remove_extents_ea)
767                 rc = cache_fsfilt->fs_remove_extents_ea(cache_inode, from, num);
768
769         post_smfs_inode(inode, cache_inode);
770         return rc;
771 }
772
773 static int fsfilt_smfs_init_extents_ea(struct inode *inode)
774 {
775         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
776         struct inode *cache_inode = NULL;
777         int    rc = -EIO;
778
779         if (!cache_fsfilt)
780                 RETURN(rc);
781
782         cache_inode = I2CI(inode);
783         if (!cache_inode)
784                 RETURN(rc);
785
786         pre_smfs_inode(inode, cache_inode);
787
788         if (cache_fsfilt->fs_init_extents_ea)
789                 rc = cache_fsfilt->fs_init_extents_ea(cache_inode);
790
791         post_smfs_inode(inode, cache_inode);
792         return rc;
793 }
794
795 static int fsfilt_smfs_free_extents(struct super_block *sb, ino_t ino,
796                                     char *pbuf, int size)
797 {
798         OBD_FREE(pbuf, size * (sizeof(struct ldlm_extent)));
799         return 0;
800 }
801
802 static int fsfilt_smfs_write_extents(struct dentry *dentry,
803                                      unsigned long from, unsigned long num)
804 {
805         int rc = 0;
806
807         if (SMFS_DO_REC(S2SMI(dentry->d_inode->i_sb)))
808                 rc = smfs_write_extents(dentry->d_inode, dentry, from, num);
809
810         return rc;
811 }
812
813 static int fsfilt_smfs_precreate_rec(struct dentry *dentry, int *count, 
814                                      struct obdo *oa)
815 {
816         int rc = 0;
817
818         if (SMFS_DO_REC(S2SMI(dentry->d_inode->i_sb)))
819                 rc = smfs_rec_precreate(dentry, count, oa);
820
821         return rc;
822 }
823
824 static int fsfilt_smfs_get_ino_write_extents(struct super_block *sb, ino_t ino,
825                                              char **pbuf, int *size)
826 {
827         struct fs_extent *fs_extents;
828         struct ldlm_extent *extents;
829         struct inode *inode;
830         struct inode *cache_inode;
831         struct fsfilt_operations *cache_fsfilt = NULL;
832         struct lvfs_run_ctxt saved;
833         int    rc = 0, fs_ex_size, ex_num, flags;
834         char   *buf = NULL, *ex_buf = NULL;
835
836         push_ctxt(&saved, S2SMI(sb)->smsi_ctxt, NULL);
837
838         inode = iget(sb, ino);
839
840         if (!inode || is_bad_inode(inode)) {
841                 CWARN("Can not get inode %lu ino\n", ino);
842                 GOTO(out, rc = 0);
843         }
844         cache_inode = I2CI(inode);
845         cache_fsfilt = I2FOPS(inode);
846
847         rc = cache_fsfilt->fs_get_xattr(cache_inode, REINT_EXTENTS_FLAGS,
848                                         &flags, sizeof(int));
849         if (!(flags & SMFS_OVER_WRITE) && !(flags & SMFS_DIRTY_WRITE)) {
850                 GOTO(out, rc = 0);
851         } else if (flags & SMFS_OVER_WRITE) {
852                 *size = 1;
853                 OBD_ALLOC(ex_buf, sizeof(struct ldlm_extent));
854                 if (!ex_buf)
855                         GOTO(out, rc=-ENOMEM);
856                 extents = (struct ldlm_extent*)(ex_buf);
857                 extents->start = 0;
858                 extents->end = 0xffffffff;
859         }
860         if (rc < 0)
861                 GOTO(out, rc);
862         rc = cache_fsfilt->fs_get_write_extents_num(cache_inode, &fs_ex_size);
863         if (rc)
864                 GOTO(out, rc);
865         OBD_ALLOC(buf, fs_ex_size);
866         if (!buf)
867                 GOTO(out, rc=-ENOMEM);
868
869         rc = cache_fsfilt->fs_get_inode_write_extents(cache_inode, &buf,
870                                                       &fs_ex_size);
871         if (rc < 0)
872                 GOTO(out, rc);
873         rc = 0;
874         ex_num = fs_ex_size / sizeof(struct fs_extent);
875         *size =  ex_num;
876         OBD_ALLOC(ex_buf, ex_num* sizeof(struct ldlm_extent));
877         if (!ex_buf)
878                 GOTO(out, rc=-ENOMEM);
879
880         fs_extents = (struct fs_extent*)(buf);
881         extents = (struct ldlm_extent*)(ex_buf);
882         while (ex_num > 0) {
883                 int blk_size = I2CI(inode)->i_blksize;
884
885                 extents->start = fs_extents->e_block * blk_size;
886                 extents->end = extents->start + fs_extents->e_num * blk_size;
887                 fs_extents++;
888                 extents++;
889                 ex_num--;
890         }
891         *pbuf = ex_buf;
892 out:
893         iput(inode);
894         if (buf)
895                 OBD_FREE(buf, fs_ex_size);
896         if (rc && extents)
897                 OBD_FREE(ex_buf, (*size) * (sizeof(struct ldlm_extent)));
898         pop_ctxt(&saved, S2SMI(sb)->smsi_ctxt, NULL);
899         return rc;
900 }
901
902 static struct fsfilt_operations fsfilt_smfs_ops = {
903         .fs_type                = "smfs",
904         .fs_owner               = THIS_MODULE,
905         .fs_start               = fsfilt_smfs_start,
906         .fs_brw_start           = fsfilt_smfs_brw_start,
907         .fs_commit              = fsfilt_smfs_commit,
908         .fs_commit_async        = fsfilt_smfs_commit_async,
909         .fs_commit_wait         = fsfilt_smfs_commit_wait,
910         .fs_setattr             = fsfilt_smfs_setattr,
911         .fs_iocontrol           = fsfilt_smfs_iocontrol,
912         .fs_set_md              = fsfilt_smfs_set_md,
913         .fs_get_md              = fsfilt_smfs_get_md,
914         .fs_readpage            = fsfilt_smfs_readpage,
915         .fs_getpage             = fsfilt_smfs_getpage,
916         .fs_add_journal_cb      = fsfilt_smfs_add_journal_cb,
917         .fs_statfs              = fsfilt_smfs_statfs,
918         .fs_sync                = fsfilt_smfs_sync,
919         .fs_map_inode_pages     = fsfilt_smfs_map_inode_pages,
920         .fs_prep_san_write      = fsfilt_smfs_prep_san_write,
921         .fs_write_record        = fsfilt_smfs_write_record,
922         .fs_read_record         = fsfilt_smfs_read_record,
923         .fs_setup               = fsfilt_smfs_setup,
924         .fs_post_setup          = fsfilt_smfs_post_setup,
925         .fs_post_cleanup        = fsfilt_smfs_post_cleanup,
926         .fs_set_kml_flags       = fsfilt_smfs_set_kml_flags,
927         .fs_clear_kml_flags     = fsfilt_smfs_clear_kml_flags,
928         .fs_set_ost_flags       = fsfilt_smfs_set_ost_flags,
929         .fs_set_mds_flags       = fsfilt_smfs_set_mds_flags,
930         .fs_precreate_rec       = fsfilt_smfs_precreate_rec,
931         .fs_get_reint_log_ctxt  = fsfilt_smfs_get_reint_log_ctxt,
932         .fs_send_bio            = fsfilt_smfs_send_bio,
933         .fs_set_xattr           = fsfilt_smfs_set_xattr,
934         .fs_get_xattr           = fsfilt_smfs_get_xattr,
935         .fs_init_extents_ea     = fsfilt_smfs_init_extents_ea,
936         .fs_insert_extents_ea   = fsfilt_smfs_insert_extents_ea,
937         .fs_remove_extents_ea   = fsfilt_smfs_remove_extents_ea,
938         .fs_get_ino_write_extents = fsfilt_smfs_get_ino_write_extents,
939         .fs_free_write_extents  = fsfilt_smfs_free_extents,
940         .fs_write_extents       = fsfilt_smfs_write_extents,
941         /* FIXME-UMKA: probably fsfilt_smfs_get_op_len() should be
942          * put here too. */
943 };
944
945 static int __init fsfilt_smfs_init(void)
946 {
947         int rc;
948
949         rc = fsfilt_register_ops(&fsfilt_smfs_ops);
950         return rc;
951 }
952
953 static void __exit fsfilt_smfs_exit(void)
954 {
955         fsfilt_unregister_ops(&fsfilt_smfs_ops);
956 }
957
958 module_init(fsfilt_smfs_init);
959 module_exit(fsfilt_smfs_exit);
960
961 MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
962 MODULE_DESCRIPTION("Lustre SMFS Filesystem Helper v0.1");
963 MODULE_LICENSE("GPL");