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