Whamcloud - gitweb
- mds_lock_mode_for_dir() should check also MDS_NO_SPLIT_EXPECTED.
[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 #include <linux/lustre_snap.h>
43 #include <linux/lustre_smfs.h>
44 static void *fsfilt_smfs_start(struct inode *inode, int op,
45                                void *desc_private, int logs)
46 {
47         void *handle;
48         struct inode *cache_inode = I2CI(inode);
49         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
50
51         if (cache_fsfilt == NULL)
52                 return NULL;
53
54         SMFS_TRANS_OP(inode, op);
55
56         if (!cache_fsfilt->fs_start)
57                 return ERR_PTR(-ENOSYS);
58
59         handle = cache_fsfilt->fs_start(cache_inode, op, desc_private, logs);
60         return handle;
61 }
62
63 static void *fsfilt_smfs_brw_start(int objcount, struct fsfilt_objinfo *fso,
64                                    int niocount, struct niobuf_local *nb,
65                                    void *desc_private, int logs)
66 {
67         struct fsfilt_operations *cache_fsfilt;
68         struct dentry *cache_dentry = NULL;
69         struct inode *cache_inode = NULL;
70         struct fsfilt_objinfo cache_fso;
71         void   *rc = NULL;
72
73         ENTRY;
74         cache_fsfilt = I2FOPS(fso->fso_dentry->d_inode);
75         if (cache_fsfilt == NULL)
76                 return NULL;
77
78         cache_inode = I2CI(fso->fso_dentry->d_inode);
79         cache_dentry = pre_smfs_dentry(NULL, cache_inode, fso->fso_dentry, 
80                                        NULL);
81
82         if (!cache_dentry)
83                 GOTO(exit, rc = ERR_PTR(-ENOMEM));
84
85         cache_fso.fso_dentry = cache_dentry;
86         cache_fso.fso_bufcnt = fso->fso_bufcnt;
87
88         if (!cache_fsfilt->fs_brw_start)
89                 return ERR_PTR(-ENOSYS);
90
91         rc = cache_fsfilt->fs_brw_start(objcount, &cache_fso, niocount, nb,
92                                         desc_private, logs);
93 exit:
94         post_smfs_dentry(cache_dentry);
95         return rc;
96 }
97
98 /* FIXME-WANGDI: here we can easily have inode == NULL due to
99    mds_open() behavior. It passes NULL inode to mds_finish_transno()
100    sometimes. Probably we should have spare way to get cache fsfilt
101    operations. */
102 static int fsfilt_smfs_commit(struct super_block *sb, struct inode *inode, 
103                               void *h, int force_sync)
104 {
105         struct fsfilt_operations *cache_fsfilt = S2SMI(sb)->sm_cache_fsfilt;
106         struct super_block *csb = S2CSB(sb); 
107         struct inode *cache_inode = NULL;
108         int    rc = -EIO;
109
110         if (inode)
111                 cache_inode = I2CI(inode);
112
113         if (cache_fsfilt == NULL)
114                 RETURN(rc);
115
116         if (!cache_fsfilt->fs_commit)
117                 RETURN(-ENOSYS);
118
119         rc = cache_fsfilt->fs_commit(csb, cache_inode, h, force_sync);
120
121         RETURN(rc);
122 }
123
124 static int fsfilt_smfs_commit_async(struct inode *inode, void *h,
125                                     void **wait_handle)
126 {
127         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
128         struct inode *cache_inode = NULL;
129         int    rc = -EIO;
130
131         cache_inode = I2CI(inode);
132         if (cache_fsfilt == NULL)
133                 RETURN(-EINVAL);
134
135         if (!cache_fsfilt->fs_commit_async)
136                 RETURN(-ENOSYS);
137
138         rc = cache_fsfilt->fs_commit_async(cache_inode, h, wait_handle);
139
140         RETURN(rc);
141 }
142
143 static int fsfilt_smfs_commit_wait(struct inode *inode, void *h)
144 {
145         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
146         struct inode *cache_inode = NULL;
147         int    rc = -EIO;
148
149         cache_inode = I2CI(inode);
150         if (cache_fsfilt == NULL)
151                 RETURN(-EINVAL);
152
153         if (!cache_fsfilt->fs_commit_wait)
154                 RETURN(-ENOSYS);
155
156         rc = cache_fsfilt->fs_commit_wait(cache_inode, h);
157
158         RETURN(rc);
159 }
160
161 static int fsfilt_smfs_setattr(struct dentry *dentry, void *handle,
162                                struct iattr *iattr, int do_trunc)
163 {
164         struct fsfilt_operations *cache_fsfilt = I2FOPS(dentry->d_inode);
165         struct dentry *cache_dentry = NULL;
166         struct inode *cache_inode = NULL;
167         int    rc = -EIO;
168
169         if (!cache_fsfilt)
170                 RETURN(rc);
171
172         cache_inode = I2CI(dentry->d_inode);
173
174         cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry, NULL);
175         if (!cache_dentry)
176                 GOTO(exit, rc = -ENOMEM);
177
178         pre_smfs_inode(dentry->d_inode, cache_inode);
179
180         if (!cache_fsfilt->fs_setattr)
181                 RETURN(-ENOSYS);
182
183         rc = cache_fsfilt->fs_setattr(cache_dentry, handle, iattr, do_trunc);
184
185         post_smfs_inode(dentry->d_inode, cache_inode);
186
187         if (rc == 0) {
188                 struct super_block *sb = dentry->d_inode->i_sb;
189
190                 if (SMFS_DO_REC(S2SMI(sb)) && 
191                     SMFS_DO_INODE_REC(dentry->d_inode)) {
192                         rc = smfs_rec_setattr(dentry->d_inode, dentry, iattr);
193                 }
194         }
195 exit:
196         post_smfs_dentry(cache_dentry);
197         RETURN(rc);
198 }
199
200 static int fsfilt_smfs_iocontrol(struct inode *inode, struct file *file,
201                                  unsigned int cmd, unsigned long arg)
202 {
203         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
204         struct inode *cache_inode = NULL;
205         struct smfs_file_info *sfi = NULL;
206         int    rc = -EIO;
207         ENTRY;
208
209         if (!cache_fsfilt)
210                 RETURN(rc);
211
212         cache_inode = I2CI(inode);
213
214         if (!cache_inode)
215                 RETURN(rc);
216
217         if (file != NULL) {
218                 sfi = F2SMFI(file);
219
220                 if (sfi->magic != SMFS_FILE_MAGIC)
221                         BUG();
222         } else {
223                 sfi = NULL;
224         }
225
226         if (!cache_fsfilt->fs_iocontrol)
227                 RETURN(-ENOSYS);
228
229         if (sfi) {
230                 rc = cache_fsfilt->fs_iocontrol(cache_inode, sfi->c_file, cmd,
231                                                 arg);
232         } else {
233                 rc = cache_fsfilt->fs_iocontrol(cache_inode, NULL, cmd, arg);
234         }
235
236         /* FIXME-UMKA: Should this be in duplicate_inode()? */
237         if (rc == 0 && cmd == EXT3_IOC_SETFLAGS)
238                 inode->i_flags = cache_inode->i_flags;
239
240         post_smfs_inode(inode, cache_inode);
241
242         RETURN(rc);
243 }
244
245 static int fsfilt_smfs_set_md(struct inode *inode, void *handle,
246                               void *lmm, int lmm_size)
247 {
248         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
249         struct inode *cache_inode = NULL;
250         int    rc = -EIO;
251
252         if (!cache_fsfilt)
253                 RETURN(-EINVAL);
254
255         cache_inode = I2CI(inode);
256
257         if (!cache_inode)
258                 RETURN(-ENOENT);
259
260         pre_smfs_inode(inode, cache_inode);
261
262         if (!cache_fsfilt->fs_set_md)
263                 RETURN(-ENOSYS);
264
265         down(&cache_inode->i_sem);
266         rc = cache_fsfilt->fs_set_md(cache_inode, handle, lmm, lmm_size);
267         up(&cache_inode->i_sem);
268
269         post_smfs_inode(inode, cache_inode);
270
271         smfs_rec_md(inode, lmm, lmm_size);
272
273         RETURN(rc);
274 }
275
276 /* Must be called with i_sem held */
277 static int fsfilt_smfs_get_md(struct inode *inode, void *lmm, int lmm_size)
278 {
279         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
280         struct inode *cache_inode = NULL;
281         int    rc = -EIO;
282
283         if (!cache_fsfilt)
284                 RETURN(-EINVAL);
285
286         cache_inode = I2CI(inode);
287
288         if (!cache_inode)
289                 RETURN(-ENOENT);
290
291         pre_smfs_inode(inode, cache_inode);
292
293         if (!cache_fsfilt->fs_get_md)
294                 RETURN(-ENOSYS);
295
296         down(&cache_inode->i_sem);
297         rc = cache_fsfilt->fs_get_md(cache_inode, lmm, lmm_size);
298         up(&cache_inode->i_sem);
299
300         post_smfs_inode(inode, cache_inode);
301
302         RETURN(rc);
303 }
304
305 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
306 static int fsfilt_smfs_send_bio(struct inode *inode, struct bio *bio)
307 #else
308 static int fsfilt_smfs_send_bio(struct inode *inode, struct kiobuf *bio)
309 #endif
310 {
311         struct inode *cache_inode;
312         struct fsfilt_operations *cache_fsfilt;
313
314         cache_fsfilt = I2FOPS(inode);
315         if (!cache_fsfilt)
316                 RETURN(-EINVAL);
317
318         cache_inode = I2CI(inode);
319         if (!cache_inode)
320                 RETURN(-EINVAL);
321
322         if (!cache_fsfilt->fs_send_bio)
323                 RETURN(-ENOSYS);
324
325         return cache_fsfilt->fs_send_bio(cache_inode, bio);
326 }
327
328 static struct page *
329 fsfilt_smfs_getpage(struct inode *inode, long int index)
330 {
331         struct  fsfilt_operations *cache_fsfilt;
332         struct  inode *cache_inode;
333
334         cache_fsfilt = I2FOPS(inode);
335         if (!cache_fsfilt)
336                 RETURN(ERR_PTR(-EINVAL));
337
338         cache_inode = I2CI(inode);
339         if (!cache_inode)
340                 RETURN(ERR_PTR(-EINVAL));
341
342         if (!cache_fsfilt->fs_getpage)
343                 RETURN(ERR_PTR(-ENOSYS));
344 #if CONFIG_SNAPFS
345         if (SMFS_DO_COW(S2SMI(inode->i_sb))) {
346                 struct address_space_operations *aops = 
347                                 cache_inode->i_mapping->a_ops;
348                 if (aops->bmap(cache_inode->i_mapping, index)) {
349                         struct inode *ind_inode = NULL;
350                         struct inode *cache_ind = NULL;
351                         struct page  *page = NULL;
352                         
353                         ind_inode = smfs_cow_get_ind(inode, index);
354                         if (!ind_inode) {
355                                 RETURN(ERR_PTR(-EIO));
356                         }
357                         cache_ind = I2CI(ind_inode);
358                         /*FIXME cow inode should be bottom fs inode */         
359                         page = cache_fsfilt->fs_getpage(cache_ind, index);
360                         iput(ind_inode); 
361                         RETURN(page);
362                 } 
363         }
364 #endif
365         return cache_fsfilt->fs_getpage(cache_inode, index);
366 }
367
368 static ssize_t fsfilt_smfs_readpage(struct file *file, char *buf,
369                                     size_t count, loff_t *off)
370 {
371         struct fsfilt_operations *cache_fsfilt;
372         struct smfs_file_info *sfi;
373         struct inode *cache_inode;
374         loff_t tmp_ppos;
375         loff_t *cache_ppos;
376         ssize_t rc = -EIO;
377
378         ENTRY;
379
380         cache_fsfilt = I2FOPS(file->f_dentry->d_inode);
381         if (!cache_fsfilt)
382                 RETURN(rc);
383
384         cache_inode = I2CI(file->f_dentry->d_inode);
385         if (!cache_inode)
386                 RETURN(rc);
387
388         sfi = F2SMFI(file);
389         if (sfi->magic != SMFS_FILE_MAGIC)
390                 BUG();
391
392         if (off != &(file->f_pos))
393                 cache_ppos = &tmp_ppos;
394         else
395                 cache_ppos = &sfi->c_file->f_pos;
396         *cache_ppos = *off;
397
398         pre_smfs_inode(file->f_dentry->d_inode, cache_inode);
399 #if CONFIG_SNAPFS
400         /*readdir page*/
401         if (smfs_dotsnap_inode(file->f_dentry->d_inode)) {
402                 struct fsfilt_operations *snapops = 
403                                         I2SNAPOPS(file->f_dentry->d_inode);
404                 
405                 LASSERT(S_ISDIR(file->f_dentry->d_inode->i_mode));
406                 
407                 rc = snapops->fs_read_dotsnap_dir_page(sfi->c_file, buf, count, 
408                                                        cache_ppos); 
409                 
410         } else {
411                 if (cache_fsfilt->fs_readpage)
412                         rc = cache_fsfilt->fs_readpage(sfi->c_file, buf, count,
413                                                        cache_ppos);
414         }
415 #else
416         if (cache_fsfilt->fs_readpage)
417                 rc = cache_fsfilt->fs_readpage(sfi->c_file, buf, count,
418                                                cache_ppos);
419
420 #endif
421         *off = *cache_ppos;
422         post_smfs_inode(file->f_dentry->d_inode, cache_inode);
423         duplicate_file(file, sfi->c_file);
424
425         RETURN(rc);
426 }
427
428
429 static int fsfilt_smfs_add_journal_cb(struct obd_device *obd,
430                                       struct super_block *sb, __u64 last_rcvd,
431                                       void *handle, fsfilt_cb_t cb_func,
432                                       void *cb_data)
433 {
434         struct fsfilt_operations *cache_fsfilt = S2SMI(sb)->sm_cache_fsfilt;
435         struct super_block *csb = S2CSB(sb);
436         int rc = -EIO;
437
438         if (!cache_fsfilt)
439                  RETURN(rc);
440         if (cache_fsfilt->fs_add_journal_cb)
441                 rc = cache_fsfilt->fs_add_journal_cb(obd, csb, last_rcvd,
442                                                      handle, cb_func, cb_data);
443         RETURN(rc);
444 }
445
446 static int fsfilt_smfs_statfs(struct super_block *sb, struct obd_statfs *osfs)
447 {
448         struct fsfilt_operations *cache_fsfilt = S2SMI(sb)->sm_cache_fsfilt;
449         struct super_block *csb = S2CSB(sb);
450         int rc = -EIO;
451
452         if (!cache_fsfilt)
453                 RETURN(rc);
454
455         if (!cache_fsfilt->fs_statfs)
456                 RETURN(-ENOSYS);
457
458         rc = cache_fsfilt->fs_statfs(csb, osfs);
459         duplicate_sb(csb, sb);
460
461         RETURN(rc);
462 }
463
464 static int fsfilt_smfs_sync(struct super_block *sb)
465 {
466         struct fsfilt_operations *cache_fsfilt = S2SMI(sb)->sm_cache_fsfilt;
467         struct super_block *csb = S2CSB(sb);
468         int    rc = -EIO;
469
470         if (!cache_fsfilt)
471                 RETURN(-EINVAL);
472
473         if (!cache_fsfilt->fs_sync)
474                 RETURN(-ENOSYS);
475
476         rc = cache_fsfilt->fs_sync(csb);
477
478         RETURN(rc);
479 }
480
481 int fsfilt_smfs_map_inode_pages(struct inode *inode, struct page **page,
482                                 int pages, unsigned long *blocks, int *created,
483                                 int create, struct semaphore *sem)
484 {
485         struct  fsfilt_operations *cache_fsfilt = I2FOPS(inode);
486         struct  inode *cache_inode = NULL;
487         int     rc = -EIO;
488
489         if (!cache_fsfilt)
490                 RETURN(-EINVAL);
491
492         cache_inode = I2CI(inode);
493
494         if (!cache_inode)
495                 RETURN(rc);
496
497         if (!cache_fsfilt->fs_map_inode_pages)
498                 RETURN(-ENOSYS);
499
500         down(&cache_inode->i_sem);
501         rc = cache_fsfilt->fs_map_inode_pages(cache_inode, page, pages, blocks,
502                                               created, create, sem);
503         up(&cache_inode->i_sem);
504
505         RETURN(rc);
506 }
507
508 static int fsfilt_smfs_prep_san_write(struct inode *inode, long *blocks,
509                                       int nblocks, loff_t newsize)
510 {
511         struct  fsfilt_operations *cache_fsfilt = I2FOPS(inode);
512         struct  inode *cache_inode = NULL;
513         int     rc = -EIO;
514
515         if (!cache_fsfilt)
516                 RETURN(-EINVAL);
517
518         cache_inode = I2CI(inode);
519
520         if (!cache_inode)
521                 RETURN(-EINVAL);
522
523         if (!cache_fsfilt->fs_prep_san_write)
524                 RETURN(-ENOSYS);
525
526         down(&cache_inode->i_sem);
527         rc = cache_fsfilt->fs_prep_san_write(cache_inode, blocks, nblocks,
528                                              newsize);
529         up(&cache_inode->i_sem);
530
531         RETURN(rc);
532 }
533
534 static int fsfilt_smfs_read_record(struct file * file, void *buf,
535                                    int size, loff_t *offs)
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;
543
544         ENTRY;
545         cache_fsfilt = I2FOPS(file->f_dentry->d_inode);
546         if (!cache_fsfilt)
547                 RETURN(-EINVAL);
548
549         cache_inode = I2CI(file->f_dentry->d_inode);
550
551         if (!cache_inode)
552                 RETURN(-EINVAL);
553
554         sfi = F2SMFI(file);
555         if (sfi->magic != SMFS_FILE_MAGIC) BUG();
556
557         if (offs != &(file->f_pos))
558                 cache_ppos = &tmp_ppos;
559         else
560                 cache_ppos = &sfi->c_file->f_pos;
561         *cache_ppos = *offs;
562
563         pre_smfs_inode(file->f_dentry->d_inode, cache_inode);
564
565         if (!cache_fsfilt->fs_read_record)
566                 RETURN(-ENOSYS);
567
568         rc = cache_fsfilt->fs_read_record(sfi->c_file, buf, size, cache_ppos);
569
570         *offs = *cache_ppos;
571         post_smfs_inode(file->f_dentry->d_inode, cache_inode);
572         duplicate_file(file, sfi->c_file);
573
574         RETURN(rc);
575 }
576
577 static int fsfilt_smfs_write_record(struct file *file, void *buf, int bufsize,
578                                     loff_t *offs, int force_sync)
579 {
580         struct  fsfilt_operations *cache_fsfilt;
581         struct  inode *cache_inode;
582         struct  smfs_file_info *sfi;
583         loff_t  tmp_ppos;
584         loff_t  *cache_ppos;
585         ssize_t rc = -EIO;
586
587         ENTRY;
588
589         cache_fsfilt = I2FOPS(file->f_dentry->d_inode);
590         if (!cache_fsfilt)
591                 RETURN(-EINVAL);
592
593         cache_inode = I2CI(file->f_dentry->d_inode);
594
595         if (!cache_inode)
596                 RETURN(-EINVAL);
597
598         sfi = F2SMFI(file);
599         if (sfi->magic != SMFS_FILE_MAGIC)
600                 BUG();
601
602         if (offs != &(file->f_pos))
603                 cache_ppos = &tmp_ppos;
604         else
605                 cache_ppos = &sfi->c_file->f_pos;
606         *cache_ppos = *offs;
607
608         pre_smfs_inode(file->f_dentry->d_inode, cache_inode);
609
610         if (!cache_fsfilt->fs_write_record)
611                 RETURN(-ENOSYS);
612
613         rc = cache_fsfilt->fs_write_record(sfi->c_file, buf,
614                                            bufsize, cache_ppos, force_sync);
615         *offs = *cache_ppos;
616         post_smfs_inode(file->f_dentry->d_inode, cache_inode);
617         duplicate_file(file, sfi->c_file);
618
619         RETURN(rc);
620 }
621
622 static int fsfilt_smfs_post_setup(struct obd_device *obd, struct vfsmount *mnt,
623                                   struct dentry *root_dentry)
624 {
625         struct super_block *sb = NULL;
626         int rc = 0;
627
628         if (mnt) {
629                 sb = mnt->mnt_sb;
630                 S2SMI(sb)->smsi_exp = obd->obd_self_export;
631                 smfs_post_setup(sb, mnt);
632                 if (SMFS_DO_REC(S2SMI(sb)))
633                         rc = smfs_start_rec(sb, mnt);
634 #if CONFIG_SNAPFS
635                 if (SMFS_DO_COW(S2SMI(sb))) {
636                        S2SNAPI(sb)->snap_root = root_dentry;  
637                        rc = smfs_start_cow(sb);
638                 }
639 #endif
640                 if (rc)
641                         GOTO(exit, rc);
642                 if (obd)
643                         obd->obd_llog_ctxt[LLOG_REINT_ORIG_CTXT] =
644                                         S2SMI(sb)->smsi_rec_log;
645         }
646 exit:
647         if (rc)
648                 CERROR("can not do post setup in obd %p rc=%d", obd, rc);
649
650         RETURN(rc);
651 }
652
653 static int fsfilt_smfs_post_cleanup(struct obd_device *obd,
654                                     struct vfsmount *mnt)
655 {
656         struct super_block *sb = NULL;
657         int rc = 0;
658         ENTRY;
659         
660         if (mnt) {
661                 sb = mnt->mnt_sb;
662                 if (SMFS_DO_REC(S2SMI(sb)))
663                         rc = smfs_stop_rec(sb);
664 #if CONFIG_SNAPFS
665                 if (SMFS_DO_COW(S2SMI(sb)))
666                         rc = smfs_stop_cow(sb);
667 #endif
668                 smfs_post_cleanup(sb);
669         }
670         RETURN(rc);
671 }
672
673 static int fsfilt_smfs_set_fs_flags(struct inode *inode, int flags)
674 {
675         int rc = 0;
676         ENTRY;
677
678         if (SMFS_DO_REC(S2SMI(inode->i_sb)) && (flags & SM_DO_REC))
679                 SMFS_SET_INODE_REC(inode);
680         if (SMFS_DO_COW(S2SMI(inode->i_sb)) && (flags & SM_DO_COW))
681                 SMFS_SET_INODE_COW(inode);
682         RETURN(rc);
683 }
684
685 static int fsfilt_smfs_clear_fs_flags(struct inode *inode, int flags)
686 {
687         int rc = 0;
688         ENTRY;
689         
690         if (SMFS_DO_REC(S2SMI(inode->i_sb)) && (flags & SM_DO_REC))
691                 SMFS_CLEAN_INODE_REC(inode);
692         if (SMFS_DO_COW(S2SMI(inode->i_sb)) && (flags & SM_DO_COW))
693                 SMFS_CLEAN_INODE_COW(inode);
694         RETURN(rc);
695 }
696
697 static int fsfilt_smfs_get_fs_flags(struct dentry *de)
698 {
699         struct inode *inode = de->d_inode;
700         int flags = 0;
701         ENTRY;
702
703         LASSERT(inode);
704
705         if (SMFS_DO_REC(S2SMI(inode->i_sb)) && SMFS_DO_INODE_REC(inode))
706                 flags |= SM_DO_REC;
707         if (SMFS_DO_COW(S2SMI(inode->i_sb)) && SMFS_DO_INODE_COW(inode))
708                 flags |= SM_DO_COW;
709        
710         RETURN(flags); 
711 }
712 static int fsfilt_smfs_set_ost_flags(struct super_block *sb)
713 {
714         int rc = 0;
715         SET_REC_PACK_TYPE_INDEX(S2SMI(sb)->smsi_flags, PACK_OST);
716         RETURN(rc);
717 }
718
719 static int fsfilt_smfs_set_mds_flags(struct super_block *sb)
720 {
721         int rc = 0;
722         SET_REC_PACK_TYPE_INDEX(S2SMI(sb)->smsi_flags, PACK_MDS);
723         RETURN(rc);
724 }
725
726 static int fsfilt_smfs_get_reint_log_ctxt(struct super_block *sb,
727                                           struct llog_ctxt **ctxt)
728 {
729         struct smfs_super_info *smfs_info = S2SMI(sb);
730         int rc = 0;
731
732         *ctxt = smfs_info->smsi_rec_log;
733         RETURN(rc);
734 }
735
736 static int fsfilt_smfs_setup(struct obd_device *obd, struct super_block *sb)
737 {
738         struct smfs_super_info *smfs_info = S2SMI(sb);
739         struct fsfilt_operations *cache_fsfilt;
740         struct super_block *csb;
741         int rc = 0;
742
743         /* It should be initialized olready by smfs_read_super(). */
744         if (!(cache_fsfilt = smfs_info->sm_cache_fsfilt))
745                     cache_fsfilt = fsfilt_get_ops(smfs_info->smsi_cache_ftype);
746
747         if (!cache_fsfilt)
748                 RETURN(-ENOENT);
749
750         csb = S2CSB(sb);
751         if (cache_fsfilt->fs_setup) 
752                 rc = cache_fsfilt->fs_setup(obd, csb);
753         
754         duplicate_sb(sb, csb);
755         
756         RETURN(rc);
757 }
758
759 static int fsfilt_smfs_set_xattr(struct inode *inode, void *handle, char *name,
760                                  void *buffer, int buffer_size)
761 {
762         struct  fsfilt_operations *cache_fsfilt = I2FOPS(inode);
763         struct  inode *cache_inode = NULL;
764         int     rc = -EIO;
765
766         if (!cache_fsfilt)
767                 RETURN(rc);
768
769         cache_inode = I2CI(inode);
770         if (!cache_inode)
771                 RETURN(rc);
772
773         pre_smfs_inode(inode, cache_inode);
774
775         if (cache_fsfilt->fs_set_xattr)
776                 rc = cache_fsfilt->fs_set_xattr(cache_inode, handle, name,
777                                                 buffer, buffer_size);
778         post_smfs_inode(inode, cache_inode);
779
780         RETURN(rc);
781 }
782
783 static int fsfilt_smfs_get_xattr(struct inode *inode, char *name,
784                                  void *buffer, int buffer_size)
785 {
786         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
787         struct inode *cache_inode = NULL;
788         int    rc = -EIO;
789
790         if (!cache_fsfilt)
791                 RETURN(rc);
792
793         cache_inode = I2CI(inode);
794         if (!cache_inode)
795                 RETURN(rc);
796
797         pre_smfs_inode(inode, cache_inode);
798
799         if (cache_fsfilt->fs_get_xattr)
800                 rc = cache_fsfilt->fs_get_xattr(cache_inode, name,
801                                                 buffer, buffer_size);
802         post_smfs_inode(inode, cache_inode);
803
804         RETURN(rc);
805 }
806
807 static int fsfilt_smfs_insert_extents_ea(struct inode *inode,
808                                          unsigned long from, unsigned long num)
809 {
810         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
811         struct inode *cache_inode = NULL;
812         int    rc = -EIO;
813
814         if (!cache_fsfilt)
815                 RETURN(rc);
816
817         cache_inode = I2CI(inode);
818         if (!cache_inode)
819                 RETURN(rc);
820
821         pre_smfs_inode(inode, cache_inode);
822
823         if (cache_fsfilt->fs_insert_extents_ea)
824                 rc = cache_fsfilt->fs_insert_extents_ea(cache_inode, from, num);
825
826         post_smfs_inode(inode, cache_inode);
827         return rc;
828 }
829
830 static int fsfilt_smfs_remove_extents_ea(struct inode *inode,
831                                          unsigned long from, unsigned long num)
832 {
833         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
834         struct inode *cache_inode = NULL;
835         int    rc = -EIO;
836
837         if (!cache_fsfilt)
838                 RETURN(rc);
839
840         cache_inode = I2CI(inode);
841         if (!cache_inode)
842                 RETURN(rc);
843
844         pre_smfs_inode(inode, cache_inode);
845
846         if (cache_fsfilt->fs_remove_extents_ea)
847                 rc = cache_fsfilt->fs_remove_extents_ea(cache_inode, from, num);
848
849         post_smfs_inode(inode, cache_inode);
850         return rc;
851 }
852
853 static int fsfilt_smfs_init_extents_ea(struct inode *inode)
854 {
855         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
856         struct inode *cache_inode = NULL;
857         int    rc = -EIO;
858
859         if (!cache_fsfilt)
860                 RETURN(rc);
861
862         cache_inode = I2CI(inode);
863         if (!cache_inode)
864                 RETURN(rc);
865
866         pre_smfs_inode(inode, cache_inode);
867
868         if (cache_fsfilt->fs_init_extents_ea)
869                 rc = cache_fsfilt->fs_init_extents_ea(cache_inode);
870
871         post_smfs_inode(inode, cache_inode);
872         return rc;
873 }
874
875 static int fsfilt_smfs_free_extents(struct super_block *sb, ino_t ino,
876                                     char *pbuf, int size)
877 {
878         OBD_FREE(pbuf, size * (sizeof(struct ldlm_extent)));
879         return 0;
880 }
881
882 static int fsfilt_smfs_write_extents(struct dentry *dentry,
883                                      unsigned long from, unsigned long num)
884 {
885         int rc = 0;
886
887         if (SMFS_DO_REC(S2SMI(dentry->d_inode->i_sb)))
888                 rc = smfs_write_extents(dentry->d_inode, dentry, from, num);
889
890         return rc;
891 }
892
893 static int fsfilt_smfs_precreate_rec(struct dentry *dentry, int *count, 
894                                      struct obdo *oa)
895 {
896         int rc = 0;
897
898         if (SMFS_DO_REC(S2SMI(dentry->d_inode->i_sb)))
899                 rc = smfs_rec_precreate(dentry, count, oa);
900
901         return rc;
902 }
903
904 static int fsfilt_smfs_get_ino_write_extents(struct super_block *sb, ino_t ino,
905                                              char **pbuf, int *size)
906 {
907         struct fs_extent *fs_extents;
908         struct ldlm_extent *extents = NULL;
909         struct inode *inode;
910         struct inode *cache_inode;
911         struct fsfilt_operations *cache_fsfilt = NULL;
912         struct lvfs_run_ctxt saved;
913         int    rc = 0, fs_ex_size, ex_num, flags;
914         char   *buf = NULL, *ex_buf = NULL;
915
916         push_ctxt(&saved, S2SMI(sb)->smsi_ctxt, NULL);
917
918         inode = iget(sb, ino);
919
920         if (!inode || is_bad_inode(inode)) {
921                 CWARN("Can not get inode %lu ino\n", ino);
922                 GOTO(out, rc = 0);
923         }
924         cache_inode = I2CI(inode);
925         cache_fsfilt = I2FOPS(inode);
926
927         rc = cache_fsfilt->fs_get_xattr(cache_inode, REINT_EXTENTS_FLAGS,
928                                         &flags, sizeof(int));
929         if (!(flags & SMFS_OVER_WRITE) && !(flags & SMFS_DIRTY_WRITE)) {
930                 GOTO(out, rc = 0);
931         } else if (flags & SMFS_OVER_WRITE) {
932                 *size = 1;
933                 OBD_ALLOC(ex_buf, sizeof(struct ldlm_extent));
934                 if (!ex_buf)
935                         GOTO(out, rc=-ENOMEM);
936                 extents = (struct ldlm_extent*)(ex_buf);
937                 extents->start = 0;
938                 extents->end = 0xffffffff;
939         }
940         if (rc < 0)
941                 GOTO(out, rc);
942         rc = cache_fsfilt->fs_get_write_extents_num(cache_inode, &fs_ex_size);
943         if (rc)
944                 GOTO(out, rc);
945         OBD_ALLOC(buf, fs_ex_size);
946         if (!buf)
947                 GOTO(out, rc=-ENOMEM);
948
949         rc = cache_fsfilt->fs_get_inode_write_extents(cache_inode, &buf,
950                                                       &fs_ex_size);
951         if (rc < 0)
952                 GOTO(out, rc);
953         rc = 0;
954         ex_num = fs_ex_size / sizeof(struct fs_extent);
955         *size =  ex_num;
956         OBD_ALLOC(ex_buf, ex_num* sizeof(struct ldlm_extent));
957         if (!ex_buf)
958                 GOTO(out, rc=-ENOMEM);
959
960         fs_extents = (struct fs_extent*)(buf);
961         extents = (struct ldlm_extent*)(ex_buf);
962         while (ex_num > 0) {
963                 int blk_size = I2CI(inode)->i_blksize;
964
965                 extents->start = fs_extents->e_block * blk_size;
966                 extents->end = extents->start + fs_extents->e_num * blk_size;
967                 fs_extents++;
968                 extents++;
969                 ex_num--;
970         }
971         *pbuf = ex_buf;
972 out:
973         iput(inode);
974         if (buf)
975                 OBD_FREE(buf, fs_ex_size);
976         if (rc && extents)
977                 OBD_FREE(ex_buf, (*size) * (sizeof(struct ldlm_extent)));
978         pop_ctxt(&saved, S2SMI(sb)->smsi_ctxt, NULL);
979         return rc;
980 }
981
982 static int fsfilt_smfs_set_snap_item(struct super_block *sb, char *name)
983 {
984         int rc = 0;
985
986         ENTRY;
987 #if CONFIG_SNAPFS
988         rc = smfs_add_snap_item(sb, name);
989 #endif
990         RETURN(rc);        
991 }
992 static int fsfilt_smfs_do_write_cow(struct dentry *de, void *extents,
993                                     int num_extents)
994 {
995         int rc = 0;
996 #if CONFIG_SNAPFS
997         struct write_extents *w_ext = (struct write_extents *)extents;
998         int i = 0;
999         ENTRY;
1000         for (i = 0; i < num_extents; i++) {
1001                size_t count = w_ext->w_count;
1002                loff_t off = w_ext->w_pos;
1003                rc = smfs_cow_write(de->d_inode, de, &count, &off);
1004                if (rc)
1005                         RETURN(rc);  
1006                w_ext ++;
1007         }
1008 #endif
1009         RETURN(rc);
1010 }
1011 static struct fsfilt_operations fsfilt_smfs_ops = {
1012         .fs_type                = "smfs",
1013         .fs_owner               = THIS_MODULE,
1014         .fs_start               = fsfilt_smfs_start,
1015         .fs_brw_start           = fsfilt_smfs_brw_start,
1016         .fs_commit              = fsfilt_smfs_commit,
1017         .fs_commit_async        = fsfilt_smfs_commit_async,
1018         .fs_commit_wait         = fsfilt_smfs_commit_wait,
1019         .fs_setattr             = fsfilt_smfs_setattr,
1020         .fs_iocontrol           = fsfilt_smfs_iocontrol,
1021         .fs_set_md              = fsfilt_smfs_set_md,
1022         .fs_get_md              = fsfilt_smfs_get_md,
1023         .fs_readpage            = fsfilt_smfs_readpage,
1024         .fs_getpage             = fsfilt_smfs_getpage,
1025         .fs_add_journal_cb      = fsfilt_smfs_add_journal_cb,
1026         .fs_statfs              = fsfilt_smfs_statfs,
1027         .fs_sync                = fsfilt_smfs_sync,
1028         .fs_map_inode_pages     = fsfilt_smfs_map_inode_pages,
1029         .fs_prep_san_write      = fsfilt_smfs_prep_san_write,
1030         .fs_write_record        = fsfilt_smfs_write_record,
1031         .fs_read_record         = fsfilt_smfs_read_record,
1032         .fs_setup               = fsfilt_smfs_setup,
1033         .fs_post_setup          = fsfilt_smfs_post_setup,
1034         .fs_post_cleanup        = fsfilt_smfs_post_cleanup,
1035         .fs_set_fs_flags       = fsfilt_smfs_set_fs_flags,
1036         .fs_clear_fs_flags     = fsfilt_smfs_clear_fs_flags,
1037         .fs_get_fs_flags       = fsfilt_smfs_get_fs_flags,
1038         .fs_set_ost_flags       = fsfilt_smfs_set_ost_flags,
1039         .fs_set_mds_flags       = fsfilt_smfs_set_mds_flags,
1040         .fs_precreate_rec       = fsfilt_smfs_precreate_rec,
1041         .fs_get_reint_log_ctxt  = fsfilt_smfs_get_reint_log_ctxt,
1042         .fs_send_bio            = fsfilt_smfs_send_bio,
1043         .fs_set_xattr           = fsfilt_smfs_set_xattr,
1044         .fs_get_xattr           = fsfilt_smfs_get_xattr,
1045         .fs_init_extents_ea     = fsfilt_smfs_init_extents_ea,
1046         .fs_insert_extents_ea   = fsfilt_smfs_insert_extents_ea,
1047         .fs_remove_extents_ea   = fsfilt_smfs_remove_extents_ea,
1048         .fs_get_ino_write_extents = fsfilt_smfs_get_ino_write_extents,
1049         .fs_free_write_extents  = fsfilt_smfs_free_extents,
1050         .fs_write_extents       = fsfilt_smfs_write_extents,
1051         .fs_set_snap_item       = fsfilt_smfs_set_snap_item,
1052         .fs_do_write_cow        = fsfilt_smfs_do_write_cow,
1053         /* FIXME-UMKA: probably fsfilt_smfs_get_op_len() should be
1054          * put here too. */
1055 };
1056
1057 static int __init fsfilt_smfs_init(void)
1058 {
1059         int rc;
1060
1061         rc = fsfilt_register_ops(&fsfilt_smfs_ops);
1062         return rc;
1063 }
1064
1065 static void __exit fsfilt_smfs_exit(void)
1066 {
1067         fsfilt_unregister_ops(&fsfilt_smfs_ops);
1068 }
1069
1070 module_init(fsfilt_smfs_init);
1071 module_exit(fsfilt_smfs_exit);
1072
1073 MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
1074 MODULE_DESCRIPTION("Lustre SMFS Filesystem Helper v0.1");
1075 MODULE_LICENSE("GPL");