Whamcloud - gitweb
Fix a few compiler warnings.
[fs/lustre-release.git] / lustre / obdclass / genops.c
1 /*
2  *  linux/fs/ext2_obd/sim_obd.c
3  * Copyright (C) 2001  Cluster File Systems, Inc.
4  *
5  * This code is issued under the GNU General Public License.
6  * See the file COPYING in this distribution
7  *
8  * These are the only exported functions, they provide some generic
9  * infrastructure for managing object devices
10  *
11  */
12
13 #define DEBUG_SUBSYSTEM S_CLASS
14 #include <linux/module.h>
15 #include <linux/obd_class.h>
16 #include <linux/random.h>
17 #include <linux/slab.h>
18
19 extern struct list_head obd_types; 
20 extern struct obd_device obd_dev[MAX_OBD_DEVICES];
21 kmem_cache_t *obdo_cachep = NULL;
22 kmem_cache_t *export_cachep = NULL;
23 kmem_cache_t *import_cachep = NULL;
24
25 /*
26  * support functions: we could use inter-module communication, but this
27  * is more portable to other OS's
28  */
29 static struct obd_type *class_search_type(char *nm)
30 {
31         struct list_head *tmp;
32         struct obd_type *type;
33         CDEBUG(D_INFO, "SEARCH %s\n", nm);
34
35         tmp = &obd_types;
36         while ( (tmp = tmp->next) != &obd_types ) {
37                 type = list_entry(tmp, struct obd_type, typ_chain);
38                 CDEBUG(D_INFO, "TYP %s\n", type->typ_name);
39                 if (strlen(type->typ_name) == strlen(nm) &&
40                     strcmp(type->typ_name, nm) == 0 ) {
41                         return type;
42                 }
43         }
44         return NULL;
45 }
46
47 struct obd_type *class_nm_to_type(char *nm)
48 {
49         struct obd_type *type = class_search_type(nm);
50
51 #ifdef CONFIG_KMOD
52         if ( !type ) {
53                 if ( !request_module(nm) ) {
54                         CDEBUG(D_INFO, "Loaded module '%s'\n", nm);
55                         type = class_search_type(nm);
56                 } else {
57                         CDEBUG(D_INFO, "Can't load module '%s'\n", nm);
58                 }
59         }
60 #endif
61         return type;
62 }
63
64 int class_register_type(struct obd_ops *ops, char *nm)
65 {
66         struct obd_type *type;
67
68         ENTRY;
69
70         if (class_nm_to_type(nm)) {
71                 CDEBUG(D_IOCTL, "Type %s already registered\n", nm);
72                 RETURN(-EEXIST);
73         }
74
75         OBD_ALLOC(type, sizeof(*type));
76         if (!type)
77                 RETURN(-ENOMEM);
78         INIT_LIST_HEAD(&type->typ_chain);
79         MOD_INC_USE_COUNT;
80         list_add(&type->typ_chain, obd_types.next);
81         type->typ_ops = ops;
82         type->typ_name = nm;
83         RETURN(0);
84 }
85
86 int class_unregister_type(char *nm)
87 {
88         struct obd_type *type = class_nm_to_type(nm);
89
90         ENTRY;
91
92         if ( !type ) {
93                 MOD_DEC_USE_COUNT;
94                 CERROR("unknown obd type\n");
95                 RETURN(-EINVAL);
96         }
97
98         if ( type->typ_refcnt ) {
99                 MOD_DEC_USE_COUNT;
100                 CERROR("type %s has refcount (%d)\n", nm, type->typ_refcnt);
101                 RETURN(-EBUSY);
102         }
103
104         list_del(&type->typ_chain);
105         OBD_FREE(type, sizeof(*type));
106         MOD_DEC_USE_COUNT;
107         RETURN(0);
108 } /* class_unregister_type */
109
110 int class_name2dev(char *name)
111 {
112         int res = -1;
113         int i;
114
115         for (i=0; i < MAX_OBD_DEVICES; i++) {
116                 struct obd_device *obd = &obd_dev[i];
117                 if (obd->obd_name && strcmp(name, obd->obd_name) == 0) {
118                         res = i;
119                         return res;
120                 }
121         }
122
123         return res;
124 }
125
126 int class_uuid2dev(char *name)
127 {
128         int res = -1;
129         int i;
130
131         for (i=0; i < MAX_OBD_DEVICES; i++) {
132                 struct obd_device *obd = &obd_dev[i];
133                 if (obd->obd_name && strncmp(name, obd->obd_uuid, 37) == 0) {
134                         res = i;
135                         return res;
136                 }
137         }
138
139         return res;
140 }
141
142 void obd_cleanup_caches(void)
143 {
144         int rc;
145         ENTRY;
146         if (obdo_cachep) { 
147                 rc = kmem_cache_destroy(obdo_cachep);
148                 if (rc)
149                         CERROR("Cannot destory obdo_cachep\n");
150                 obdo_cachep = NULL;
151         }
152         if (import_cachep) { 
153                 rc = kmem_cache_destroy(import_cachep);
154                 if (rc)
155                         CERROR("Cannot destory import_cachep\n");
156                 import_cachep = NULL;
157         }
158         if (export_cachep) { 
159                 rc = kmem_cache_destroy(export_cachep);
160                 if (rc)
161                         CERROR("Cannot destory import_cachep\n");
162                 export_cachep = NULL;
163         }
164         EXIT;
165 }
166
167 int obd_init_caches(void)
168 {
169         ENTRY;
170         if (obdo_cachep == NULL) {
171                 obdo_cachep = kmem_cache_create("obdo_cache",
172                                                 sizeof(struct obdo),
173                                                 0, SLAB_HWCACHE_ALIGN,
174                                                 NULL, NULL);
175                 if (obdo_cachep == NULL)
176                         GOTO(out, -ENOMEM);
177         }
178
179         if (export_cachep == NULL) {
180                 export_cachep = kmem_cache_create("export_cache",
181                                                 sizeof(struct obd_export),
182                                                 0, SLAB_HWCACHE_ALIGN,
183                                                 NULL, NULL);
184                 if (export_cachep == NULL)
185                         GOTO(out, -ENOMEM);
186         }
187
188         if (import_cachep == NULL) {
189                 import_cachep = kmem_cache_create("import_cache",
190                                                 sizeof(struct obd_import),
191                                                 0, SLAB_HWCACHE_ALIGN,
192                                                 NULL, NULL);
193                 if (import_cachep == NULL)
194                         GOTO(out, -ENOMEM);
195         }
196         RETURN(0);
197  out:
198         obd_cleanup_caches();
199         RETURN(-ENOMEM);
200
201 }
202
203 /* map connection to client */
204 struct obd_export *class_conn2export(struct lustre_handle *conn)
205 {
206         struct obd_export * export;
207
208         if (!conn)
209                 RETURN(NULL);
210
211         if (!conn->addr || conn->addr == -1 ) { 
212                 fixme();
213                 RETURN(NULL);
214         }
215               
216         export = (struct obd_export *) (unsigned long)conn->addr;
217         if (!kmem_cache_validate(export_cachep, (void *)export))
218                 RETURN(NULL);
219
220         if (export->export_cookie != conn->cookie)
221                 return NULL;
222         return export;
223 } /* class_conn2export */
224
225 struct obd_device *class_conn2obd(struct lustre_handle *conn)
226 {
227         struct obd_export *export;
228         export = class_conn2export(conn); 
229         if (export) 
230                 return export->export_obd;
231         fixme();
232         return NULL;
233 }
234
235 /* a connection defines an export context in which preallocation can
236    be managed. */
237 int class_connect (struct lustre_handle *conn, struct obd_device *obd)
238 {
239         struct obd_export * export;
240
241         export = kmem_cache_alloc(export_cachep, GFP_KERNEL); 
242         if ( !export ) {
243                 CERROR("no memory! (minor %d)\n", obd->obd_minor);
244                 return -ENOMEM;
245         }
246
247         memset(export, 0, sizeof(*export));
248         get_random_bytes(&export->export_cookie, sizeof(__u64));
249         /* XXX this should probably spinlocked? */
250         export->export_id = ++obd->obd_gen_last_id;
251         export->export_obd = obd; 
252         export->export_import.addr = conn->addr;
253         export->export_import.cookie = conn->cookie;
254         
255         list_add(&(export->export_chain), export->export_obd->obd_exports.prev);
256
257         CDEBUG(D_INFO, "connect: new ID %u\n", export->export_id);
258         conn->addr = (__u64) (unsigned long)export;
259         conn->cookie = export->export_cookie;
260         return 0;
261 } /* class_connect */
262
263 int class_disconnect(struct lustre_handle *conn)
264 {
265         struct obd_export * export;
266         ENTRY;
267
268         if (!(export = class_conn2export(conn))) {
269                 fixme();
270                 CDEBUG(D_IOCTL, "disconnect: attempting to free "
271                        "nonexistent client %Lx\n", conn->addr);
272                 RETURN(-EINVAL);
273         }
274         list_del(&export->export_chain);
275         kmem_cache_free(export_cachep, export);
276
277         RETURN(0);
278 } /* gen_obd_disconnect */
279
280 /* FIXME: Data is a space- or comma-separated list of device IDs.  This will
281  * have to change. */
282 int class_multi_setup(struct obd_device *obddev, uint32_t len, void *data)
283 {
284         int count, rc;
285         char *p;
286         ENTRY;
287
288         for (p = data, count = 0; p < (char *)data + len; count++) {
289                 char *end;
290                 int tmp = simple_strtoul(p, &end, 0);
291
292                 if (p == end) {
293                         CERROR("invalid device ID starting at: %s\n", p);
294                         GOTO(err_disconnect, rc = -EINVAL);
295                 }
296                 
297                 if (tmp < 0 || tmp >= MAX_OBD_DEVICES) { 
298                         CERROR("Trying to sub dev %d  - dev no too large\n", 
299                                tmp);
300                         GOTO(err_disconnect, rc  = -EINVAL); 
301                 }
302
303                 rc = obd_connect(&obddev->obd_multi_conn[count], &obd_dev[tmp]);
304                 if (rc) {
305                         CERROR("cannot connect to device %d: rc = %d\n", tmp,
306                                rc);
307                         GOTO(err_disconnect, rc);
308                 }
309
310                 CDEBUG(D_INFO, "target OBD %d is of type %s\n", count,
311                        obd_dev[tmp].obd_type->typ_name);
312
313                 p = end + 1;
314         }
315
316         obddev->obd_multi_count = count;
317
318         RETURN(0);
319
320  err_disconnect:
321         for (count--; count >= 0; count--)
322                 obd_disconnect(&obddev->obd_multi_conn[count]);
323         return rc;
324 }
325
326 /*
327  *    remove all connections to this device
328  *    close all connections to lower devices
329  *    needed for forced unloads of OBD client drivers
330  */
331 int class_multi_cleanup(struct obd_device *obddev)
332 {
333         int i;
334
335         for (i = 0; i < obddev->obd_multi_count; i++) {
336                 int rc;
337                 struct obd_device *obd = class_conn2obd(&obddev->obd_multi_conn[i]);
338
339                 if (!obd) { 
340                         CERROR("no such device [i %d]\n", i); 
341                         RETURN(-EINVAL);
342                 }
343
344                 rc = obd_disconnect(&obddev->obd_multi_conn[i]);
345                 if (rc)
346                         CERROR("disconnect failure %d\n", obd->obd_minor);
347         }
348         return 0;
349 }
350