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