Whamcloud - gitweb
merge b_devel into HEAD, which will become 0.7.3
[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(cobd, &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 cobd_cleanup(struct obd_device *dev, int flags)
90 {
91         struct cache_obd  *cobd = &dev->u.cobd;
92         int                rc;
93
94         if (!list_empty(&dev->obd_exports))
95                 return (-EBUSY);
96
97         rc = obd_disconnect(&cobd->cobd_cache, flags);
98         if (rc != 0)
99                 CERROR ("error %d disconnecting cache\n", rc);
100
101         rc = obd_disconnect(&cobd->cobd_target, flags);
102         if (rc != 0)
103                 CERROR ("error %d disconnecting target\n", rc);
104
105         return (0);
106 }
107
108 static int
109 cobd_connect (struct lustre_handle *conn, struct obd_device *obd,
110               struct obd_uuid *cluuid)
111 {
112         int rc = class_connect (conn, obd, cluuid);
113
114         CERROR ("rc %d\n", rc);
115         return (rc);
116 }
117
118 static int cobd_disconnect(struct lustre_handle *conn, int flags)
119 {
120         int rc = class_disconnect(conn, flags);
121
122         CERROR ("rc %d\n", rc);
123         return (rc);
124 }
125
126 static int
127 cobd_get_info(struct lustre_handle *conn, obd_count keylen,
128               void *key, __u32 *vallen, void *val)
129 {
130         struct obd_device *obd = class_conn2obd(conn);
131         struct cache_obd  *cobd;
132
133         if (obd == NULL) {
134                 CERROR("invalid client cookie "LPX64"\n", conn->cookie);
135                 return -EINVAL;
136         }
137
138         cobd = &obd->u.cobd;
139
140         /* intercept cache utilisation info? */
141
142         return obd_get_info(&cobd->cobd_target, keylen, key, vallen, val);
143 }
144
145 static int cobd_statfs(struct obd_device *obd, struct obd_statfs *osfs,
146                        unsigned long max_age)
147 {
148         return obd_statfs(class_conn2obd(&obd->u.cobd.cobd_target), osfs,
149                           max_age);
150 }
151
152 static int cobd_getattr(struct lustre_handle *conn, struct obdo *oa,
153                         struct lov_stripe_md *lsm)
154 {
155         struct obd_device *obd = class_conn2obd(conn);
156         struct cache_obd  *cobd;
157
158         if (obd == NULL) {
159                 CERROR("invalid client cookie "LPX64"\n", conn->cookie);
160                 return -EINVAL;
161         }
162
163         cobd = &obd->u.cobd;
164         return (obd_getattr (&cobd->cobd_target, oa, lsm));
165 }
166
167 static int
168 cobd_open(struct lustre_handle *conn, struct obdo *oa,
169           struct lov_stripe_md *lsm, struct obd_trans_info *oti,
170           struct obd_client_handle *och)
171 {
172         struct obd_device *obd = class_conn2obd(conn);
173         struct cache_obd  *cobd;
174
175         if (obd == NULL) {
176                 CERROR("invalid client cookie "LPX64"\n", conn->cookie);
177                 return -EINVAL;
178         }
179
180         cobd = &obd->u.cobd;
181         return (obd_open (&cobd->cobd_target, oa, lsm, oti, och));
182 }
183
184 static int
185 cobd_close(struct lustre_handle *conn, struct obdo *oa,
186            struct lov_stripe_md *lsm, struct obd_trans_info *oti)
187 {
188         struct obd_device *obd = class_conn2obd(conn);
189         struct cache_obd  *cobd;
190
191         if (obd == NULL) {
192                 CERROR("invalid client cookie "LPX64"\n", conn->cookie);
193                 return -EINVAL;
194         }
195
196         cobd = &obd->u.cobd;
197         return (obd_close (&cobd->cobd_target, oa, lsm, oti));
198 }
199
200 static int cobd_preprw(int cmd, struct obd_export *exp, struct obdo *oa,
201                        int objcount, struct obd_ioobj *obj,
202                        int niocount, struct niobuf_remote *nb,
203                        struct niobuf_local *res, struct obd_trans_info *oti)
204 {
205         struct obd_export *cobd_exp;
206         int rc;
207
208         if (exp->exp_obd == NULL)
209                 return -EINVAL;
210
211         if ((cmd & OBD_BRW_WRITE) != 0)
212                 return -EOPNOTSUPP;
213
214         cobd_exp = class_conn2export(&exp->exp_obd->u.cobd.cobd_target);
215         rc = obd_preprw(cmd, cobd_exp, oa, objcount, obj, niocount, nb, res,
216                         oti);
217         class_export_put(cobd_exp);
218
219         return rc;
220 }
221
222 static int cobd_commitrw(int cmd, struct obd_export *exp, struct obdo *oa,
223                          int objcount, struct obd_ioobj *obj,
224                          int niocount, struct niobuf_local *local,
225                          struct obd_trans_info *oti)
226 {
227         struct obd_export *cobd_exp;
228         int rc;
229
230         if (exp->exp_obd == NULL)
231                 return -EINVAL;
232
233         if ((cmd & OBD_BRW_WRITE) != 0)
234                 return -EOPNOTSUPP;
235
236         cobd_exp = class_conn2export(&exp->exp_obd->u.cobd.cobd_target);
237         rc = obd_commitrw(cmd, cobd_exp, oa, objcount, obj,niocount,local,oti);
238         class_export_put(cobd_exp);
239         return rc;
240 }
241
242 static int cobd_brw(int cmd, struct lustre_handle *conn, struct obdo *oa,
243                     struct lov_stripe_md *lsm, obd_count oa_bufs,
244                     struct brw_page *pga, struct obd_trans_info *oti)
245 {
246         struct obd_device *obd = class_conn2obd(conn);
247         struct cache_obd  *cobd;
248
249         if (obd == NULL) {
250                 CERROR("invalid client cookie "LPX64"\n", conn->cookie);
251                 return -EINVAL;
252         }
253
254         if ((cmd & OBD_BRW_WRITE) != 0)
255                 return -EOPNOTSUPP;
256
257         cobd = &obd->u.cobd;
258         return (obd_brw(cmd, &cobd->cobd_target, oa, lsm, oa_bufs, pga, oti));
259 }
260
261 static int cobd_iocontrol(unsigned int cmd, struct lustre_handle *conn, int len,
262                           void *karg, void *uarg)
263 {
264         struct obd_device *obd = class_conn2obd(conn);
265         struct cache_obd  *cobd;
266
267         if (obd == NULL) {
268                 CERROR("invalid client cookie "LPX64"\n", conn->cookie);
269                 return -EINVAL;
270         }
271
272         /* intercept? */
273
274         cobd = &obd->u.cobd;
275         return (obd_iocontrol(cmd, &cobd->cobd_target, len, karg, uarg));
276 }
277
278 static struct obd_ops cobd_ops = {
279         o_owner:                THIS_MODULE,
280         o_attach:               cobd_attach,
281         o_detach:               cobd_detach,
282
283         o_setup:                cobd_setup,
284         o_cleanup:              cobd_cleanup,
285
286         o_connect:              cobd_connect,
287         o_disconnect:           cobd_disconnect,
288
289         o_get_info:             cobd_get_info,
290         o_statfs:               cobd_statfs,
291
292         o_getattr:              cobd_getattr,
293         o_open:                 cobd_open,
294         o_close:                cobd_close,
295         o_preprw:               cobd_preprw,
296         o_commitrw:             cobd_commitrw,
297         o_brw:                  cobd_brw,
298         o_iocontrol:            cobd_iocontrol,
299 };
300
301 static int __init cobd_init(void)
302 {
303         struct lprocfs_static_vars lvars;
304         ENTRY;
305
306         printk(KERN_INFO "Lustre Caching OBD driver; info@clusterfs.com\n");
307
308         lprocfs_init_vars(cobd, &lvars);
309         RETURN(class_register_type(&cobd_ops, lvars.module_vars,
310                                    OBD_CACHE_DEVICENAME));
311 }
312
313 static void /*__exit*/ cobd_exit(void)
314 {
315         class_unregister_type(OBD_CACHE_DEVICENAME);
316 }
317
318 MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
319 MODULE_DESCRIPTION("Lustre Caching OBD driver");
320 MODULE_LICENSE("GPL");
321
322 module_init(cobd_init);
323 module_exit(cobd_exit);