Whamcloud - gitweb
Land b1_2 onto HEAD (20040304_171022)
[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 #include <linux/init.h>
26 #include <linux/obd_support.h>
27 #include <linux/lustre_lib.h>
28 #include <linux/lustre_net.h>
29 #include <linux/lustre_idl.h>
30 #include <linux/obd_class.h>
31 #include <linux/obd_cache.h>
32
33 static int cobd_attach(struct obd_device *dev, obd_count len, void *data)
34 {
35         struct lprocfs_static_vars lvars;
36
37         lprocfs_init_vars(cobd, &lvars);
38         return lprocfs_obd_attach(dev, lvars.obd_vars);
39 }
40
41 static int cobd_detach(struct obd_device *dev)
42 {
43         return lprocfs_obd_detach(dev);
44 }
45
46 static int
47 cobd_setup (struct obd_device *dev, obd_count len, void *buf)
48 {
49         struct lustre_cfg *lcfg = (struct lustre_cfg *)buf;
50         struct cache_obd  *cobd = &dev->u.cobd;
51         struct obd_device *target;
52         struct obd_device *cache;
53         struct obd_uuid target_uuid;
54         struct obd_uuid cache_uuid;
55         struct lustre_handle target_conn = {0,}, cache_conn = {0,};
56         int                rc;
57
58         if (lcfg->lcfg_inlbuf1 == NULL ||
59             lcfg->lcfg_inlbuf2 == NULL)
60                 return (-EINVAL);
61
62         obd_str2uuid(&target_uuid, lcfg->lcfg_inlbuf1);
63         target = class_uuid2obd (&target_uuid);
64
65         obd_str2uuid(&cache_uuid, lcfg->lcfg_inlbuf2);
66         cache  = class_uuid2obd (&cache_uuid);
67         if (target == NULL ||
68             cache == NULL)
69                 return (-EINVAL);
70
71         /* don't bother checking attached/setup;
72          * obd_connect() should, and it can change underneath us */
73         rc = obd_connect(&target_conn, target, &target_uuid);
74         if (rc != 0)
75                 return (rc);
76         cobd->cobd_target_exp = class_conn2export(&target_conn);
77
78         rc = obd_connect(&cache_conn, cache, &cache_uuid);
79         if (rc != 0) {
80                 obd_disconnect(cobd->cobd_target_exp, 0);
81                 return rc;
82         }
83         cobd->cobd_cache_exp = class_conn2export(&cache_conn);
84
85         return rc;
86 }
87
88 static int cobd_cleanup(struct obd_device *dev, int flags)
89 {
90         struct cache_obd  *cobd = &dev->u.cobd;
91         int                rc;
92
93         if (!list_empty(&dev->obd_exports))
94                 return (-EBUSY);
95
96         rc = obd_disconnect(cobd->cobd_cache_exp, flags);
97         if (rc != 0)
98                 CERROR ("error %d disconnecting cache\n", rc);
99
100         rc = obd_disconnect(cobd->cobd_target_exp, flags);
101         if (rc != 0)
102                 CERROR ("error %d disconnecting target\n", rc);
103
104         return (0);
105 }
106
107 static int
108 cobd_connect (struct lustre_handle *conn, struct obd_device *obd,
109               struct obd_uuid *cluuid)
110 {
111         int rc = class_connect (conn, obd, cluuid);
112
113         CERROR ("rc %d\n", rc);
114         return (rc);
115 }
116
117 static int cobd_disconnect(struct obd_export *exp, int flags)
118 {
119         int rc = class_disconnect(exp, flags);
120
121         CERROR ("rc %d\n", rc);
122         return (rc);
123 }
124
125 static int cobd_get_info(struct obd_export *exp, obd_count keylen,
126                          void *key, __u32 *vallen, void *val)
127 {
128         struct obd_device *obd = class_exp2obd(exp);
129         struct cache_obd  *cobd;
130
131         if (obd == NULL) {
132                 CERROR("invalid client cookie "LPX64"\n", 
133                        exp->exp_handle.h_cookie);
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_exp, keylen, key, vallen, val);
142 }
143
144 static int cobd_statfs(struct obd_device *obd, struct obd_statfs *osfs,
145                        unsigned long max_age)
146 {
147         return obd_statfs(class_exp2obd(obd->u.cobd.cobd_target_exp), osfs,
148                           max_age);
149 }
150
151 static int cobd_getattr(struct obd_export *exp, struct obdo *oa,
152                         struct lov_stripe_md *lsm)
153 {
154         struct obd_device *obd = class_exp2obd(exp);
155         struct cache_obd  *cobd;
156
157         if (obd == NULL) {
158                 CERROR("invalid client cookie "LPX64"\n", 
159                         exp->exp_handle.h_cookie);
160                 return -EINVAL;
161         }
162
163         cobd = &obd->u.cobd;
164         return obd_getattr(cobd->cobd_target_exp, oa, lsm);
165 }
166
167 static int cobd_preprw(int cmd, struct obd_export *exp, struct obdo *oa,
168                        int objcount, struct obd_ioobj *obj,
169                        int niocount, struct niobuf_remote *nb,
170                        struct niobuf_local *res, struct obd_trans_info *oti)
171 {
172         struct obd_export *cobd_exp;
173         int rc;
174
175         if (exp->exp_obd == NULL)
176                 return -EINVAL;
177
178         if ((cmd & OBD_BRW_WRITE) != 0)
179                 return -EOPNOTSUPP;
180
181         cobd_exp = exp->exp_obd->u.cobd.cobd_target_exp;
182         rc = obd_preprw(cmd, cobd_exp, oa, objcount, obj, niocount, nb, res,
183                         oti);
184
185         return rc;
186 }
187
188 static int cobd_commitrw(int cmd, struct obd_export *exp, struct obdo *oa,
189                          int objcount, struct obd_ioobj *obj,
190                          int niocount, struct niobuf_local *local,
191                          struct obd_trans_info *oti, int rc)
192 {
193         struct obd_export *cobd_exp;
194
195         if (exp->exp_obd == NULL)
196                 return -EINVAL;
197
198         if ((cmd & OBD_BRW_WRITE) != 0)
199                 return -EOPNOTSUPP;
200
201         cobd_exp = exp->exp_obd->u.cobd.cobd_target_exp;
202         rc = obd_commitrw(cmd, cobd_exp, oa, objcount, obj, niocount, local,
203                           oti, rc);
204         return rc;
205 }
206
207 static int cobd_brw(int cmd, struct obd_export *exp, struct obdo *oa,
208                     struct lov_stripe_md *lsm, obd_count oa_bufs,
209                     struct brw_page *pga, struct obd_trans_info *oti)
210 {
211         struct obd_device *obd = class_exp2obd(exp);
212         struct cache_obd  *cobd;
213
214         if (obd == NULL) {
215                 CERROR("invalid client cookie "LPX64"\n",
216                        exp->exp_handle.h_cookie);
217                 return -EINVAL;
218         }
219
220         if ((cmd & OBD_BRW_WRITE) != 0)
221                 return -EOPNOTSUPP;
222
223         cobd = &obd->u.cobd;
224         return obd_brw(cmd, cobd->cobd_target_exp, oa, lsm, oa_bufs, pga, oti);
225 }
226
227 static int cobd_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
228                           void *karg, void *uarg)
229 {
230         struct obd_device *obd = class_exp2obd(exp);
231         struct cache_obd  *cobd;
232
233         if (obd == NULL) {
234                 CERROR("invalid client cookie "LPX64"\n", 
235                        exp->exp_handle.h_cookie);
236                 return -EINVAL;
237         }
238
239         /* intercept? */
240
241         cobd = &obd->u.cobd;
242         return obd_iocontrol(cmd, cobd->cobd_target_exp, len, karg, uarg);
243 }
244
245 static struct obd_ops cobd_ops = {
246         o_owner:                THIS_MODULE,
247         o_attach:               cobd_attach,
248         o_detach:               cobd_detach,
249
250         o_setup:                cobd_setup,
251         o_cleanup:              cobd_cleanup,
252
253         o_connect:              cobd_connect,
254         o_disconnect:           cobd_disconnect,
255
256         o_get_info:             cobd_get_info,
257         o_statfs:               cobd_statfs,
258
259         o_getattr:              cobd_getattr,
260         o_preprw:               cobd_preprw,
261         o_commitrw:             cobd_commitrw,
262         o_brw:                  cobd_brw,
263         o_iocontrol:            cobd_iocontrol,
264 };
265
266 static int __init cobd_init(void)
267 {
268         struct lprocfs_static_vars lvars;
269         ENTRY;
270
271         printk(KERN_INFO "Lustre: Caching OBD driver; info@clusterfs.com\n");
272
273         lprocfs_init_vars(cobd, &lvars);
274         RETURN(class_register_type(&cobd_ops, lvars.module_vars,
275                                    OBD_CACHE_DEVICENAME));
276 }
277
278 static void /*__exit*/ cobd_exit(void)
279 {
280         class_unregister_type(OBD_CACHE_DEVICENAME);
281 }
282
283 MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
284 MODULE_DESCRIPTION("Lustre Caching OBD driver");
285 MODULE_LICENSE("GPL");
286
287 module_init(cobd_init);
288 module_exit(cobd_exit);