Whamcloud - gitweb
landing b_cmobd_merge on 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/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/lustre_log.h>
31 #include <linux/lustre_mds.h>
32 #include <linux/obd_class.h>
33 #include <linux/obd_cache.h>
34
35 static int cobd_attach(struct obd_device *obd, obd_count len, void *buf)
36 {
37         struct lprocfs_static_vars lvars;
38         
39         lprocfs_init_vars(cobd, &lvars);
40         return lprocfs_obd_attach(obd, lvars.obd_vars);
41 }
42
43 static int cobd_detach(struct obd_device *obd)
44 {
45         return lprocfs_obd_detach(obd);
46 }
47
48 static int cobd_setup(struct obd_device *obd, obd_count len, void *buf)
49 {
50         struct lustre_cfg *lcfg = (struct lustre_cfg *)buf;
51         struct cache_obd  *cobd = &obd->u.cobd;
52         struct obd_device *real;
53         struct obd_device *cache;
54         struct obd_uuid real_uuid;
55         struct obd_uuid cache_uuid;
56         struct lustre_handle real_conn = {0,}, cache_conn = {0,};
57         int rc;
58
59         if (lcfg->lcfg_inllen1 == 0 || lcfg->lcfg_inlbuf1 == NULL) {
60                 CERROR("%s: setup requires real device name\n", 
61                        obd->obd_name);
62                 return (-EINVAL);
63         }
64
65         real = class_name2obd(lcfg->lcfg_inlbuf1);
66         if (real == NULL) {
67                 CERROR("%s: unable to find a client for real: %s\n",
68                        obd->obd_name, lcfg->lcfg_inlbuf1);
69                 return (-EINVAL);
70         }
71
72         if (lcfg->lcfg_inllen2 == 0 || lcfg->lcfg_inlbuf2 == NULL) {
73                 CERROR("%s: setup requires cache device name\n", obd->obd_name);
74                 return (-EINVAL);
75         }
76
77         cache  = class_name2obd(lcfg->lcfg_inlbuf2);
78         if (cache == NULL) {
79                 CERROR("%s: unable to find a client for cache: %s\n",
80                        obd->obd_name, lcfg->lcfg_inlbuf2);
81                 return (-EINVAL);
82         }
83
84         /* don't bother checking attached/setup;
85          * obd_connect() should, and it can change underneath us */
86         rc = obd_connect(&real_conn, real, &real_uuid);
87         if (rc != 0)
88                 return (rc);
89         cobd->cobd_real_exp = class_conn2export(&real_conn);
90
91         rc = obd_connect(&cache_conn, cache, &cache_uuid);
92         if (rc != 0) {
93                 obd_disconnect(cobd->cobd_real_exp, 0);
94                 return rc;
95         }
96         cobd->cobd_cache_exp = class_conn2export(&cache_conn);
97         /* set mds_num for lustre */
98
99         if (!strcmp(real->obd_type->typ_name, LUSTRE_MDC_NAME)) {
100                 int mds_num;
101                 mds_num = REAL_MDS_NUMBER;
102                 obd_set_info(cobd->cobd_real_exp, strlen("mds_num"),
103                                "mds_num", sizeof(mds_num), &mds_num);
104                 mds_num = CACHE_MDS_NUMBER;
105                 obd_set_info(cobd->cobd_cache_exp, strlen("mds_num"),
106                                "mds_num", sizeof(mds_num), &mds_num);
107         }
108         /*default write to real obd*/
109         cobd->cache_on = 1;
110         return 0;
111 }
112
113 static int cobd_cleanup(struct obd_device *obd, int flags)
114 {
115         struct cache_obd  *cobd = &obd->u.cobd;
116         int                rc;
117
118         if (!list_empty(&obd->obd_exports))
119                 return (-EBUSY);
120         if (cobd->cache_on) { 
121                 rc = obd_disconnect(cobd->cobd_cache_exp, flags);
122                 if (rc != 0)
123                         CERROR("error %d disconnecting cache\n", rc);
124         }
125         rc = obd_disconnect(cobd->cobd_real_exp, flags);
126         if (rc != 0)
127                 CERROR("error %d disconnecting real\n", rc);
128         
129         return (rc);
130 }
131
132 struct obd_export *cobd_get_exp(struct obd_device *obd)
133 {
134         struct cache_obd  *cobd = &obd->u.cobd;
135         
136         if (cobd->cache_on)  
137                 return cobd->cobd_cache_exp;
138         else
139                 return cobd->cobd_real_exp;
140 }
141
142 static int
143 cobd_connect(struct lustre_handle *conn, struct obd_device *obd,
144              struct obd_uuid *cluuid)
145 {
146         int rc;
147         rc = class_connect(conn, obd, cluuid);
148         return rc; 
149 }
150
151 static int cobd_disconnect(struct obd_export *exp, int flags)
152 {
153         int rc;
154         rc = class_disconnect(exp, 0);
155         return rc; 
156 }
157
158 static int cobd_get_info(struct obd_export *exp, obd_count keylen,
159                          void *key, __u32 *vallen, void *val)
160 {
161         struct obd_device *obd = class_exp2obd(exp);
162         struct obd_export *cobd_exp;
163         if (obd == NULL) {
164                 CERROR("invalid client cookie "LPX64"\n", 
165                        exp->exp_handle.h_cookie);
166                 return -EINVAL;
167         }
168         cobd_exp = cobd_get_exp(obd);
169         /* intercept cache utilisation info? */
170
171         return obd_get_info(cobd_exp, keylen, key, vallen, val);
172 }
173
174 static int cobd_set_info(struct obd_export *exp, obd_count keylen,
175                          void *key, obd_count vallen, void *val)
176 {
177         struct obd_device *obd = class_exp2obd(exp);
178         struct obd_export *cobd_exp;
179
180         if (obd == NULL) {
181                 CERROR("invalid client cookie "LPX64"\n", 
182                        exp->exp_handle.h_cookie);
183                 return -EINVAL;
184         }
185         cobd_exp = cobd_get_exp(obd);
186         /* intercept cache utilisation info? */
187
188         return obd_set_info(cobd_exp, keylen, key, vallen, val);
189 }
190
191 static int cobd_statfs(struct obd_device *obd, struct obd_statfs *osfs,
192                        unsigned long max_age)
193 {
194         struct obd_export *cobd_exp;
195
196         cobd_exp = cobd_get_exp(obd);
197
198         return obd_statfs(class_exp2obd(cobd_exp), osfs, max_age);
199 }
200
201 static int cobd_packmd(struct obd_export *exp,
202                        struct lov_mds_md **disk_tgt,
203                        struct lov_stripe_md *mem_src)
204 {
205         struct obd_device *obd = class_exp2obd(exp);
206         struct obd_export *cobd_exp;
207
208         if (obd == NULL) {
209                 CERROR("invalid client cookie "LPX64"\n", 
210                        exp->exp_handle.h_cookie);
211                 return -EINVAL;
212         }
213         cobd_exp = cobd_get_exp(obd);
214         return obd_packmd(cobd_exp, disk_tgt, mem_src);
215 }
216
217 static int cobd_unpackmd(struct obd_export *exp,
218                          struct lov_stripe_md **mem_tgt,
219                          struct lov_mds_md *disk_src,
220                          int disk_len)
221 {
222         struct obd_device *obd = class_exp2obd(exp);
223         struct obd_export *cobd_exp;
224
225         if (obd == NULL) {
226                 CERROR("invalid client cookie "LPX64"\n", 
227                        exp->exp_handle.h_cookie);
228                 return -EINVAL;
229         }
230         cobd_exp = cobd_get_exp(obd);
231         return obd_unpackmd(cobd_exp, mem_tgt, disk_src, disk_len);
232 }
233
234 static int cobd_create(struct obd_export *exp, struct obdo *obdo,
235                        struct lov_stripe_md **ea,
236                        struct obd_trans_info *oti)
237 {
238         struct obd_device *obd = class_exp2obd(exp);
239         struct obd_export *cobd_exp;
240
241         if (obd == NULL) {
242                 CERROR("invalid client cookie "LPX64"\n", 
243                        exp->exp_handle.h_cookie);
244                 return -EINVAL;
245         }
246         cobd_exp = cobd_get_exp(obd);
247         return obd_create(cobd_exp, obdo, ea, oti); 
248 }
249
250 static int cobd_destroy(struct obd_export *exp, struct obdo *obdo,
251                         struct lov_stripe_md *ea,
252                         struct obd_trans_info *oti)
253 {
254         struct obd_device *obd = class_exp2obd(exp);
255         struct obd_export *cobd_exp;
256
257         if (obd == NULL) {
258                 CERROR("invalid client cookie "LPX64"\n", 
259                        exp->exp_handle.h_cookie);
260                 return -EINVAL;
261         }
262         cobd_exp = cobd_get_exp(obd);
263         return obd_destroy(cobd_exp, obdo, ea, oti); 
264 }
265
266 static int cobd_precleanup(struct obd_device *obd, int flags)
267 {
268         /*FIXME Do we need some cleanup here?*/
269         return 0;
270 }
271
272 static int cobd_getattr(struct obd_export *exp, struct obdo *oa,
273                         struct lov_stripe_md *lsm)
274 {
275         struct obd_device *obd = class_exp2obd(exp);
276         struct obd_export *cobd_exp;
277
278         if (obd == NULL) {
279                 CERROR("invalid client cookie "LPX64"\n", 
280                        exp->exp_handle.h_cookie);
281                 return -EINVAL;
282         }
283         cobd_exp = cobd_get_exp(obd);
284         return obd_getattr(cobd_exp, oa, lsm);
285 }
286
287 static int cobd_getattr_async(struct obd_export *exp,
288                              struct obdo *obdo, struct lov_stripe_md *ea,
289                              struct ptlrpc_request_set *set)
290 {
291         struct obd_device *obd = class_exp2obd(exp);
292         struct obd_export *cobd_exp;
293
294         if (obd == NULL) {
295                 CERROR("invalid client cookie "LPX64"\n", 
296                        exp->exp_handle.h_cookie);
297                 return -EINVAL;
298         }
299         cobd_exp = cobd_get_exp(obd);
300         return obd_getattr_async(cobd_exp, obdo, ea, set);
301 }
302
303 static int cobd_setattr(struct obd_export *exp, struct obdo *obdo,
304                         struct lov_stripe_md *ea,
305                         struct obd_trans_info *oti)
306 {
307         struct obd_device *obd = class_exp2obd(exp);
308         struct obd_export *cobd_exp;
309
310         if (obd == NULL) {
311                 CERROR("invalid client cookie "LPX64"\n", 
312                        exp->exp_handle.h_cookie);
313                 return -EINVAL;
314         }
315         cobd_exp = cobd_get_exp(obd);
316         return obd_setattr(cobd_exp, obdo, ea, oti);
317 }
318
319 static int cobd_md_getstatus(struct obd_export *exp, struct ll_fid *rootfid)
320 {
321         struct obd_device *obd = class_exp2obd(exp);
322         struct obd_export *cobd_exp;
323
324         if (obd == NULL) {
325                 CERROR("invalid client cookie "LPX64"\n", 
326                        exp->exp_handle.h_cookie);
327                 return -EINVAL;
328         }
329         cobd_exp = cobd_get_exp(obd);
330         return md_getstatus(cobd_exp, rootfid);
331 }
332
333 static int cobd_brw(int cmd, struct obd_export *exp, struct obdo *oa,
334                     struct lov_stripe_md *ea, obd_count oa_bufs,
335                     struct brw_page *pg, struct obd_trans_info *oti)
336 {
337         struct obd_device *obd = class_exp2obd(exp);
338         struct obd_export *cobd_exp;
339
340         if (obd == NULL) {
341                 CERROR("invalid client cookie "LPX64"\n", 
342                        exp->exp_handle.h_cookie);
343                 return -EINVAL;
344         }
345         cobd_exp = cobd_get_exp(obd);
346         return obd_brw(cmd, cobd_exp, oa, ea, oa_bufs, pg, oti);
347 }
348
349 static int cobd_brw_async(int cmd, struct obd_export *exp,
350                           struct obdo *oa, struct lov_stripe_md *ea,
351                           obd_count oa_bufs, struct brw_page *pg,
352                           struct ptlrpc_request_set *set,
353                           struct obd_trans_info *oti)
354 {
355         struct obd_device *obd = class_exp2obd(exp);
356         struct obd_export *cobd_exp;
357
358         if (obd == NULL) {
359                 CERROR("invalid client cookie "LPX64"\n", 
360                        exp->exp_handle.h_cookie);
361                 return -EINVAL;
362         }
363         cobd_exp = cobd_get_exp(obd);
364         return obd_brw_async(cmd, cobd_exp, oa, ea, oa_bufs, 
365                              pg, set, oti);
366 }
367
368 static int cobd_prep_async_page(struct obd_export *exp, 
369                                 struct lov_stripe_md *lsm,
370                                 struct lov_oinfo *loi, 
371                                 struct page *page, obd_off offset, 
372                                 struct obd_async_page_ops *ops, 
373                                 void *data, void **res)
374 {
375         struct obd_device *obd = class_exp2obd(exp);
376         struct obd_export *cobd_exp;
377
378         if (obd == NULL) {
379                 CERROR("invalid client cookie "LPX64"\n", 
380                        exp->exp_handle.h_cookie);
381                 return -EINVAL;
382         }
383         cobd_exp = cobd_get_exp(obd);
384         return obd_prep_async_page(cobd_exp, lsm, loi, page, offset,
385                                    ops, data, res);
386 }
387
388 static int cobd_queue_async_io(struct obd_export *exp,
389                                struct lov_stripe_md *lsm,
390                                struct lov_oinfo *loi, void *cookie,
391                                int cmd, obd_off off, int count,
392                                obd_flag brw_flags, obd_flag async_flags)
393 {
394         struct obd_device *obd = class_exp2obd(exp);
395         struct obd_export *cobd_exp;
396
397         if (obd == NULL) {
398                 CERROR("invalid client cookie "LPX64"\n", 
399                        exp->exp_handle.h_cookie);
400                 return -EINVAL;
401         }
402         cobd_exp = cobd_get_exp(obd);
403         return obd_queue_async_io(cobd_exp, lsm, loi, cookie, cmd, off, count,
404                                   brw_flags, async_flags);
405 }
406
407 static int cobd_set_async_flags(struct obd_export *exp,
408                                struct lov_stripe_md *lsm,
409                                struct lov_oinfo *loi, void *cookie,
410                                obd_flag async_flags)
411 {
412         struct obd_device *obd = class_exp2obd(exp);
413         struct obd_export *cobd_exp;
414
415         if (obd == NULL) {
416                 CERROR("invalid client cookie "LPX64"\n", 
417                        exp->exp_handle.h_cookie);
418                 return -EINVAL;
419         }
420         cobd_exp = cobd_get_exp(obd);
421         return obd_set_async_flags(cobd_exp, lsm, loi, cookie, async_flags);
422 }
423
424 static int cobd_queue_group_io(struct obd_export *exp, 
425                                struct lov_stripe_md *lsm, 
426                                struct lov_oinfo *loi, 
427                                struct obd_io_group *oig, 
428                                void *cookie, int cmd, obd_off off, 
429                                int count, obd_flag brw_flags,
430                                obd_flag async_flags)
431 {
432         struct obd_device *obd = class_exp2obd(exp);
433         struct obd_export *cobd_exp;
434
435         if (obd == NULL) {
436                 CERROR("invalid client cookie "LPX64"\n", 
437                        exp->exp_handle.h_cookie);
438                 return -EINVAL;
439         }
440         cobd_exp = cobd_get_exp(obd);
441         return obd_queue_group_io(cobd_exp, lsm, loi, oig, cookie,
442                                   cmd, off, count, brw_flags, async_flags);
443 }
444
445 static int cobd_trigger_group_io(struct obd_export *exp, 
446                                  struct lov_stripe_md *lsm, 
447                                  struct lov_oinfo *loi,
448                                  struct obd_io_group *oig)
449 {
450         struct obd_device *obd = class_exp2obd(exp);
451         struct obd_export *cobd_exp;
452
453         if (obd == NULL) {
454                 CERROR("invalid client cookie "LPX64"\n", 
455                        exp->exp_handle.h_cookie);
456                 return -EINVAL;
457         }
458         cobd_exp = cobd_get_exp(obd);
459         return obd_trigger_group_io(cobd_exp, lsm, loi, oig); 
460 }
461
462 static int cobd_teardown_async_page(struct obd_export *exp,
463                                     struct lov_stripe_md *lsm,
464                                     struct lov_oinfo *loi, void *cookie)
465 {
466         struct obd_device *obd = class_exp2obd(exp);
467         struct obd_export *cobd_exp;
468
469         if (obd == NULL) {
470                 CERROR("invalid client cookie "LPX64"\n", 
471                        exp->exp_handle.h_cookie);
472                 return -EINVAL;
473         }
474         cobd_exp = cobd_get_exp(obd);
475         return obd_teardown_async_page(cobd_exp, lsm, loi, cookie);
476 }
477
478 static int cobd_punch(struct obd_export *exp, struct obdo *oa,
479                       struct lov_stripe_md *ea, obd_size start,
480                       obd_size end, struct obd_trans_info *oti)
481 {
482         struct obd_device *obd = class_exp2obd(exp);
483         struct obd_export *cobd_exp;
484
485         if (obd == NULL) {
486                 CERROR("invalid client cookie "LPX64"\n", 
487                        exp->exp_handle.h_cookie);
488                 return -EINVAL;
489         }
490         cobd_exp = cobd_get_exp(obd);
491         return obd_punch(cobd_exp, oa, ea, start, end, oti);
492 }
493
494 static int cobd_sync(struct obd_export *exp, struct obdo *oa,
495                      struct lov_stripe_md *ea, obd_size start, 
496                      obd_size end)
497 {
498         struct obd_device *obd = class_exp2obd(exp);
499         struct obd_export *cobd_exp;
500
501         if (obd == NULL) {
502                 CERROR("invalid client cookie "LPX64"\n", 
503                        exp->exp_handle.h_cookie);
504                 return -EINVAL;
505         }
506         cobd_exp = cobd_get_exp(obd);
507         return obd_sync(cobd_exp, oa, ea, start, end);
508 }
509
510 static int cobd_enqueue(struct obd_export *exp, struct lov_stripe_md *ea,
511                         __u32 type, ldlm_policy_data_t *policy,
512                         __u32 mode, int *flags, void *bl_cb, void *cp_cb,
513                         void *gl_cb, void *data, __u32 lvb_len,
514                         void *lvb_swabber, struct lustre_handle *lockh)
515 {
516         struct obd_device *obd = class_exp2obd(exp);
517         struct obd_export *cobd_exp;
518
519         if (obd == NULL) {
520                 CERROR("invalid client cookie "LPX64"\n", 
521                        exp->exp_handle.h_cookie);
522                 return -EINVAL;
523         }
524         cobd_exp = cobd_get_exp(obd);
525         return obd_enqueue(cobd_exp, ea, type, policy, mode, flags, 
526                            bl_cb, cp_cb, gl_cb, data, lvb_len,
527                            lvb_swabber, lockh);
528 }
529
530 static int cobd_match(struct obd_export *exp, struct lov_stripe_md *ea,
531                       __u32 type, ldlm_policy_data_t *policy, __u32 mode,
532                       int *flags, void *data, struct lustre_handle *lockh)
533 {
534         struct obd_device *obd = class_exp2obd(exp);
535         struct obd_export *cobd_exp;
536
537         if (obd == NULL) {
538                 CERROR("invalid client cookie "LPX64"\n", 
539                        exp->exp_handle.h_cookie);
540                 return -EINVAL;
541         }
542         cobd_exp = cobd_get_exp(obd);
543         return obd_match(cobd_exp, ea, type, policy, mode, flags, data,
544                          lockh); 
545 }
546 static int cobd_change_cbdata(struct obd_export *exp,
547                               struct lov_stripe_md *lsm, 
548                               ldlm_iterator_t it, void *data)
549 {
550         struct obd_device *obd = class_exp2obd(exp);
551         struct obd_export *cobd_exp;
552
553         if (obd == NULL) {
554                 CERROR("invalid client cookie "LPX64"\n", 
555                        exp->exp_handle.h_cookie);
556                 return -EINVAL;
557         }
558         cobd_exp = cobd_get_exp(obd);
559         return obd_change_cbdata(cobd_exp, lsm, it, data);
560 }
561
562 static int cobd_cancel(struct obd_export *exp,
563                        struct lov_stripe_md *ea, __u32 mode,
564                        struct lustre_handle *lockh)
565 {
566         struct obd_device *obd = class_exp2obd(exp);
567         struct obd_export *cobd_exp;
568
569         if (obd == NULL) {
570                 CERROR("invalid client cookie "LPX64"\n", 
571                        exp->exp_handle.h_cookie);
572                 return -EINVAL;
573         }
574         cobd_exp = cobd_get_exp(obd);
575         return obd_cancel(cobd_exp, ea, mode, lockh);
576 }
577
578 static int cobd_cancel_unused(struct obd_export *exp,
579                               struct lov_stripe_md *ea, int flags,
580                               void *opaque)
581 {
582         struct obd_device *obd = class_exp2obd(exp);
583         struct obd_export *cobd_exp;
584
585         if (obd == NULL) {
586                 CERROR("invalid client cookie "LPX64"\n", 
587                        exp->exp_handle.h_cookie);
588                 return -EINVAL;
589         }
590         cobd_exp = cobd_get_exp(obd);
591         return obd_cancel_unused(cobd_exp, ea, flags, opaque);
592 }
593
594 static int cobd_preprw(int cmd, struct obd_export *exp, struct obdo *oa,
595                        int objcount, struct obd_ioobj *obj,
596                        int niocount, struct niobuf_remote *nb,
597                        struct niobuf_local *res, struct obd_trans_info *oti)
598 {
599         struct obd_device *obd = class_exp2obd(exp);
600         struct obd_export *cobd_exp;
601
602         if (obd == NULL) {
603                 CERROR("invalid client cookie "LPX64"\n", 
604                        exp->exp_handle.h_cookie);
605                 return -EINVAL;
606         }
607         cobd_exp = cobd_get_exp(obd);
608         return obd_preprw(cmd, cobd_exp, oa, objcount, obj, niocount, nb, 
609                           res, oti);
610 }
611
612 static int cobd_commitrw(int cmd, struct obd_export *exp, struct obdo *oa,
613                          int objcount, struct obd_ioobj *obj,
614                          int niocount, struct niobuf_local *local,
615                          struct obd_trans_info *oti, int rc)
616 {
617         struct obd_device *obd = class_exp2obd(exp);
618         struct obd_export *cobd_exp;
619
620         if (obd == NULL) {
621                 CERROR("invalid client cookie "LPX64"\n", 
622                        exp->exp_handle.h_cookie);
623                 return -EINVAL;
624         }
625         cobd_exp = cobd_get_exp(obd);
626         return obd_commitrw(cmd, cobd_exp, oa, objcount, obj, niocount, 
627                             local, oti, rc);
628 }
629
630 static int cobd_flush(struct obd_device *obd)
631 {
632        /*FLUSH the filesystem from the cache 
633         *to the real device */
634         return 0; 
635 }
636
637 static int cobd_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
638                           void *karg, void *uarg)
639 {
640         struct obd_device *obd = class_exp2obd(exp);
641         struct cache_obd  *cobd = &obd->u.cobd;
642         struct obd_device *real_dev = class_exp2obd(cobd->cobd_real_exp);
643         struct obd_device *cache_dev = class_exp2obd(cobd->cobd_cache_exp);
644         struct obd_export *cobd_exp;
645         int rc = 0;
646  
647         switch (cmd) {
648         case OBD_IOC_COBD_CON:
649                 if (!cobd->cache_on) {
650                         cobd->cache_on = 1;
651                         /*FIXME should connect the cache obd again*/ 
652                 }
653                 break;
654         case OBD_IOC_COBD_COFF: 
655                 if (cobd->cache_on) {
656                         /*Here disconnect for cancel unused ldlm resources,
657                          *then do flush, otherwise, there will be some problems
658                          *in flush cache
659                          *is is right? FIXME later*/
660                         rc = obd_disconnect(cobd->cobd_cache_exp, 0);
661                         if (rc != 0)
662                                 CERROR("error %d disconnecting real\n", rc);
663
664                         cobd->cache_on = 0;
665                         /*FIXME, should read from real_dev*/
666                         real_dev->u.cli.cl_max_mds_easize = 
667                                               cache_dev->u.cli.cl_max_mds_easize;
668                         real_dev->u.cli.cl_max_mds_cookiesize = 
669                                               cache_dev->u.cli.cl_max_mds_cookiesize;
670                         break;
671                 }
672         case OBD_IOC_COBD_CFLUSH:
673                 if (cobd->cache_on) {
674                         cobd->cache_on = 0;
675                         cobd_flush(obd);
676                         break;
677                 }
678         default:
679                 cobd_exp = cobd_get_exp(obd);
680                 rc = obd_iocontrol(cmd, cobd_exp, len, karg, uarg);
681         }
682         
683         return rc;
684 }
685
686 static int cobd_llog_init(struct obd_device *obd, struct obd_llogs *llogs, 
687                           struct obd_device *disk_obd, int count, 
688                           struct llog_catid *logid)
689 {
690         struct obd_export *cobd_exp;
691         struct obd_device *cobd_obd;
692
693         cobd_exp = cobd_get_exp(obd);
694         cobd_obd = class_exp2obd(cobd_exp);
695         
696         return obd_llog_init(cobd_obd, &cobd_obd->obd_llogs, 
697                              disk_obd, count, logid);
698 }
699
700 static int cobd_llog_finish(struct obd_device *obd, struct obd_llogs *llogs, 
701                             int count)
702 {
703         struct obd_export *cobd_exp;
704         struct obd_device *cobd_obd;
705
706         cobd_exp = cobd_get_exp(obd);
707         cobd_obd = class_exp2obd(cobd_exp);
708
709         return obd_llog_finish(cobd_obd, &cobd_obd->obd_llogs, count);
710 }
711
712 static int cobd_notify(struct obd_device *obd,
713                        struct obd_device *watched,
714                        int active)
715 {
716         struct obd_export *cobd_exp;
717
718         cobd_exp = cobd_get_exp(obd);
719
720         return obd_notify(class_exp2obd(cobd_exp), watched, active);
721 }
722
723 static int cobd_pin(struct obd_export *exp, obd_id ino, __u32 gen,
724                     int type, struct obd_client_handle *handle, int flag)
725 {
726         struct obd_device *obd = class_exp2obd(exp);
727         struct obd_export *cobd_exp;
728
729         if (obd == NULL) {
730                 CERROR("invalid client cookie "LPX64"\n", 
731                        exp->exp_handle.h_cookie);
732                 return -EINVAL;
733         }
734         cobd_exp = cobd_get_exp(obd);
735
736         return obd_pin(cobd_exp, ino, gen, type, handle, flag);
737 }
738
739 static int cobd_unpin(struct obd_export *exp,
740                       struct obd_client_handle *handle, int flag)
741 {
742         struct obd_device *obd = class_exp2obd(exp);
743         struct obd_export *cobd_exp;
744
745         if (obd == NULL) {
746                 CERROR("invalid client cookie "LPX64"\n", 
747                        exp->exp_handle.h_cookie);
748                 return -EINVAL;
749         }
750         cobd_exp = cobd_get_exp(obd);
751
752         return obd_unpin(cobd_exp, handle, flag);
753 }
754
755 static int cobd_init_ea_size(struct obd_export *exp, int easize, int cookiesize)
756 {
757         struct obd_export *cobd_exp;
758
759         cobd_exp = cobd_get_exp(exp->exp_obd);
760         return obd_init_ea_size(cobd_exp, easize, cookiesize);
761 }
762
763 static int  cobd_import_event(struct obd_device *obd,
764                               struct obd_import *imp,
765                               enum obd_import_event event)
766 {
767         struct obd_export *cobd_exp;
768
769         cobd_exp = cobd_get_exp(obd);
770
771         obd_import_event(class_exp2obd(cobd_exp), imp, event);
772         
773         return 0; 
774 }
775
776 static int cobd_md_getattr(struct obd_export *exp, struct ll_fid *fid,
777                            unsigned long valid, unsigned int ea_size,
778                            struct ptlrpc_request **request)
779 {
780         struct obd_device *obd = class_exp2obd(exp);
781         struct obd_export *cobd_exp;
782
783         if (obd == NULL) {
784                 CERROR("invalid client cookie "LPX64"\n", 
785                        exp->exp_handle.h_cookie);
786                 return -EINVAL;
787         }
788         cobd_exp = cobd_get_exp(obd);
789         return md_getattr(cobd_exp, fid, valid, ea_size, request);
790 }
791
792 static int cobd_md_req2lustre_md (struct obd_export *mdc_exp, 
793                                   struct ptlrpc_request *req, unsigned int offset,
794                                   struct obd_export *osc_exp, struct lustre_md *md)
795 {
796         struct obd_device *obd = class_exp2obd(mdc_exp);
797         struct obd_export *cobd_exp;
798
799         if (obd == NULL) {
800                 CERROR("invalid client cookie "LPX64"\n", 
801                        mdc_exp->exp_handle.h_cookie);
802                 return -EINVAL;
803         }
804         cobd_exp = cobd_get_exp(obd);
805         return md_req2lustre_md(cobd_exp, req, offset, osc_exp, md);
806 }
807
808 static int cobd_md_change_cbdata(struct obd_export *exp, struct ll_fid *fid, 
809                                  ldlm_iterator_t it, void *data)
810 {
811         struct obd_device *obd = class_exp2obd(exp);
812         struct obd_export *cobd_exp;
813
814         if (obd == NULL) {
815                 CERROR("invalid client cookie "LPX64"\n", 
816                        exp->exp_handle.h_cookie);
817                 return -EINVAL;
818         }
819         cobd_exp = cobd_get_exp(obd);
820         return md_change_cbdata(cobd_exp, fid, it, data);
821 }
822
823 static int cobd_md_getattr_name(struct obd_export *exp, struct ll_fid *fid,
824                                 char *filename, int namelen, 
825                                 unsigned long valid,
826                                 unsigned int ea_size, 
827                                 struct ptlrpc_request **request)
828 {
829         struct obd_device *obd = class_exp2obd(exp);
830         struct obd_export *cobd_exp;
831
832         if (obd == NULL) {
833                 CERROR("invalid client cookie "LPX64"\n", 
834                        exp->exp_handle.h_cookie);
835                 return -EINVAL;
836         }
837         cobd_exp = cobd_get_exp(obd);
838         return md_getattr_name(cobd_exp, fid, filename, namelen, valid,
839                                ea_size, request);
840 }
841
842 static int cobd_md_create(struct obd_export *exp, struct mdc_op_data *op_data,
843                           const void *data, int datalen, int mode, 
844                           __u32 uid, __u32 gid, __u64 rdev, 
845                           struct ptlrpc_request **request)
846 {
847         struct obd_device *obd = class_exp2obd(exp);
848         struct obd_export *cobd_exp;
849
850         if (obd == NULL) {
851                 CERROR("invalid client cookie "LPX64"\n", 
852                        exp->exp_handle.h_cookie);
853                 return -EINVAL;
854         }
855         cobd_exp = cobd_get_exp(obd);
856         return md_create(cobd_exp, op_data, data, datalen, mode,
857                          uid, gid, rdev, request);
858 }
859
860 static int cobd_md_unlink(struct obd_export *exp, struct mdc_op_data *data,
861                           struct ptlrpc_request **request)
862 {
863         struct obd_device *obd = class_exp2obd(exp);
864         struct obd_export *cobd_exp;
865
866         if (obd == NULL) {
867                 CERROR("invalid client cookie "LPX64"\n", 
868                        exp->exp_handle.h_cookie);
869                 return -EINVAL;
870         }
871         cobd_exp = cobd_get_exp(obd);
872         return md_unlink(cobd_exp, data, request);
873 }
874
875 static int cobd_md_valid_attrs(struct obd_export *exp, struct ll_fid *fid)
876 {
877         struct obd_device *obd = class_exp2obd(exp);
878         struct obd_export *cobd_exp;
879
880         if (obd == NULL) {
881                 CERROR("invalid client cookie "LPX64"\n", 
882                        exp->exp_handle.h_cookie);
883                 return -EINVAL;
884         }
885         cobd_exp = cobd_get_exp(obd);
886         return md_valid_attrs(cobd_exp, fid);
887 }
888
889 static int cobd_md_rename(struct obd_export *exp, struct mdc_op_data *data,
890                           const char *old, int oldlen, const char *new, 
891                           int newlen, struct ptlrpc_request **request)
892 {
893         struct obd_device *obd = class_exp2obd(exp);
894         struct obd_export *cobd_exp;
895
896         if (obd == NULL) {
897                 CERROR("invalid client cookie "LPX64"\n", 
898                        exp->exp_handle.h_cookie);
899                 return -EINVAL;
900         }
901         cobd_exp = cobd_get_exp(obd);
902         return md_rename(cobd_exp, data, old, oldlen, new, newlen, request);
903 }
904
905 static int cobd_md_link(struct obd_export *exp, struct mdc_op_data *data,
906                         struct ptlrpc_request **request)
907 {
908         struct obd_device *obd = class_exp2obd(exp);
909         struct obd_export *cobd_exp;
910
911         if (obd == NULL) {
912                 CERROR("invalid client cookie "LPX64"\n", 
913                        exp->exp_handle.h_cookie);
914                 return -EINVAL;
915         }
916         cobd_exp = cobd_get_exp(obd);
917         return md_link(cobd_exp, data, request);
918 }
919
920 static int cobd_md_setattr(struct obd_export *exp, struct mdc_op_data *data,
921                            struct iattr *iattr, void *ea, int ealen, void *ea2, 
922                            int ea2len, struct ptlrpc_request **request)
923 {
924         struct obd_device *obd = class_exp2obd(exp);
925         struct obd_export *cobd_exp;
926
927         if (obd == NULL) {
928                 CERROR("invalid client cookie "LPX64"\n", 
929                        exp->exp_handle.h_cookie);
930                 return -EINVAL;
931         }
932         cobd_exp = cobd_get_exp(obd);
933         return md_setattr(cobd_exp, data, iattr, ea, ealen, ea2, ea2len, request);
934 }
935
936 static int cobd_md_readpage(struct obd_export *exp, struct ll_fid *mdc_fid,
937                             __u64 offset, struct page *page, 
938                             struct ptlrpc_request **request)
939 {
940         struct obd_device *obd = class_exp2obd(exp);
941         struct obd_export *cobd_exp;
942
943         if (obd == NULL) {
944                 CERROR("invalid client cookie "LPX64"\n", 
945                        exp->exp_handle.h_cookie);
946                 return -EINVAL;
947         }
948         cobd_exp = cobd_get_exp(obd);
949         return md_readpage(cobd_exp, mdc_fid, offset, page, request);
950 }
951
952 static int cobd_md_close(struct obd_export *exp, struct obdo *obdo,
953                          struct obd_client_handle *och, 
954                          struct ptlrpc_request **request)
955 {
956         struct obd_device *obd = class_exp2obd(exp);
957         struct obd_export *cobd_exp;
958
959         if (obd == NULL) {
960                 CERROR("invalid client cookie "LPX64"\n", 
961                        exp->exp_handle.h_cookie);
962                 return -EINVAL;
963         }
964         cobd_exp = cobd_get_exp(obd);
965         return md_close(cobd_exp, obdo, och, request);
966 }
967
968 static int cobd_md_done_writing(struct obd_export *exp, struct obdo *obdo)
969 {
970         struct obd_device *obd = class_exp2obd(exp);
971         struct obd_export *cobd_exp;
972
973         if (obd == NULL) {
974                 CERROR("invalid client cookie "LPX64"\n", 
975                        exp->exp_handle.h_cookie);
976                 return -EINVAL;
977         }
978         cobd_exp = cobd_get_exp(obd);
979         return md_done_writing(cobd_exp, obdo);
980 }
981
982 static int cobd_md_sync(struct obd_export *exp, struct ll_fid *fid,
983                         struct ptlrpc_request **request)
984 {
985         struct obd_device *obd = class_exp2obd(exp);
986         struct obd_export *cobd_exp;
987
988         if (obd == NULL) {
989                 CERROR("invalid client cookie "LPX64"\n", 
990                        exp->exp_handle.h_cookie);
991                 return -EINVAL;
992         }
993         cobd_exp = cobd_get_exp(obd);
994         
995         return md_sync(cobd_exp, fid, request);
996 }
997
998 static int cobd_md_set_open_replay_data(struct obd_export *exp,
999                                         struct obd_client_handle *och,
1000                                         struct ptlrpc_request *open_req)
1001 {
1002         struct obd_device *obd = class_exp2obd(exp);
1003         struct obd_export *cobd_exp;
1004
1005         if (obd == NULL) {
1006                 CERROR("invalid client cookie "LPX64"\n", 
1007                        exp->exp_handle.h_cookie);
1008                 return -EINVAL;
1009         }
1010         cobd_exp = cobd_get_exp(obd);
1011         
1012         return md_set_open_replay_data(cobd_exp, och, open_req);
1013 }
1014
1015 static int cobd_md_clear_open_replay_data(struct obd_export *exp,
1016                                           struct obd_client_handle *och)
1017 {
1018         struct obd_device *obd = class_exp2obd(exp);
1019         struct obd_export *cobd_exp;
1020
1021         if (obd == NULL) {
1022                 CERROR("invalid client cookie "LPX64"\n", 
1023                        exp->exp_handle.h_cookie);
1024                 return -EINVAL;
1025         }
1026         cobd_exp = cobd_get_exp(obd);
1027  
1028         return md_clear_open_replay_data(cobd_exp, och);
1029 }
1030
1031 static int cobd_md_store_inode_generation(struct obd_export *exp,
1032                                           struct ptlrpc_request *req, 
1033                                           int reqoff, int repoff)
1034 {
1035         struct obd_device *obd = class_exp2obd(exp);
1036         struct obd_export *cobd_exp;
1037
1038         if (obd == NULL) {
1039                 CERROR("invalid client cookie "LPX64"\n", 
1040                        exp->exp_handle.h_cookie);
1041                 return -EINVAL;
1042         }
1043         cobd_exp = cobd_get_exp(obd);
1044
1045         return md_store_inode_generation(cobd_exp, req, reqoff, repoff);
1046 }
1047
1048 static int cobd_md_set_lock_data(struct obd_export *exp, __u64 *l, void *data)
1049 {
1050         struct obd_device *obd = class_exp2obd(exp);
1051         struct obd_export *cobd_exp;
1052
1053         if (obd == NULL) {
1054                 CERROR("invalid client cookie "LPX64"\n", 
1055                        exp->exp_handle.h_cookie);
1056                 return -EINVAL;
1057         }
1058         cobd_exp = cobd_get_exp(obd);
1059
1060         return md_set_lock_data(cobd_exp, l, data);
1061 }
1062
1063 static int cobd_md_enqueue(struct obd_export *exp, int lock_type,
1064                            struct lookup_intent *it, int lock_mode,
1065                            struct mdc_op_data *data, struct lustre_handle *lockh,
1066                            void *lmm, int lmmsize, 
1067                            ldlm_completion_callback cb_completion,
1068                            ldlm_blocking_callback cb_blocking, void *cb_data)
1069 {
1070         struct obd_device *obd = class_exp2obd(exp);
1071         struct obd_export *cobd_exp;
1072
1073         if (obd == NULL) {
1074                 CERROR("invalid client cookie "LPX64"\n", 
1075                        exp->exp_handle.h_cookie);
1076                 return -EINVAL;
1077         }
1078         cobd_exp = cobd_get_exp(obd);
1079         return md_enqueue(cobd_exp, lock_type, it, lock_mode, data,
1080                           lockh, lmm, lmmsize, cb_completion, cb_blocking,
1081                           cb_data);
1082 }
1083
1084 static int cobd_md_intent_lock(struct obd_export *exp, struct ll_uctxt *uctxt,
1085                                struct ll_fid *pfid, const char *name, int len,
1086                                void *lmm, int lmmsize,
1087                                struct ll_fid *cfid, struct lookup_intent *it,
1088                                int lookup_flags, struct ptlrpc_request **reqp,
1089                                ldlm_blocking_callback cb_blocking)
1090 {
1091         struct obd_device *obd = class_exp2obd(exp);
1092         struct obd_export *cobd_exp;
1093
1094         if (obd == NULL) {
1095                 CERROR("invalid client cookie "LPX64"\n", 
1096                        exp->exp_handle.h_cookie);
1097                 return -EINVAL;
1098         }
1099         cobd_exp = cobd_get_exp(obd);
1100         return md_intent_lock(cobd_exp, uctxt, pfid, name, len, lmm, lmmsize,
1101                               cfid, it, lookup_flags, reqp, cb_blocking);
1102 }
1103
1104 static struct obd_device * cobd_md_get_real_obd(struct obd_export *exp,
1105                                                 char *name, int len)
1106 {
1107         struct obd_device *obd = class_exp2obd(exp);
1108         struct obd_export *cobd_exp;
1109
1110         if (obd == NULL) {
1111                 CERROR("invalid client cookie "LPX64"\n", 
1112                        exp->exp_handle.h_cookie);
1113                 return NULL;
1114         }
1115         cobd_exp = cobd_get_exp(obd);
1116         return md_get_real_obd(cobd_exp, name, len);
1117 }
1118
1119 static int cobd_md_change_cbdata_name(struct obd_export *exp,
1120                                       struct ll_fid *fid, char *name,
1121                                       int namelen, struct ll_fid *fid2,
1122                                       ldlm_iterator_t it, void *data)
1123 {
1124         struct obd_device *obd = class_exp2obd(exp);
1125         struct obd_export *cobd_exp;
1126
1127         if (obd == NULL) {
1128                 CERROR("invalid client cookie "LPX64"\n", 
1129                        exp->exp_handle.h_cookie);
1130                 return -EINVAL;
1131         }
1132         cobd_exp = cobd_get_exp(obd);
1133         return md_change_cbdata_name(cobd_exp, fid, name, namelen, fid2, it, 
1134                                      data);
1135 }
1136 static struct obd_ops cobd_obd_ops = {
1137         .o_owner                = THIS_MODULE,
1138         .o_attach               = cobd_attach,
1139         .o_detach               = cobd_detach,
1140         .o_setup                = cobd_setup,
1141         .o_cleanup              = cobd_cleanup,
1142         .o_connect              = cobd_connect,
1143         .o_disconnect           = cobd_disconnect,
1144         .o_set_info             = cobd_set_info,
1145         .o_get_info             = cobd_get_info,
1146         .o_statfs               = cobd_statfs,
1147
1148         .o_packmd               = cobd_packmd,
1149         .o_unpackmd             = cobd_unpackmd,
1150         .o_create               = cobd_create,
1151         .o_destroy              = cobd_destroy,
1152         .o_precleanup           = cobd_precleanup,
1153         .o_getattr              = cobd_getattr,
1154         .o_getattr_async        = cobd_getattr_async,
1155         .o_setattr              = cobd_setattr,
1156
1157         .o_brw                  = cobd_brw,
1158         .o_brw_async            = cobd_brw_async,
1159         .o_prep_async_page      = cobd_prep_async_page,
1160         .o_queue_async_io       = cobd_queue_async_io,
1161         .o_set_async_flags      = cobd_set_async_flags,
1162         .o_queue_group_io       = cobd_queue_group_io,
1163         .o_trigger_group_io     = cobd_trigger_group_io,
1164         .o_teardown_async_page  = cobd_teardown_async_page,
1165         .o_preprw               = cobd_preprw,
1166         .o_punch                = cobd_punch,
1167         .o_sync                 = cobd_sync,
1168         .o_enqueue              = cobd_enqueue,
1169         .o_match                = cobd_match,
1170         .o_change_cbdata        = cobd_change_cbdata,
1171         .o_cancel               = cobd_cancel,
1172         .o_cancel_unused        = cobd_cancel_unused,
1173         .o_iocontrol            = cobd_iocontrol,
1174         .o_commitrw             = cobd_commitrw,
1175         .o_llog_init            = cobd_llog_init,
1176         .o_llog_finish          = cobd_llog_finish,
1177         .o_notify               = cobd_notify,
1178         .o_pin                  = cobd_pin,
1179         .o_unpin                = cobd_unpin,
1180         .o_import_event         = cobd_import_event,
1181         .o_init_ea_size         = cobd_init_ea_size,
1182 };
1183
1184 struct md_ops cobd_md_ops = {
1185         .m_getstatus            = cobd_md_getstatus,
1186         .m_getattr              = cobd_md_getattr,
1187         .m_req2lustre_md        = cobd_md_req2lustre_md,
1188         .m_change_cbdata        = cobd_md_change_cbdata,
1189         .m_getattr_name         = cobd_md_getattr_name,
1190         .m_create               = cobd_md_create,
1191         .m_unlink               = cobd_md_unlink,
1192         .m_valid_attrs          = cobd_md_valid_attrs,
1193         .m_rename               = cobd_md_rename,
1194         .m_link                 = cobd_md_link,
1195         .m_setattr              = cobd_md_setattr,
1196         .m_readpage             = cobd_md_readpage,
1197         .m_close                = cobd_md_close,
1198         .m_done_writing         = cobd_md_done_writing,
1199         .m_sync                 = cobd_md_sync,
1200         .m_set_open_replay_data = cobd_md_set_open_replay_data,
1201         .m_clear_open_replay_data = cobd_md_clear_open_replay_data,
1202         .m_store_inode_generation = cobd_md_store_inode_generation,
1203         .m_set_lock_data        = cobd_md_set_lock_data,
1204         .m_enqueue              = cobd_md_enqueue,
1205         .m_get_real_obd         = cobd_md_get_real_obd,
1206         .m_intent_lock          = cobd_md_intent_lock,
1207         .m_change_cbdata_name   = cobd_md_change_cbdata_name,
1208 };
1209
1210 static int __init cobd_init(void)
1211 {
1212         struct lprocfs_static_vars lvars;
1213         ENTRY;
1214
1215         printk(KERN_INFO "Lustre: Caching OBD driver; info@clusterfs.com\n");
1216
1217         lprocfs_init_vars(cobd, &lvars);
1218         RETURN(class_register_type(&cobd_obd_ops, &cobd_md_ops,
1219                                    lvars.module_vars, OBD_CACHE_DEVICENAME));
1220 }
1221
1222 static void /*__exit*/ cobd_exit(void)
1223 {
1224         class_unregister_type(OBD_CACHE_DEVICENAME);
1225 }
1226
1227 MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
1228 MODULE_DESCRIPTION("Lustre Caching OBD driver");
1229 MODULE_LICENSE("GPL");
1230
1231 module_init(cobd_init);
1232 module_exit(cobd_exit);