Whamcloud - gitweb
Merge b_md into HEAD
[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/obd_support.h>
25 #include <linux/lustre_lib.h>
26 #include <linux/lustre_net.h>
27 #include <linux/lustre_idl.h>
28 #include <linux/obd_class.h>
29 #include <linux/obd_cache.h>
30
31 static int cobd_attach(struct obd_device *dev, obd_count len, void *data)
32 {
33         struct lprocfs_static_vars lvars;
34
35         lprocfs_init_vars(&lvars);
36         return lprocfs_obd_attach(dev, lvars.obd_vars);
37 }
38
39 static int cobd_detach(struct obd_device *dev)
40 {
41         return lprocfs_obd_detach(dev);
42 }
43
44 static int
45 cobd_setup (struct obd_device *dev, obd_count len, void *buf)
46 {
47         struct obd_ioctl_data *data = (struct obd_ioctl_data *)buf;
48         struct cache_obd  *cobd = &dev->u.cobd;
49         struct obd_device *target;
50         struct obd_device *cache;
51         struct obd_uuid target_uuid;
52         struct obd_uuid cache_uuid;
53         int                rc;
54
55         if (data->ioc_inlbuf1 == NULL ||
56             data->ioc_inlbuf2 == NULL)
57                 return (-EINVAL);
58
59         obd_str2uuid(&target_uuid, data->ioc_inlbuf1);
60         target = class_uuid2obd (&target_uuid);
61
62         obd_str2uuid(&cache_uuid, data->ioc_inlbuf2);
63         cache  = class_uuid2obd (&cache_uuid);
64         if (target == NULL ||
65             cache == NULL)
66                 return (-EINVAL);
67
68         /* don't bother checking attached/setup;
69          * obd_connect() should, and it can change underneath us */
70         rc = obd_connect (&cobd->cobd_target, target, &target_uuid, NULL, NULL);
71         if (rc != 0)
72                 return (rc);
73
74         rc = obd_connect (&cobd->cobd_cache, cache, &cache_uuid, NULL, NULL);
75         if (rc != 0)
76                 goto fail_0;
77
78         return (0);
79
80  fail_0:
81         obd_disconnect (&cobd->cobd_target);
82         return (rc);
83 }
84
85 static int
86 cobd_cleanup (struct obd_device *dev)
87 {
88         struct cache_obd  *cobd = &dev->u.cobd;
89         int                rc;
90
91         if (!list_empty (&dev->obd_exports))
92                 return (-EBUSY);
93
94         rc = obd_disconnect (&cobd->cobd_cache);
95         if (rc != 0)
96                 CERROR ("error %d disconnecting cache\n", rc);
97
98         rc = obd_disconnect (&cobd->cobd_target);
99         if (rc != 0)
100                 CERROR ("error %d disconnecting target\n", rc);
101
102         return (0);
103 }
104
105 static int
106 cobd_connect (struct lustre_handle *conn, struct obd_device *obd,
107               struct obd_uuid *cluuid, struct recovd_obd *recovd,
108               ptlrpc_recovery_cb_t recover)
109 {
110         int rc = class_connect (conn, obd, cluuid);
111
112         CERROR ("rc %d\n", rc);
113         return (rc);
114 }
115
116 static int
117 cobd_disconnect (struct lustre_handle *conn)
118 {
119         int rc = class_disconnect (conn);
120
121         CERROR ("rc %d\n", rc);
122         return (rc);
123 }
124
125 static int
126 cobd_get_info(struct lustre_handle *conn, obd_count keylen,
127               void *key, obd_count *vallen, void **val)
128 {
129         struct obd_device *obd = class_conn2obd(conn);
130         struct cache_obd  *cobd;
131
132         if (obd == NULL) {
133                 CERROR("invalid client "LPX64"\n", conn->addr);
134                 return -EINVAL;
135         }
136
137         cobd = &obd->u.cobd;
138
139         /* intercept cache utilisation info? */
140
141         return (obd_get_info (&cobd->cobd_target,
142                               keylen, key, vallen, val));
143 }
144
145 static int
146 cobd_statfs(struct lustre_handle *conn, struct obd_statfs *osfs)
147 {
148         struct obd_device *obd = class_conn2obd(conn);
149         struct cache_obd  *cobd;
150
151         if (obd == NULL) {
152                 CERROR("invalid client "LPX64"\n", conn->addr);
153                 return -EINVAL;
154         }
155
156         cobd = &obd->u.cobd;
157         return (obd_statfs (&cobd->cobd_target, osfs));
158 }
159
160 static int
161 cobd_getattr(struct lustre_handle *conn, struct obdo *oa,
162              struct lov_stripe_md *lsm)
163 {
164         struct obd_device *obd = class_conn2obd(conn);
165         struct cache_obd  *cobd;
166
167         if (obd == NULL) {
168                 CERROR("invalid client "LPX64"\n", conn->addr);
169                 return -EINVAL;
170         }
171
172         cobd = &obd->u.cobd;
173         return (obd_getattr (&cobd->cobd_target, oa, lsm));
174 }
175
176 static int
177 cobd_open(struct lustre_handle *conn, struct obdo *oa,
178           struct lov_stripe_md *lsm, struct obd_trans_info *oti)
179 {
180         struct obd_device *obd = class_conn2obd(conn);
181         struct cache_obd  *cobd;
182
183         if (obd == NULL) {
184                 CERROR("invalid client "LPX64"\n", conn->addr);
185                 return -EINVAL;
186         }
187
188         cobd = &obd->u.cobd;
189         return (obd_open (&cobd->cobd_target, oa, lsm, oti));
190 }
191
192 static int
193 cobd_close(struct lustre_handle *conn, struct obdo *oa,
194            struct lov_stripe_md *lsm, struct obd_trans_info *oti)
195 {
196         struct obd_device *obd = class_conn2obd(conn);
197         struct cache_obd  *cobd;
198
199         if (obd == NULL) {
200                 CERROR("invalid client "LPX64"\n", conn->addr);
201                 return -EINVAL;
202         }
203
204         cobd = &obd->u.cobd;
205         return (obd_close (&cobd->cobd_target, oa, lsm, oti));
206 }
207
208 static int
209 cobd_preprw(int cmd, struct lustre_handle *conn,
210             int objcount, struct obd_ioobj *obj,
211             int niocount, struct niobuf_remote *nb,
212             struct niobuf_local *res, void **desc_private, 
213             struct obd_trans_info *oti)
214 {
215         struct obd_device *obd = class_conn2obd(conn);
216         struct cache_obd  *cobd;
217
218         if (obd == NULL) {
219                 CERROR("invalid client "LPX64"\n", conn->addr);
220                 return -EINVAL;
221         }
222
223         if ((cmd & OBD_BRW_WRITE) != 0)
224                 return -EOPNOTSUPP;
225
226         cobd = &obd->u.cobd;
227         return (obd_preprw (cmd, &cobd->cobd_target,
228                             objcount, obj,
229                             niocount, nb,
230                             res, desc_private, oti));
231 }
232
233 static int
234 cobd_commitrw(int cmd, struct lustre_handle *conn,
235               int objcount, struct obd_ioobj *obj,
236               int niocount, struct niobuf_local *local,
237               void *desc_private, struct obd_trans_info *oti)
238 {
239         struct obd_device *obd = class_conn2obd(conn);
240         struct cache_obd  *cobd;
241
242         if (obd == NULL) {
243                 CERROR("invalid client "LPX64"\n", conn->addr);
244                 return -EINVAL;
245         }
246
247         if ((cmd & OBD_BRW_WRITE) != 0)
248                 return -EOPNOTSUPP;
249
250         cobd = &obd->u.cobd;
251         return (obd_commitrw (cmd, &cobd->cobd_target,
252                               objcount, obj,
253                               niocount, local,
254                               desc_private, oti));
255 }
256
257 static inline int
258 cobd_brw(int cmd, struct lustre_handle *conn,
259          struct lov_stripe_md *lsm, obd_count oa_bufs,
260          struct brw_page *pga, struct obd_brw_set *set, 
261          struct obd_trans_info *oti)
262 {
263         struct obd_device *obd = class_conn2obd(conn);
264         struct cache_obd  *cobd;
265
266         if (obd == NULL) {
267                 CERROR("invalid client "LPX64"\n", conn->addr);
268                 return -EINVAL;
269         }
270
271         if ((cmd & OBD_BRW_WRITE) != 0)
272                 return -EOPNOTSUPP;
273
274         cobd = &obd->u.cobd;
275         return (obd_brw (cmd, &cobd->cobd_target,
276                          lsm, oa_bufs, pga, set, oti));
277 }
278
279 static int
280 cobd_iocontrol(unsigned int cmd, struct lustre_handle *conn, int len,
281                void *karg, void *uarg)
282 {
283         struct obd_device *obd = class_conn2obd(conn);
284         struct cache_obd  *cobd;
285
286         if (obd == NULL) {
287                 CERROR("invalid client "LPX64"\n", conn->addr);
288                 return -EINVAL;
289         }
290
291         /* intercept? */
292
293         cobd = &obd->u.cobd;
294         return (obd_iocontrol (cmd, &cobd->cobd_target, len, karg, uarg));
295 }
296
297 static struct obd_ops cobd_ops = {
298         o_owner:                THIS_MODULE,
299         o_attach:               cobd_attach,
300         o_detach:               cobd_detach,
301
302         o_setup:                cobd_setup,
303         o_cleanup:              cobd_cleanup,
304
305         o_connect:              cobd_connect,
306         o_disconnect:           cobd_disconnect,
307
308         o_get_info:             cobd_get_info,
309         o_statfs:               cobd_statfs,
310
311         o_getattr:              cobd_getattr,
312         o_open:                 cobd_open,
313         o_close:                cobd_close,
314         o_preprw:               cobd_preprw,
315         o_commitrw:             cobd_commitrw,
316         o_brw:                  cobd_brw,
317         o_iocontrol:            cobd_iocontrol,
318 };
319
320 static int __init cobd_init(void)
321 {
322         struct lprocfs_static_vars lvars;
323         ENTRY;
324
325         printk(KERN_INFO "Lustre Caching OBD driver; info@clusterfs.com\n");
326
327         lprocfs_init_vars(&lvars);
328         RETURN(class_register_type(&cobd_ops, lvars.module_vars,
329                                    OBD_CACHE_DEVICENAME));
330 }
331
332 static void __exit cobd_exit(void)
333 {
334         class_unregister_type(OBD_CACHE_DEVICENAME);
335 }
336
337 MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
338 MODULE_DESCRIPTION("Lustre Caching OBD driver");
339 MODULE_LICENSE("GPL");
340
341 module_init(cobd_init);
342 module_exit(cobd_exit);