Whamcloud - gitweb
land v0.9.1 on HEAD, in preparation for a 1.0.x branch
[fs/lustre-release.git] / lustre / lvfs / fsfilt.c
1 #ifndef EXPORT_SYMTAB
2 # define EXPORT_SYMTAB
3 #endif
4 #define DEBUG_SUBSYSTEM S_FILTER
5
6 #include <linux/fs.h>
7 #include <linux/jbd.h>
8 #include <linux/module.h>
9 #include <linux/kmod.h>
10 #include <linux/slab.h>
11 #include <linux/kp30.h>
12 #include <linux/lustre_fsfilt.h>
13
14 LIST_HEAD(fsfilt_types);
15
16 static struct fsfilt_operations *fsfilt_search_type(const char *type)
17 {
18         struct fsfilt_operations *found;
19         struct list_head *p;
20
21         list_for_each(p, &fsfilt_types) {
22                 found = list_entry(p, struct fsfilt_operations, fs_list);
23                 if (!strcmp(found->fs_type, type)) {
24                         return found;
25                 }
26         }
27         return NULL;
28 }
29
30 int fsfilt_register_ops(struct fsfilt_operations *fs_ops)
31 {
32         struct fsfilt_operations *found;
33
34         /* lock fsfilt_types list */
35         if ((found = fsfilt_search_type(fs_ops->fs_type))) {
36                 if (found != fs_ops) {
37                         CERROR("different operations for type %s\n",
38                                fs_ops->fs_type);
39                         /* unlock fsfilt_types list */
40                         RETURN(-EEXIST);
41                 }
42         } else {
43                 PORTAL_MODULE_USE;
44                 list_add(&fs_ops->fs_list, &fsfilt_types);
45         }
46
47         /* unlock fsfilt_types list */
48         return 0;
49 }
50
51 void fsfilt_unregister_ops(struct fsfilt_operations *fs_ops)
52 {
53         struct list_head *p;
54
55         /* lock fsfilt_types list */
56         list_for_each(p, &fsfilt_types) {
57                 struct fsfilt_operations *found;
58
59                 found = list_entry(p, typeof(*found), fs_list);
60                 if (found == fs_ops) {
61                         list_del(p);
62                         PORTAL_MODULE_UNUSE;
63                         break;
64                 }
65         }
66         /* unlock fsfilt_types list */
67 }
68
69 struct fsfilt_operations *fsfilt_get_ops(const char *type)
70 {
71         struct fsfilt_operations *fs_ops;
72
73         /* lock fsfilt_types list */
74         if (!(fs_ops = fsfilt_search_type(type))) {
75                 char name[32];
76                 int rc;
77
78                 snprintf(name, sizeof(name) - 1, "fsfilt_%s", type);
79                 name[sizeof(name) - 1] = '\0';
80
81                 if (!(rc = request_module(name))) {
82                         fs_ops = fsfilt_search_type(type);
83                         CDEBUG(D_INFO, "Loaded module '%s'\n", name);
84                         if (!fs_ops)
85                                 rc = -ENOENT;
86                 }
87
88                 if (rc) {
89                         CERROR("Can't find fsfilt_%s interface\n", name);
90                         RETURN(ERR_PTR(rc));
91                         /* unlock fsfilt_types list */
92                 }
93         }
94         try_module_get(fs_ops->fs_owner);
95         /* unlock fsfilt_types list */
96
97         return fs_ops;
98 }
99
100 void fsfilt_put_ops(struct fsfilt_operations *fs_ops)
101 {
102         module_put(fs_ops->fs_owner);
103 }
104
105
106 EXPORT_SYMBOL(fsfilt_register_ops);
107 EXPORT_SYMBOL(fsfilt_unregister_ops);
108 EXPORT_SYMBOL(fsfilt_get_ops);
109 EXPORT_SYMBOL(fsfilt_put_ops);