Whamcloud - gitweb
landing smfs.
[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) 2002, 2003 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
41 static void *fsfilt_smfs_start(struct inode *inode, int op, 
42                                void *desc_private, int logs)
43 {
44         void *handle;
45         struct inode *cache_inode = I2CI(inode);
46         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
47
48         if (cache_fsfilt == NULL)
49                 return NULL;
50
51         if (!cache_fsfilt->fs_start)
52                 return ERR_PTR(-ENOSYS);
53                 
54         handle = cache_fsfilt->fs_start(cache_inode, op, 
55                                         desc_private, logs);
56         return handle;
57 }
58
59 static void *fsfilt_smfs_brw_start(int objcount, struct fsfilt_objinfo *fso,
60                                    int niocount, struct niobuf_local *nb,
61                                    void *desc_private, int logs)
62 {
63         struct fsfilt_operations *cache_fsfilt;
64         struct dentry *cache_dentry = NULL;
65         struct inode *cache_inode = NULL;
66         struct fsfilt_objinfo cache_fso;
67         void   *rc = NULL;
68         
69         ENTRY; 
70         cache_fsfilt = I2FOPS(fso->fso_dentry->d_inode);
71         if (cache_fsfilt == NULL) 
72                 return NULL;
73
74         cache_inode = I2CI(fso->fso_dentry->d_inode);
75         cache_dentry = pre_smfs_dentry(NULL, cache_inode, fso->fso_dentry);     
76     
77         if (!cache_dentry)
78                 GOTO(exit, rc = ERR_PTR(-ENOMEM));
79     
80         cache_fso.fso_dentry = cache_dentry; 
81         cache_fso.fso_bufcnt = fso->fso_bufcnt;
82  
83         if (!cache_fsfilt->fs_brw_start)
84                 return ERR_PTR(-ENOSYS);
85                 
86         rc = (cache_fsfilt->fs_brw_start(objcount, &cache_fso, 
87                                          niocount, nb, desc_private,
88                                          logs));
89 exit:
90         post_smfs_dentry(cache_dentry); 
91         return rc; 
92 }
93
94 static int fsfilt_smfs_commit(struct inode *inode, void *h, 
95                               int force_sync)
96 {
97         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
98         struct inode *cache_inode = NULL;
99         int    rc = -EIO;      
100  
101         cache_inode = I2CI(inode);
102  
103         if (cache_fsfilt == NULL)
104                 RETURN(rc);
105        
106         if (!cache_fsfilt->fs_commit) 
107                 RETURN(-ENOSYS);
108         
109         rc = cache_fsfilt->fs_commit(cache_inode, h, force_sync);
110         
111         RETURN(rc);
112 }
113
114 static int fsfilt_smfs_commit_async(struct inode *inode, void *h,
115                                     void **wait_handle)
116 {
117         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
118         struct inode *cache_inode = NULL;
119         int    rc = -EIO;      
120  
121         cache_inode = I2CI(inode);
122         if (cache_fsfilt == NULL)
123                 RETURN(-EINVAL);
124        
125         if (!cache_fsfilt->fs_commit_async)
126                 RETURN(-ENOSYS);
127                 
128         rc = cache_fsfilt->fs_commit_async(cache_inode, h, wait_handle);
129         
130         RETURN(rc);
131 }
132
133 static int fsfilt_smfs_commit_wait(struct inode *inode, void *h)
134 {
135         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
136         struct inode *cache_inode = NULL;
137         int    rc = -EIO;      
138  
139         cache_inode = I2CI(inode);
140         if (cache_fsfilt == NULL)
141                 RETURN(-EINVAL);
142        
143         if (!cache_fsfilt->fs_commit_wait) 
144                 RETURN(-ENOSYS);
145         
146         rc = cache_fsfilt->fs_commit_wait(cache_inode, h);
147         
148         RETURN(rc);
149 }
150
151 static int fsfilt_smfs_setattr(struct dentry *dentry, void *handle,
152                                struct iattr *iattr, int do_trunc)
153 {
154         struct fsfilt_operations *cache_fsfilt = I2FOPS(dentry->d_inode);
155         struct dentry *cache_dentry = NULL;
156         struct inode *cache_inode = NULL;
157         int    rc = -EIO;
158  
159         if (!cache_fsfilt) 
160                 RETURN(rc);
161  
162         cache_inode = I2CI(dentry->d_inode); 
163        
164         cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);      
165         if (!cache_dentry)
166                 GOTO(exit, rc = -ENOMEM);
167   
168         pre_smfs_inode(dentry->d_inode, cache_inode);
169         
170         if (!cache_fsfilt->fs_setattr)
171                 RETURN(-ENOSYS);
172                 
173         rc = cache_fsfilt->fs_setattr(cache_dentry, handle, 
174                                       iattr, do_trunc);
175         
176         post_smfs_inode(dentry->d_inode, cache_inode);
177        
178 exit:
179         post_smfs_dentry(cache_dentry);
180         RETURN(rc);                    
181 }
182
183 static int fsfilt_smfs_iocontrol(struct inode *inode, struct file *file,
184                                  unsigned int cmd, unsigned long arg)
185 {
186         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
187         struct inode *cache_inode = NULL;
188         struct smfs_file_info *sfi = NULL;
189         int    rc = -EIO;                                                                                                                                                                                                     
190         ENTRY;
191                                                                                                                                                                                                      
192         if (!cache_fsfilt) 
193                 RETURN(rc);
194         
195         cache_inode = I2CI(inode);
196        
197         if (!cache_inode)
198                 RETURN(rc);
199
200         if (file != NULL) {
201                 sfi = F2SMFI(file);
202                 
203                 if (sfi->magic != SMFS_FILE_MAGIC) 
204                         BUG();
205         } else {
206                 sfi = NULL;
207         }
208         
209         if (!cache_fsfilt->fs_iocontrol)
210                 RETURN(-ENOSYS);
211     
212         if (sfi) {
213                 rc = cache_fsfilt->fs_iocontrol(cache_inode,
214                                                 sfi->c_file, 
215                                                 cmd, arg);
216         } else {
217                 rc = cache_fsfilt->fs_iocontrol(cache_inode,
218                                                 NULL, cmd, arg);
219         }
220         
221         /* FIXME-UMKA: Should this be in duplicate_inode()? */
222         if (rc == 0 && cmd == EXT3_IOC_SETFLAGS)
223                 inode->i_flags = cache_inode->i_flags;
224                 
225         post_smfs_inode(inode, cache_inode); 
226
227         RETURN(rc);
228 }
229
230 static int fsfilt_smfs_set_md(struct inode *inode, void *handle,
231                               void *lmm, int lmm_size)
232 {
233         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
234         struct inode *cache_inode = NULL;
235         int    rc = -EIO;
236   
237         if (!cache_fsfilt) 
238                 RETURN(-EINVAL);
239         
240         cache_inode = I2CI(inode);
241        
242         if (!cache_inode)
243                 RETURN(-ENOENT);
244        
245         pre_smfs_inode(inode, cache_inode); 
246         
247         if (!cache_fsfilt->fs_set_md)
248                 RETURN(-ENOSYS);
249                 
250         down(&cache_inode->i_sem);
251                 
252         rc = cache_fsfilt->fs_set_md(cache_inode, handle,
253                                      lmm, lmm_size); 
254                                      
255         up(&cache_inode->i_sem);
256         
257         post_smfs_inode(inode, cache_inode); 
258         
259         RETURN(rc); 
260 }
261
262 /* Must be called with i_sem held */
263 static int fsfilt_smfs_get_md(struct inode *inode, void *lmm, int lmm_size)
264 {
265         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
266         struct inode *cache_inode = NULL;
267         int    rc = -EIO;
268   
269         if (!cache_fsfilt) 
270                 RETURN(-EINVAL);
271         
272         cache_inode = I2CI(inode);
273        
274         if (!cache_inode)
275                 RETURN(-ENOENT);
276        
277         pre_smfs_inode(inode, cache_inode); 
278         
279         if (!cache_fsfilt->fs_get_md)
280                 RETURN(-ENOSYS);
281                 
282         down(&cache_inode->i_sem);
283         
284         rc = cache_fsfilt->fs_get_md(cache_inode, lmm, 
285                                      lmm_size); 
286                                      
287         up(&cache_inode->i_sem);
288         
289         post_smfs_inode(inode, cache_inode); 
290        
291         RETURN(rc); 
292 }
293
294 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
295 static int fsfilt_smfs_send_bio(struct inode *inode, 
296                                 struct bio *bio)
297 #else
298 static int fsfilt_smfs_send_bio(struct inode *inode, 
299                                 struct kiobuf *bio)
300 #endif
301 {
302         struct inode *cache_inode;
303         struct fsfilt_operations *cache_fsfilt;
304         
305         cache_fsfilt = I2FOPS(inode);
306         if (!cache_fsfilt) 
307                 RETURN(-EINVAL);
308         
309         cache_inode = I2CI(inode);
310         if (!cache_inode)
311                 RETURN(-EINVAL);
312         
313         if (!cache_fsfilt->fs_send_bio)
314                 RETURN(-ENOSYS);
315                 
316         return cache_fsfilt->fs_send_bio(cache_inode, bio);
317 }
318
319 static struct page *
320 fsfilt_smfs_getpage(struct inode *inode, long int index)
321 {
322         struct  fsfilt_operations *cache_fsfilt;
323         struct  inode *cache_inode;
324
325         cache_fsfilt = I2FOPS(inode);
326         if (!cache_fsfilt) 
327                 RETURN(ERR_PTR(-EINVAL));
328         
329         cache_inode = I2CI(inode);
330         if (!cache_inode)
331                 RETURN(ERR_PTR(-EINVAL));
332         
333         if (!cache_fsfilt->fs_getpage)
334                 RETURN(ERR_PTR(-ENOSYS));
335         
336         return cache_fsfilt->fs_getpage(cache_inode, index);
337 }
338
339 static ssize_t fsfilt_smfs_readpage(struct file *file, char *buf,
340                                     size_t count, loff_t *off)
341 {
342         struct fsfilt_operations *cache_fsfilt;
343         struct smfs_file_info *sfi; 
344         struct inode *cache_inode;
345         loff_t tmp_ppos;
346         loff_t *cache_ppos;
347         ssize_t rc = -EIO;
348
349         ENTRY;
350
351         cache_fsfilt = I2FOPS(file->f_dentry->d_inode);
352         if (!cache_fsfilt) 
353                 RETURN(rc);
354         
355         cache_inode = I2CI(file->f_dentry->d_inode);
356         if (!cache_inode)
357                 RETURN(rc);
358
359         sfi = F2SMFI(file);
360         if (sfi->magic != SMFS_FILE_MAGIC)
361                 BUG();
362         
363         if (off != &(file->f_pos)) {
364                 cache_ppos = &tmp_ppos;
365         } else {
366                 cache_ppos = &sfi->c_file->f_pos;
367         }
368         *cache_ppos = *off;
369         
370         pre_smfs_inode(file->f_dentry->d_inode, cache_inode);
371         
372         if (cache_fsfilt->fs_readpage) 
373                 rc = cache_fsfilt->fs_readpage(sfi->c_file, buf,
374                                                count, cache_ppos);
375         
376         *off = *cache_ppos;
377         post_smfs_inode(file->f_dentry->d_inode, cache_inode);
378         duplicate_file(file, sfi->c_file);
379         
380         RETURN(rc);
381 }
382
383 static int fsfilt_smfs_add_journal_cb(struct obd_device *obd,
384                                       struct super_block *sb,
385                                       __u64 last_rcvd, void *handle,
386                                       fsfilt_cb_t cb_func,
387                                       void *cb_data)
388 {
389         struct fsfilt_operations *cache_fsfilt = S2SMI(sb)->sm_cache_fsfilt;
390         struct super_block *csb = S2CSB(sb);
391         int rc = -EIO;
392
393         if (!cache_fsfilt) 
394                  RETURN(rc);
395         if (cache_fsfilt->fs_add_journal_cb)
396                 rc = cache_fsfilt->fs_add_journal_cb(obd, csb, last_rcvd,
397                                                      handle, cb_func, cb_data);
398         RETURN(rc);
399 }
400
401 static int fsfilt_smfs_statfs(struct super_block *sb, struct obd_statfs *osfs)
402 {
403         struct fsfilt_operations *cache_fsfilt = S2SMI(sb)->sm_cache_fsfilt;
404         struct super_block *csb = S2CSB(sb);
405         int rc = -EIO;
406
407         if (!cache_fsfilt)
408                 RETURN(rc);
409         
410         if (!cache_fsfilt->fs_statfs)
411                 RETURN(-ENOSYS);
412                 
413         rc = cache_fsfilt->fs_statfs(csb, osfs);
414         duplicate_sb(csb, sb);
415         
416         RETURN(rc);
417 }
418
419 static int fsfilt_smfs_sync(struct super_block *sb)
420 {
421         struct fsfilt_operations *cache_fsfilt = S2SMI(sb)->sm_cache_fsfilt;
422         struct super_block *csb = S2CSB(sb);
423         int    rc = -EIO;
424  
425         if(!cache_fsfilt)
426                 RETURN(-EINVAL);
427         
428         if (!cache_fsfilt->fs_sync)
429                 RETURN(-ENOSYS);
430         
431         rc = cache_fsfilt->fs_sync(csb);
432         
433         RETURN(rc); 
434 }
435
436 int fsfilt_smfs_map_inode_page(struct inode *inode, struct page *page,
437                                unsigned long *blocks, int *created, int create)
438 {
439         struct  fsfilt_operations *cache_fsfilt = I2FOPS(inode);
440         struct  inode *cache_inode = NULL;
441         int     rc = -EIO;
442          
443         if (!cache_fsfilt)
444                 RETURN(-EINVAL);
445         
446         cache_inode = I2CI(inode);
447        
448         if (!cache_inode)
449                 RETURN(rc);
450
451         if (!cache_fsfilt->fs_map_inode_page) 
452                 RETURN(-ENOSYS);
453         
454         down(&cache_inode->i_sem);
455         rc = cache_fsfilt->fs_map_inode_page(cache_inode, page, 
456                                              blocks, created, create);
457         up(&cache_inode->i_sem);
458         
459         RETURN(rc);
460 }
461
462 static int fsfilt_smfs_prep_san_write(struct inode *inode, long *blocks,
463                                       int nblocks, loff_t newsize)
464 {
465         struct  fsfilt_operations *cache_fsfilt = I2FOPS(inode);
466         struct  inode *cache_inode = NULL;
467         int     rc = -EIO;
468          
469         if (!cache_fsfilt)
470                 RETURN(-EINVAL);
471         
472         cache_inode = I2CI(inode);
473        
474         if (!cache_inode)
475                 RETURN(-EINVAL);
476
477         if (!cache_fsfilt->fs_prep_san_write)
478                 RETURN(-ENOSYS);
479         
480         down(&cache_inode->i_sem);
481         rc = cache_fsfilt->fs_prep_san_write(cache_inode, blocks, 
482                                              nblocks, newsize);
483         up(&cache_inode->i_sem);
484         
485         RETURN(rc);
486 }
487
488 static int fsfilt_smfs_read_record(struct file * file, void *buf,
489                                    int size, loff_t *offs)
490 {
491         struct  fsfilt_operations *cache_fsfilt;
492         struct  inode *cache_inode;
493         struct  smfs_file_info *sfi; 
494         loff_t  tmp_ppos;
495         loff_t  *cache_ppos;
496         ssize_t rc;
497         
498         ENTRY;
499         cache_fsfilt = I2FOPS(file->f_dentry->d_inode); 
500         if (!cache_fsfilt) 
501                 RETURN(-EINVAL);
502         
503         cache_inode = I2CI(file->f_dentry->d_inode);
504         
505         if (!cache_inode)
506                 RETURN(-EINVAL);
507
508         sfi = F2SMFI(file);
509         if (sfi->magic != SMFS_FILE_MAGIC) BUG();
510         
511         if (offs != &(file->f_pos)) {
512                 cache_ppos = &tmp_ppos;
513         } else {
514                 cache_ppos = &sfi->c_file->f_pos;
515         }
516         *cache_ppos = *offs;
517
518         pre_smfs_inode(file->f_dentry->d_inode, cache_inode);
519
520         if (!cache_fsfilt->fs_read_record)
521                 RETURN(-ENOSYS);
522                 
523         rc = cache_fsfilt->fs_read_record(sfi->c_file, buf, 
524                                           size, cache_ppos);
525         
526         *offs = *cache_ppos;
527         post_smfs_inode(file->f_dentry->d_inode, cache_inode);
528         duplicate_file(file, sfi->c_file); 
529         
530         RETURN(rc);
531 }
532
533 static int fsfilt_smfs_write_record(struct file *file, void *buf, int bufsize,
534                                     loff_t *offs, int force_sync)
535 {
536         struct  fsfilt_operations *cache_fsfilt;
537         struct  inode *cache_inode;
538         struct  smfs_file_info *sfi; 
539         loff_t  tmp_ppos;
540         loff_t  *cache_ppos;
541         ssize_t rc = -EIO;
542
543         ENTRY;
544
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         }
562         *cache_ppos = *offs;
563        
564         pre_smfs_inode(file->f_dentry->d_inode, cache_inode);
565         
566         if (!cache_fsfilt->fs_write_record)
567                 RETURN(-ENOSYS);
568         
569         rc = cache_fsfilt->fs_write_record(sfi->c_file, buf, 
570                                            bufsize, cache_ppos, force_sync);
571         *offs = *cache_ppos; 
572         post_smfs_inode(file->f_dentry->d_inode, cache_inode);
573         duplicate_file(file, sfi->c_file); 
574         
575         RETURN(rc);
576 }
577
578 static int fsfilt_smfs_setup(struct super_block *sb)
579 {
580         struct smfs_super_info *smfs_info = S2SMI(sb);
581         struct fsfilt_operations *cache_fsfilt;
582         struct super_block *csb;
583         int rc = 0;
584
585         /* It should be initialized olready by smfs_read_super(). */
586         if (!(cache_fsfilt = smfs_info->sm_cache_fsfilt))
587                 cache_fsfilt = fsfilt_get_ops(smfs_info->cache_fs_type);
588
589         if (!cache_fsfilt)
590                 RETURN(-ENOENT);
591         
592         csb = S2CSB(sb);
593
594         if (cache_fsfilt->fs_setup) 
595                 rc = cache_fsfilt->fs_setup(csb);
596         
597         RETURN(rc);
598 }
599
600 static int fsfilt_smfs_set_xattr(struct inode *inode, void *handle,
601                                  char *name,  void *buffer, 
602                                  int buffer_size)
603 {
604         struct  fsfilt_operations *cache_fsfilt = I2FOPS(inode);
605         struct  inode *cache_inode = NULL;
606         int     rc = -EIO;
607          
608         if (!cache_fsfilt)
609                 RETURN(rc);
610         
611         cache_inode = I2CI(inode);
612         if (!cache_inode)
613                 RETURN(rc);
614         
615         pre_smfs_inode(inode, cache_inode); 
616        
617         if (cache_fsfilt->fs_set_xattr) 
618                 rc = cache_fsfilt->fs_set_xattr(cache_inode, handle, name, 
619                                                 buffer, buffer_size);
620         post_smfs_inode(inode, cache_inode); 
621         
622         RETURN(rc);
623 }
624
625 static int fsfilt_smfs_get_xattr(struct inode *inode, char *name,
626                                  void *buffer, int buffer_size)
627 {
628         struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
629         struct inode *cache_inode = NULL;
630         int    rc = -EIO;
631
632          if (!cache_fsfilt)
633                 RETURN(rc);
634         
635         cache_inode = I2CI(inode);
636         if (!cache_inode)
637                 RETURN(rc);
638         
639         pre_smfs_inode(inode, cache_inode); 
640        
641         if (cache_fsfilt->fs_get_xattr) 
642                 rc = cache_fsfilt->fs_get_xattr(cache_inode, name, 
643                                                 buffer, buffer_size);
644         post_smfs_inode(inode, cache_inode); 
645         
646         RETURN(rc);
647 }
648
649 static struct fsfilt_operations fsfilt_smfs_ops = {
650         .fs_type                = "smfs",
651         .fs_owner               = THIS_MODULE,
652         .fs_start               = fsfilt_smfs_start,
653         .fs_brw_start           = fsfilt_smfs_brw_start,
654         .fs_commit              = fsfilt_smfs_commit,
655         .fs_commit_async        = fsfilt_smfs_commit_async,
656         .fs_commit_wait         = fsfilt_smfs_commit_wait,
657         .fs_setattr             = fsfilt_smfs_setattr,
658         .fs_iocontrol           = fsfilt_smfs_iocontrol,
659         .fs_set_md              = fsfilt_smfs_set_md,
660         .fs_get_md              = fsfilt_smfs_get_md,
661         .fs_readpage            = fsfilt_smfs_readpage,
662         .fs_getpage             = fsfilt_smfs_getpage,
663         .fs_add_journal_cb      = fsfilt_smfs_add_journal_cb,
664         .fs_statfs              = fsfilt_smfs_statfs,
665         .fs_sync                = fsfilt_smfs_sync,
666         .fs_map_inode_page      = fsfilt_smfs_map_inode_page,
667         .fs_prep_san_write      = fsfilt_smfs_prep_san_write,
668         .fs_write_record        = fsfilt_smfs_write_record,
669         .fs_read_record         = fsfilt_smfs_read_record,
670         .fs_setup               = fsfilt_smfs_setup,
671         .fs_send_bio            = fsfilt_smfs_send_bio,
672         .fs_set_xattr           = fsfilt_smfs_set_xattr,
673         .fs_get_xattr           = fsfilt_smfs_get_xattr,
674         
675         /* FIXME-UMKA: probably fsfilt_smfs_get_op_len() should be put here
676          * too. */
677 };
678
679 static int __init fsfilt_smfs_init(void)
680 {
681         int rc;
682         
683         rc = fsfilt_register_ops(&fsfilt_smfs_ops);
684         return rc;
685 }
686
687 static void __exit fsfilt_smfs_exit(void)
688 {
689         fsfilt_unregister_ops(&fsfilt_smfs_ops);
690 }
691
692 module_init(fsfilt_smfs_init);
693 module_exit(fsfilt_smfs_exit);
694
695 MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
696 MODULE_DESCRIPTION("Lustre SMFS Filesystem Helper v0.1");
697 MODULE_LICENSE("GPL");