Whamcloud - gitweb
c96b2adc1ac036603c7a8c9da05aa74f4385c9f6
[fs/lustre-release.git] / lustre / cobd / cache_obd.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  Copyright (c) 2002 Cluster File Systems, Inc. <info@clusterfs.com>
5  *
6  *   This file is part of Lustre, http://www.lustre.org.
7  *
8  *   Lustre is free software; you can redistribute it and/or
9  *   modify it under the terms of version 2 of the GNU General Public
10  *   License as published by the Free Software Foundation.
11  *
12  *   Lustre is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *   GNU General Public License for more details.
16  *
17  *   You should have received a copy of the GNU General Public License
18  *   along with Lustre; if not, write to the Free Software
19  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  */
21
22 #define DEBUG_SUBSYSTEM S_COBD
23
24 #include <linux/version.h>
25 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
26 #include <linux/init.h>
27 #endif
28 #include <linux/obd_support.h>
29 #include <linux/lustre_lib.h>
30 #include <linux/lustre_net.h>
31 #include <linux/lustre_idl.h>
32 #include <linux/obd_class.h>
33 #include <linux/obd_cache.h>
34
35 static int cobd_attach(struct obd_device *dev, obd_count len, void *data)
36 {
37         struct lprocfs_static_vars lvars;
38
39         lprocfs_init_vars(&lvars);
40         return lprocfs_obd_attach(dev, lvars.obd_vars);
41 }
42
43 static int cobd_detach(struct obd_device *dev)
44 {
45         return lprocfs_obd_detach(dev);
46 }
47
48 static int
49 cobd_setup (struct obd_device *dev, obd_count len, void *buf)
50 {
51         struct obd_ioctl_data *data = (struct obd_ioctl_data *)buf;
52         struct cache_obd  *cobd = &dev->u.cobd;
53         struct obd_device *target;
54         struct obd_device *cache;
55         struct obd_uuid target_uuid;
56         struct obd_uuid cache_uuid;
57         int                rc;
58
59         if (data->ioc_inlbuf1 == NULL ||
60             data->ioc_inlbuf2 == NULL)
61                 return (-EINVAL);
62
63         obd_str2uuid(&target_uuid, data->ioc_inlbuf1);
64         target = class_uuid2obd (&target_uuid);
65
66         obd_str2uuid(&cache_uuid, data->ioc_inlbuf2);
67         cache  = class_uuid2obd (&cache_uuid);
68         if (target == NULL ||
69             cache == NULL)
70                 return (-EINVAL);
71
72         /* don't bother checking attached/setup;
73          * obd_connect() should, and it can change underneath us */
74         rc = obd_connect (&cobd->cobd_target, target, &target_uuid);
75         if (rc != 0)
76                 return (rc);
77
78         rc = obd_connect (&cobd->cobd_cache, cache, &cache_uuid);
79         if (rc != 0)
80                 goto fail_0;
81
82         return (0);
83
84  fail_0:
85         obd_disconnect (&cobd->cobd_target, 0 );
86         return (rc);
87 }
88
89 static int
90 cobd_cleanup (struct obd_device *dev, int force, int failover)
91 {
92         struct cache_obd  *cobd = &dev->u.cobd;
93         int                rc;
94
95         if (!list_empty (&dev->obd_exports))
96                 return (-EBUSY);
97
98         rc = obd_disconnect (&cobd->cobd_cache, failover);
99         if (rc != 0)
100                 CERROR ("error %d disconnecting cache\n", rc);
101
102         rc = obd_disconnect (&cobd->cobd_target, failover);
103         if (rc != 0)
104                 CERROR ("error %d disconnecting target\n", rc);
105
106         return (0);
107 }
108
109 static int
110 cobd_connect (struct lustre_handle *conn, struct obd_device *obd,
111               struct obd_uuid *cluuid)
112 {
113         int rc = class_connect (conn, obd, cluuid);
114
115         CERROR ("rc %d\n", rc);
116         return (rc);
117 }
118
119 static int
120 cobd_disconnect (struct lustre_handle *conn, int failover)
121 {
122         int rc = class_disconnect (conn, failover);
123
124         CERROR ("rc %d\n", rc);
125         return (rc);
126 }
127
128 static int
129 cobd_get_info(struct lustre_handle *conn, obd_count keylen,
130               void *key, __u32 *vallen, void *val)
131 {
132         struct obd_device *obd = class_conn2obd(conn);
133         struct cache_obd  *cobd;
134
135         if (obd == NULL) {
136                 CERROR("invalid client cookie "LPX64"\n", conn->cookie);
137                 return -EINVAL;
138         }
139
140         cobd = &obd->u.cobd;
141
142         /* intercept cache utilisation info? */
143
144         return obd_get_info(&cobd->cobd_target, keylen, key, vallen, val);
145 }
146
147 static int
148 cobd_statfs(struct lustre_handle *conn, struct obd_statfs *osfs)
149 {
150         struct obd_device *obd = class_conn2obd(conn);
151         struct cache_obd  *cobd;
152
153         if (obd == NULL) {
154                 CERROR("invalid client cookie "LPX64"\n", conn->cookie);
155                 return -EINVAL;
156         }
157
158         cobd = &obd->u.cobd;
159         return (obd_statfs (&cobd->cobd_target, osfs));
160 }
161
162 static int
163 cobd_getattr(struct lustre_handle *conn, struct obdo *oa,
164              struct lov_stripe_md *lsm)
165 {
166         struct obd_device *obd = class_conn2obd(conn);
167         struct cache_obd  *cobd;
168
169         if (obd == NULL) {
170                 CERROR("invalid client cookie "LPX64"\n", conn->cookie);
171                 return -EINVAL;
172         }
173
174         cobd = &obd->u.cobd;
175         return (obd_getattr (&cobd->cobd_target, oa, lsm));
176 }
177
178 static int
179 cobd_open(struct lustre_handle *conn, struct obdo *oa,
180           struct lov_stripe_md *lsm, struct obd_trans_info *oti,
181           struct obd_client_handle *och)
182 {
183         struct obd_device *obd = class_conn2obd(conn);
184         struct cache_obd  *cobd;
185
186         if (obd == NULL) {
187                 CERROR("invalid client cookie "LPX64"\n", conn->cookie);
188                 return -EINVAL;
189         }
190
191         cobd = &obd->u.cobd;
192         return (obd_open (&cobd->cobd_target, oa, lsm, oti, och));
193 }
194
195 static int
196 cobd_close(struct lustre_handle *conn, struct obdo *oa,
197            struct lov_stripe_md *lsm, struct obd_trans_info *oti)
198 {
199         struct obd_device *obd = class_conn2obd(conn);
200         struct cache_obd  *cobd;
201
202         if (obd == NULL) {
203                 CERROR("invalid client cookie "LPX64"\n", conn->cookie);
204                 return -EINVAL;
205         }
206
207         cobd = &obd->u.cobd;
208         return (obd_close (&cobd->cobd_target, oa, lsm, oti));
209 }
210
211 static int cobd_preprw(int cmd, struct obd_export *exp,
212                        int objcount, struct obd_ioobj *obj,
213                        int niocount, struct niobuf_remote *nb,
214                        struct niobuf_local *res, void **desc_private,
215                        struct obd_trans_info *oti)
216 {
217         struct obd_export *cobd_exp;
218         int rc;
219
220         if (exp->exp_obd == NULL)
221                 return -EINVAL;
222
223         if ((cmd & OBD_BRW_WRITE) != 0)
224                 return -EOPNOTSUPP;
225
226         cobd_exp = class_conn2export(&exp->exp_obd->u.cobd.cobd_target);
227         rc = obd_preprw(cmd, cobd_exp, objcount, obj, niocount, nb, res,
228                         desc_private, oti);
229         class_export_put(cobd_exp);
230         return rc;
231 }
232
233 static int cobd_commitrw(int cmd, struct obd_export *exp,
234                          int objcount, struct obd_ioobj *obj,
235                          int niocount, struct niobuf_local *local,
236                          void *desc_private, struct obd_trans_info *oti)
237 {
238         struct obd_export *cobd_exp;
239         int rc;
240
241         if (exp->exp_obd == NULL)
242                 return -EINVAL;
243
244         if ((cmd & OBD_BRW_WRITE) != 0)
245                 return -EOPNOTSUPP;
246
247         cobd_exp = class_conn2export(&exp->exp_obd->u.cobd.cobd_target);
248         rc = obd_commitrw(cmd, cobd_exp, objcount, obj, niocount, local,
249                           desc_private, oti);
250         class_export_put(cobd_exp);
251         return rc;
252 }
253
254 static inline int
255 cobd_brw(int cmd, struct lustre_handle *conn,
256          struct lov_stripe_md *lsm, obd_count oa_bufs,
257          struct brw_page *pga, struct obd_trans_info *oti)
258 {
259         struct obd_device *obd = class_conn2obd(conn);
260         struct cache_obd  *cobd;
261
262         if (obd == NULL) {
263                 CERROR("invalid client cookie "LPX64"\n", conn->cookie);
264                 return -EINVAL;
265         }
266
267         if ((cmd & OBD_BRW_WRITE) != 0)
268                 return -EOPNOTSUPP;
269
270         cobd = &obd->u.cobd;
271         return (obd_brw (cmd, &cobd->cobd_target,
272                          lsm, oa_bufs, pga, oti));
273 }
274
275 static int
276 cobd_iocontrol(unsigned int cmd, struct lustre_handle *conn, int len,
277                void *karg, void *uarg)
278 {
279         struct obd_device *obd = class_conn2obd(conn);
280         struct cache_obd  *cobd;
281
282         if (obd == NULL) {
283                 CERROR("invalid client cookie "LPX64"\n", conn->cookie);
284                 return -EINVAL;
285         }
286
287         /* intercept? */
288
289         cobd = &obd->u.cobd;
290         return (obd_iocontrol (cmd, &cobd->cobd_target, len, karg, uarg));
291 }
292
293 static struct obd_ops cobd_ops = {
294         o_owner:                THIS_MODULE,
295         o_attach:               cobd_attach,
296         o_detach:               cobd_detach,
297
298         o_setup:                cobd_setup,
299         o_cleanup:              cobd_cleanup,
300
301         o_connect:              cobd_connect,
302         o_disconnect:           cobd_disconnect,
303
304         o_get_info:             cobd_get_info,
305         o_statfs:               cobd_statfs,
306
307         o_getattr:              cobd_getattr,
308         o_open:                 cobd_open,
309         o_close:                cobd_close,
310         o_preprw:               cobd_preprw,
311         o_commitrw:             cobd_commitrw,
312         o_brw:                  cobd_brw,
313         o_iocontrol:            cobd_iocontrol,
314 };
315
316 static int __init cobd_init(void)
317 {
318         struct lprocfs_static_vars lvars;
319         ENTRY;
320
321         printk(KERN_INFO "Lustre Caching OBD driver; info@clusterfs.com\n");
322
323         lprocfs_init_vars(&lvars);
324         RETURN(class_register_type(&cobd_ops, lvars.module_vars,
325                                    OBD_CACHE_DEVICENAME));
326 }
327
328 static void __exit cobd_exit(void)
329 {
330         class_unregister_type(OBD_CACHE_DEVICENAME);
331 }
332
333 MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
334 MODULE_DESCRIPTION("Lustre Caching OBD driver");
335 MODULE_LICENSE("GPL");
336
337 module_init(cobd_init);
338 module_exit(cobd_exit);