Whamcloud - gitweb
- landed b_hd_mdref (mostly WB cache 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/lustre_log.h>
31 #include <linux/lustre_mds.h>
32 #include <linux/obd_class.h>
33 #include <linux/obd_cache.h>
34 #include <linux/obd_lmv.h>
35 #include <linux/obd_lov.h>
36
37 static int cobd_attach(struct obd_device *obd,
38                        obd_count len, void *buf)
39 {
40         struct lprocfs_static_vars lvars;
41         int rc = 0;
42         ENTRY;
43         
44         lprocfs_init_vars(cobd, &lvars);
45         rc = lprocfs_obd_attach(obd, lvars.obd_vars);
46         
47         RETURN(rc);
48 }
49
50 static int cobd_detach(struct obd_device *obd)
51 {
52         ENTRY;
53         RETURN(lprocfs_obd_detach(obd));
54 }
55
56 static int cobd_setup(struct obd_device *obd, obd_count len, void *buf)
57 {
58         struct lustre_cfg *lcfg = (struct lustre_cfg *)buf;
59         int inst_len = 0, mname_len = 0, cname_len = 0;
60         struct obd_device *master_obd, *cache_obd;
61         struct cache_obd  *cobd = &obd->u.cobd;
62         struct lustre_handle conn = { 0 };
63         int rc = 0;
64         ENTRY;
65
66         sema_init(&cobd->sem, 1);
67         
68         if (LUSTRE_CFG_BUFLEN(lcfg, 1) < 1 ||
69             lustre_cfg_buf(lcfg, 1) == NULL) {
70                 CERROR("%s: setup requires master device name\n", 
71                        obd->obd_name);
72                 RETURN(-EINVAL);
73         }
74
75         if (LUSTRE_CFG_BUFLEN(lcfg, 2) < 1 ||
76             lustre_cfg_buf(lcfg, 2) == NULL) {
77                 CERROR("%s: setup requires cache device name\n",
78                        obd->obd_name);
79                 RETURN(-EINVAL);
80         }
81         inst_len = LUSTRE_CFG_BUFLEN(lcfg, 3);
82         
83         if (inst_len) {
84                 LASSERT(lustre_cfg_buf(lcfg, 3) != NULL);
85                 mname_len = LUSTRE_CFG_BUFLEN(lcfg, 1) + inst_len;  
86                 cname_len = LUSTRE_CFG_BUFLEN(lcfg, 2) + inst_len;  
87         } else {
88                 mname_len = LUSTRE_CFG_BUFLEN(lcfg, 1);
89                 cname_len = LUSTRE_CFG_BUFLEN(lcfg, 2);
90         } 
91        
92         /* get the cache obd name and master name */
93         OBD_ALLOC(cobd->master_name, mname_len);
94         if (!cobd->master_name) 
95                 RETURN(-ENOMEM);
96         if(inst_len)
97                 sprintf(cobd->master_name, "%s-%s", lustre_cfg_string(lcfg, 1), 
98                         lustre_cfg_string(lcfg, 3));
99         else 
100                 sprintf(cobd->master_name, "%s", lustre_cfg_string(lcfg, 1));
101         
102         OBD_ALLOC(cobd->cache_name, cname_len);
103         if (!cobd->cache_name) {
104                 OBD_FREE(cobd->master_name, mname_len);
105                 RETURN(-ENOMEM);
106         } 
107         if (inst_len)
108                 sprintf(cobd->cache_name, "%s-%s", lustre_cfg_string(lcfg, 2), 
109                         lustre_cfg_string(lcfg, 3));
110         else 
111                 sprintf(cobd->cache_name, "%s", lustre_cfg_string(lcfg, 2));
112
113         CDEBUG(D_INFO, "master name %s cache name %s\n", cobd->master_name,
114                cobd->cache_name);
115         
116         /* getting master obd */
117         master_obd = class_name2obd(cobd->master_name);
118         if (!master_obd) {
119                 CERROR("can't find master obd by name %s\n",
120                        cobd->master_name);
121                 GOTO(put_names, rc = -EINVAL);
122         }
123
124         /* connecting master */
125         memset(&conn, 0, sizeof(conn));
126         rc = class_connect(&conn, master_obd, &obd->obd_uuid);
127         if (rc)
128                GOTO(put_names, rc);
129         
130         cobd->master_exp = class_conn2export(&conn);
131
132         /* getting cache obd */
133         cache_obd = class_name2obd(cobd->cache_name);
134         if (!cache_obd) {
135                 class_disconnect(cobd->master_exp, 0);
136                 CERROR("can't find cache obd by name %s\n",
137                        cobd->cache_name);
138                 GOTO(put_names, rc = -EINVAL);
139         }
140
141         /* connecting cache */
142         memset(&conn, 0, sizeof(conn));
143         rc = class_connect(&conn, cache_obd, &obd->obd_uuid);
144         if (rc) {
145                 class_disconnect(cobd->master_exp, 0);
146                 GOTO(put_names, rc);
147         }
148         cobd->cache_exp = class_conn2export(&conn);
149         
150         /* default set cache on, but nothins is realy connected yet, will be
151          * done in cobd_connect() time. */
152         cobd->cache_on = 1;
153
154         /* nothing is connected, make exports reflect this state to not confuse
155          * cobd_switch() later. */
156         cobd->cache_real_exp = NULL;
157         cobd->master_real_exp = NULL;
158         
159         EXIT;
160 put_names:
161         if (rc) {
162                 if (cobd->master_name) {
163                         OBD_FREE(cobd->master_name, LUSTRE_CFG_BUFLEN(lcfg, 1));
164                         cobd->master_name = NULL;
165                 } 
166                 if (cobd->cache_name) {
167                         OBD_FREE(cobd->cache_name, LUSTRE_CFG_BUFLEN(lcfg, 2));
168                         cobd->cache_name = NULL;
169                 }
170         }
171         return rc;
172 }
173
174 static int cobd_cleanup(struct obd_device *obd, int flags)
175 {
176         struct cache_obd  *cobd = &obd->u.cobd;
177         int rc = 0;
178         ENTRY;
179
180         if (!list_empty(&obd->obd_exports))
181                 RETURN(-EBUSY);
182
183         if (cobd->cache_name)
184                 OBD_FREE(cobd->cache_name, 
185                          strlen(cobd->cache_name) + 1);
186         if (cobd->master_name)
187                 OBD_FREE(cobd->master_name, 
188                          strlen(cobd->master_name) + 1);
189         
190         rc = class_disconnect(cobd->master_exp, flags);
191         if (rc) {
192                 CERROR("error disconnecting master, err %d\n",
193                        rc);
194         }
195         rc = class_disconnect(cobd->cache_exp, flags);
196         if (rc) {
197                 CERROR("error disconnecting master, err %d\n",
198                        rc);
199         }
200
201         RETURN(0);
202 }
203
204 static inline struct obd_export *
205 cobd_get_exp(struct obd_device *obd)
206 {
207         struct cache_obd *cobd = &obd->u.cobd;
208         ENTRY;
209         
210         if (cobd->cache_on) {
211                 CDEBUG(D_TRACE, "get cache exp %p \n", cobd->cache_exp); 
212                 if (cobd->cache_real_exp)
213                         RETURN(cobd->cache_real_exp);
214                 RETURN(cobd->cache_exp);
215         }
216         
217         CDEBUG(D_TRACE, "get master exp %p \n", cobd->master_exp);
218         if (cobd->master_real_exp)
219                 RETURN(cobd->master_real_exp); 
220         RETURN(cobd->master_exp);
221 }
222
223 static int cobd_init_dt_desc(struct obd_device *obd)
224 {
225         struct cache_obd *cobd = &obd->u.cobd;
226         struct obd_export *cobd_exp;
227         __u32 valsize;
228         int rc = 0;
229         ENTRY;
230         
231         valsize = sizeof(cobd->dt_desc);
232         memset(&cobd->dt_desc, 0, sizeof(cobd->dt_desc));
233
234         cobd_exp = cobd_get_exp(obd);
235         rc = obd_get_info(cobd_exp, strlen("lovdesc") + 1,
236                           "lovdesc", &valsize, &cobd->dt_desc);
237         RETURN(rc);
238 }
239         
240 static int cobd_init_ea_size(struct obd_device *obd)
241 {
242         int rc = 0, tgt_count, easize, cookiesize;
243         struct cache_obd *cobd = &obd->u.cobd;
244         struct obd_export *cobd_exp;
245         ENTRY;
246
247         tgt_count = cobd->dt_desc.ld_tgt_count;
248
249         /* no EA setup is needed as there is single OST with no LOV */
250         if (tgt_count == 0)
251                 RETURN(0);
252
253         cobd_exp = cobd_get_exp(obd);
254         easize = lov_mds_md_size(tgt_count);
255         cookiesize = tgt_count * sizeof(struct llog_cookie);
256         rc = obd_init_ea_size(cobd_exp, easize, cookiesize);
257         RETURN(rc);
258 }
259
260 static int
261 cobd_connect_client(struct obd_device *obd,
262                     struct obd_export *exp,
263                     struct lustre_handle *conn,
264                     struct obd_connect_data *data,
265                     unsigned long flags)
266
267         struct obd_device *cli_obd;
268         int rc = 0;
269         ENTRY;
270  
271         LASSERT(obd);
272         LASSERT(conn);
273         
274         cli_obd = class_exp2obd(exp);
275         if (cli_obd == NULL) 
276                 RETURN(-EINVAL);
277
278         rc = obd_connect(conn, cli_obd, &obd->obd_uuid,
279                          data, flags);
280         if (rc) 
281                 CERROR("error connecting err %d\n", rc);
282
283         RETURN(rc);
284 }
285
286 static int
287 cobd_disconnect_client(struct obd_device *obd,
288                        struct obd_export *exp,
289                        unsigned long flags)
290 {
291         struct obd_device *cli_obd;
292         int rc = 0;
293         ENTRY;
294
295         cli_obd = class_exp2obd(exp);
296         cli_obd->obd_no_recov = obd->obd_no_recov;
297         
298         rc = obd_disconnect(exp, flags);
299         if (rc) {
300                 CERROR("error disconnecting from %s, err %d\n",
301                        cli_obd->obd_name, rc);
302                 class_export_put(exp);
303         }
304         RETURN(rc);
305 }
306
307 #define COBD_CONNECT (1 << 0)
308 #define COBD_DISCON (1 << 1)
309 #define COBD_BOTH (1 << 2)
310
311 /* magic function for switching cobd between two exports cache and master in
312  * strong correspondence with passed @cache_on. It also may perform partial
313  * actions like only turn off old export or only turn on new one.
314  *
315  * bias == COBD_CONNECT only connect new export (used in cobd_connect())
316  * bias == COBD_DISCON only disconnect old export (used in cobd_disconnect())
317  * bias == COBD_BOTH do both (disconnect old and connect new) (used in
318  * cobd_iocontrol())
319  */
320 static int cobd_switch(struct obd_device *obd,
321                        int cache_on, int bias)
322 {
323         struct cache_obd *cobd = &obd->u.cobd;
324         struct obd_device *cli_obd = NULL;
325         struct lustre_handle conn = {0,};
326         struct obd_export *discon_exp;
327         struct obd_export *conn_exp;
328         int rc = 0;
329         ENTRY;
330
331         if (cache_on) {
332                 discon_exp = cobd->master_real_exp;
333                 conn_exp = cobd->cache_exp;
334         } else {
335                 discon_exp = cobd->cache_real_exp;
336                 conn_exp = cobd->master_exp;
337         }
338
339         /* disconnect old export */
340         if (bias == COBD_BOTH || bias == COBD_DISCON) {
341                 if (discon_exp) {
342                         rc = cobd_disconnect_client(obd, discon_exp, 0);
343                         if (rc) {
344                                 CWARN("can't disconnect export %p, err %d\n",
345                                       discon_exp, rc);
346                         }
347                 }
348                 
349                 if (cache_on)
350                         cobd->master_real_exp = NULL;
351                 else
352                         cobd->cache_real_exp = NULL; 
353         }
354
355         /* connect new export */
356         if (bias == COBD_BOTH || bias == COBD_CONNECT) {
357                 rc = cobd_connect_client(obd, conn_exp, &conn,
358                                          NULL, OBD_OPT_REAL_CLIENT);
359                 if (rc) {
360                         CERROR("can't connect export %p, err %d\n",
361                                conn_exp, rc);
362                         RETURN(rc);
363                 }
364
365                 if (cache_on) {
366                         cobd->cache_real_exp = class_conn2export(&conn);
367                         cli_obd = class_exp2obd(cobd->cache_exp);
368                 } else {
369                         cobd->master_real_exp = class_conn2export(&conn);
370                         cli_obd = class_exp2obd(cobd->master_exp);
371                 }
372         }
373
374         cobd->cache_on = cache_on;
375         
376         if (bias == COBD_BOTH || bias == COBD_CONNECT) {
377                 /* re-init EA size for new selected export. This should be done after
378                  * assigining new state to @cobd->cache_on to not call not connened
379                  * already old export. */
380                 if (obd_md_type(cli_obd)) {
381                         rc = cobd_init_dt_desc(obd);
382                         if (rc == 0) {
383                                 rc = cobd_init_ea_size(obd);
384                                 if (rc) {
385                                         CERROR("can't initialize EA size, "
386                                                "err %d\n", rc);
387                                 }
388                         } else {
389                                 /* ignore cases when we di dnot manage to init
390                                  * lovdesc. This is because some devices may not know
391                                  * "lovdesc" info command. */
392                                 rc = 0;
393                         }
394                 }
395         }
396
397         RETURN(rc);
398 }
399
400 static int
401 cobd_connect(struct lustre_handle *conn, struct obd_device *obd,
402              struct obd_uuid *cluuid, struct obd_connect_data *data,
403              unsigned long flags)
404 {
405         struct cache_obd *cobd = &obd->u.cobd;
406         struct obd_export *exp;
407         int rc = 0;
408         ENTRY;
409
410         rc = class_connect(conn, obd, cluuid);
411         if (rc)
412                 RETURN(rc);
413
414         exp = class_conn2export(conn);
415         rc = cobd_switch(obd, cobd->cache_on,
416                          COBD_CONNECT);
417         if (rc)
418                 class_disconnect(exp, 0);
419         else
420                 class_export_put(exp);
421         RETURN(rc);
422 }
423
424 static int
425 cobd_disconnect(struct obd_export *exp, unsigned long flags)
426 {
427         struct cache_obd *cobd;
428         struct obd_device *obd;
429         int rc = 0;
430         ENTRY;
431         
432         LASSERT(exp != NULL);
433         obd = class_exp2obd(exp);
434         if (obd == NULL) {
435                 CDEBUG(D_IOCTL, "invalid client cookie "
436                        LPX64"\n", exp->exp_handle.h_cookie);
437                 RETURN(-EINVAL);
438         }
439
440         /* here would be nice also to check that disconnect goes to the same
441          * export as connect did. But as now we are accepting the notion that
442          * cache should be switched after client umount this is not needed.
443          * --umka. */
444         cobd = &obd->u.cobd;
445         rc = cobd_switch(obd, cobd->cache_on, COBD_DISCON);
446         class_disconnect(exp, flags);
447
448         RETURN(rc);
449 }
450
451 static int cobd_get_info(struct obd_export *exp, __u32 keylen,
452                          void *key, __u32 *vallen, void *val)
453 {
454         struct obd_device *obd = class_exp2obd(exp);
455         struct obd_export *cobd_exp;
456         int rc = 0;
457         ENTRY;
458         
459         if (obd == NULL) {
460                 CERROR("invalid client cookie "LPX64"\n", 
461                        exp->exp_handle.h_cookie);
462                 RETURN(-EINVAL);
463         }
464         cobd_exp = cobd_get_exp(obd);
465
466         /* intercept cache utilisation info? */
467         rc = obd_get_info(cobd_exp, keylen, key, vallen, val);
468         RETURN(rc);
469 }
470
471 static int cobd_set_info(struct obd_export *exp, obd_count keylen,
472                          void *key, obd_count vallen, void *val)
473 {
474         struct obd_device *obd = class_exp2obd(exp);
475         struct obd_export *cobd_exp;
476         int rc = 0;
477         ENTRY;
478
479         if (obd == NULL) {
480                 CERROR("invalid client cookie "LPX64"\n", 
481                        exp->exp_handle.h_cookie);
482                 RETURN(-EINVAL);
483         }
484         cobd_exp = cobd_get_exp(obd);
485        
486         LASSERT(cobd_exp);
487         
488         /* intercept cache utilisation info? */
489         rc = obd_set_info(cobd_exp, keylen, key, vallen, val);
490         RETURN(rc);
491 }
492
493 static int cobd_statfs(struct obd_device *obd,
494                        struct obd_statfs *osfs,
495                        unsigned long max_age)
496 {
497         struct obd_export *cobd_exp;
498         int rc = 0;
499         ENTRY;
500
501         cobd_exp = cobd_get_exp(obd);
502         rc = obd_statfs(class_exp2obd(cobd_exp), osfs, max_age);
503         RETURN(rc);
504 }
505
506 static int cobd_iocontrol(unsigned int cmd, struct obd_export *exp,
507                           int len, void *karg, void *uarg)
508 {
509         struct obd_device *obd = class_exp2obd(exp);
510         struct cache_obd  *cobd = &obd->u.cobd;
511         struct obd_export *cobd_exp;
512         int rc = 0;
513         ENTRY;
514
515         down(&cobd->sem);
516         
517         /* here would be nice also to make sure somehow that there are no
518          * out-standing requests which go to wrong MDS after cache switch (close
519          * RPCs). But how to check that from COBD? I do not know. --umka */
520         switch (cmd) {
521         case OBD_IOC_COBD_CON:
522                 if (!cobd->cache_on)
523                         rc = cobd_switch(obd, 1, COBD_BOTH);
524                 break;
525         case OBD_IOC_COBD_COFF: 
526                 if (cobd->cache_on)
527                         rc = cobd_switch(obd, 0, COBD_BOTH);
528                 break;
529         default:
530                 cobd_exp = cobd_get_exp(obd);
531                 rc = obd_iocontrol(cmd, cobd_exp, len, karg, uarg);
532         }
533
534         up(&cobd->sem);
535         RETURN(rc);
536 }
537
538 static int cobd_dt_packmd(struct obd_export *exp,
539                           struct lov_mds_md **disk_tgt,
540                           struct lov_stripe_md *mem_src)
541 {
542         struct obd_device *obd = class_exp2obd(exp);
543         struct obd_export *cobd_exp;
544         int rc = 0;
545         ENTRY;
546
547         if (obd == NULL) {
548                 CERROR("invalid client cookie "LPX64"\n", 
549                        exp->exp_handle.h_cookie);
550                 RETURN(-EINVAL);
551         }
552         cobd_exp = cobd_get_exp(obd);
553         rc = obd_packmd(cobd_exp, disk_tgt, mem_src);
554         RETURN(rc);
555 }
556
557 static int cobd_dt_unpackmd(struct obd_export *exp,
558                             struct lov_stripe_md **mem_tgt,
559                             struct lov_mds_md *disk_src,
560                             int disk_len)
561 {
562         struct obd_device *obd = class_exp2obd(exp);
563         struct obd_export *cobd_exp;
564         int rc = 0;
565         ENTRY;
566
567         if (obd == NULL) {
568                 CERROR("invalid client cookie "LPX64"\n", 
569                        exp->exp_handle.h_cookie);
570                 RETURN(-EINVAL);
571         }
572         cobd_exp = cobd_get_exp(obd);
573         rc = obd_unpackmd(cobd_exp, mem_tgt, disk_src, disk_len);
574         RETURN(rc);
575 }
576
577 static int cobd_dt_create(struct obd_export *exp,
578                           struct obdo *obdo,
579                           void *acl, int acl_size,
580                           struct lov_stripe_md **ea,
581                           struct obd_trans_info *oti)
582 {
583         struct obd_device *obd = class_exp2obd(exp);
584         struct obd_export *cobd_exp;
585         int rc = 0;
586         ENTRY;
587
588         if (obd == NULL) {
589                 CERROR("invalid client cookie "LPX64"\n", 
590                        exp->exp_handle.h_cookie);
591                 RETURN(-EINVAL);
592         }
593         cobd_exp = cobd_get_exp(obd);
594         rc = obd_create(cobd_exp, obdo, acl, acl_size, ea, oti);
595         RETURN(rc);
596 }
597
598 static int cobd_dt_destroy(struct obd_export *exp,
599                            struct obdo *obdo,
600                            struct lov_stripe_md *ea,
601                            struct obd_trans_info *oti)
602 {
603         struct obd_device *obd = class_exp2obd(exp);
604         struct obd_export *cobd_exp;
605         int rc = 0;
606         ENTRY;
607
608         if (obd == NULL) {
609                 CERROR("invalid client cookie "LPX64"\n", 
610                        exp->exp_handle.h_cookie);
611                 RETURN(-EINVAL);
612         }
613         cobd_exp = cobd_get_exp(obd);
614         rc = obd_destroy(cobd_exp, obdo, ea, oti);
615         RETURN(rc);
616 }
617
618 static int cobd_dt_precleanup(struct obd_device *obd, int flags)
619 {
620         /* FIXME: do we need some cleanup here? */
621         ENTRY;
622         RETURN(0);
623 }
624
625 static int cobd_dt_getattr(struct obd_export *exp, struct obdo *oa,
626                            struct lov_stripe_md *ea)
627 {
628         struct obd_device *obd = class_exp2obd(exp);
629         struct obd_export *cobd_exp;
630         int rc = 0;
631         ENTRY;
632
633         if (obd == NULL) {
634                 CERROR("invalid client cookie "LPX64"\n", 
635                        exp->exp_handle.h_cookie);
636                 RETURN(-EINVAL);
637         }
638         cobd_exp = cobd_get_exp(obd);
639         rc = obd_getattr(cobd_exp, oa, ea);
640         RETURN(rc);
641 }
642
643 static int cobd_dt_getattr_async(struct obd_export *exp,
644                                  struct obdo *obdo, struct lov_stripe_md *ea,
645                                  struct ptlrpc_request_set *set)
646 {
647         struct obd_device *obd = class_exp2obd(exp);
648         struct obd_export *cobd_exp;
649         int rc = 0;
650         ENTRY;
651
652         if (obd == NULL) {
653                 CERROR("invalid client cookie "LPX64"\n", 
654                        exp->exp_handle.h_cookie);
655                 RETURN(-EINVAL);
656         }
657         cobd_exp = cobd_get_exp(obd);
658         rc = obd_getattr_async(cobd_exp, obdo, ea, set);
659         RETURN(rc);
660 }
661
662 static int cobd_dt_setattr(struct obd_export *exp, struct obdo *obdo,
663                            struct lov_stripe_md *ea,
664                            struct obd_trans_info *oti)
665 {
666         struct obd_device *obd = class_exp2obd(exp);
667         struct obd_export *cobd_exp;
668         int rc = 0;
669         ENTRY;
670
671         if (obd == NULL) {
672                 CERROR("invalid client cookie "LPX64"\n", 
673                        exp->exp_handle.h_cookie);
674                 RETURN(-EINVAL);
675         }
676         cobd_exp = cobd_get_exp(obd);
677         rc = obd_setattr(cobd_exp, obdo, ea, oti);
678         RETURN(rc);
679 }
680
681 static int cobd_dt_brw(int cmd, struct obd_export *exp, struct obdo *oa,
682                        struct lov_stripe_md *ea, obd_count oa_bufs,
683                        struct brw_page *pg, struct obd_trans_info *oti)
684 {
685         struct obd_device *obd = class_exp2obd(exp);
686         struct obd_export *cobd_exp;
687         int rc = 0;
688         ENTRY;
689
690         if (obd == NULL) {
691                 CERROR("invalid client cookie "LPX64"\n", 
692                        exp->exp_handle.h_cookie);
693                 RETURN(-EINVAL);
694         }
695         cobd_exp = cobd_get_exp(obd);
696         rc = obd_brw(cmd, cobd_exp, oa, ea, oa_bufs, pg, oti);
697         RETURN(rc);
698 }
699
700 static int cobd_dt_brw_async(int cmd, struct obd_export *exp,
701                              struct obdo *oa, struct lov_stripe_md *ea,
702                              obd_count oa_bufs, struct brw_page *pg,
703                              struct ptlrpc_request_set *set,
704                              struct obd_trans_info *oti)
705 {
706         struct obd_device *obd = class_exp2obd(exp);
707         struct obd_export *cobd_exp;
708         int rc = 0;
709         ENTRY;
710
711         if (obd == NULL) {
712                 CERROR("invalid client cookie "LPX64"\n", 
713                        exp->exp_handle.h_cookie);
714                 RETURN(-EINVAL);
715         }
716         cobd_exp = cobd_get_exp(obd);
717         rc = obd_brw_async(cmd, cobd_exp, oa, ea, oa_bufs, 
718                            pg, set, oti);
719         RETURN(rc);
720 }
721
722 static int cobd_dt_prep_async_page(struct obd_export *exp, 
723                                    struct lov_stripe_md *lsm,
724                                    struct lov_oinfo *loi, 
725                                    struct page *page, obd_off offset, 
726                                    struct obd_async_page_ops *ops, 
727                                    void *data, void **res)
728 {
729         struct obd_device *obd = class_exp2obd(exp);
730         struct obd_export *cobd_exp;
731         int rc = 0;
732         ENTRY;
733
734         if (obd == NULL) {
735                 CERROR("invalid client cookie "LPX64"\n", 
736                        exp->exp_handle.h_cookie);
737                 RETURN(-EINVAL);
738         }
739         cobd_exp = cobd_get_exp(obd);
740         rc = obd_prep_async_page(cobd_exp, lsm, loi, page,
741                                  offset, ops, data, res);
742         RETURN(rc);
743 }
744
745 static int cobd_dt_queue_async_io(struct obd_export *exp,
746                                   struct lov_stripe_md *lsm,
747                                   struct lov_oinfo *loi, void *cookie,
748                                   int cmd, obd_off off, int count,
749                                   obd_flags brw_flags, obd_flags async_flags)
750 {
751         struct obd_device *obd = class_exp2obd(exp);
752         struct obd_export *cobd_exp;
753         int rc = 0;
754         ENTRY;
755
756         if (obd == NULL) {
757                 CERROR("invalid client cookie "LPX64"\n", 
758                        exp->exp_handle.h_cookie);
759                 RETURN(-EINVAL);
760         }
761         cobd_exp = cobd_get_exp(obd);
762         rc = obd_queue_async_io(cobd_exp, lsm, loi, cookie, cmd, off,
763                                 count, brw_flags, async_flags);
764         RETURN(rc);
765 }
766
767 static int cobd_dt_set_async_flags(struct obd_export *exp,
768                                    struct lov_stripe_md *lsm,
769                                    struct lov_oinfo *loi, void *cookie,
770                                    obd_flags async_flags)
771 {
772         struct obd_device *obd = class_exp2obd(exp);
773         struct obd_export *cobd_exp;
774         int rc = 0;
775         ENTRY;
776
777         if (obd == NULL) {
778                 CERROR("invalid client cookie "LPX64"\n", 
779                        exp->exp_handle.h_cookie);
780                 RETURN(-EINVAL);
781         }
782         cobd_exp = cobd_get_exp(obd);
783         rc = obd_set_async_flags(cobd_exp, lsm, loi, cookie,
784                                  async_flags);
785         RETURN(rc);
786 }
787
788 static int cobd_dt_queue_group_io(struct obd_export *exp, 
789                                   struct lov_stripe_md *lsm, 
790                                   struct lov_oinfo *loi, 
791                                   struct obd_io_group *oig, 
792                                   void *cookie, int cmd, obd_off off, 
793                                   int count, obd_flags brw_flags,
794                                   obd_flags async_flags)
795 {
796         struct obd_device *obd = class_exp2obd(exp);
797         struct obd_export *cobd_exp;
798         int rc = 0;
799         ENTRY;
800
801         if (obd == NULL) {
802                 CERROR("invalid client cookie "LPX64"\n", 
803                        exp->exp_handle.h_cookie);
804                 RETURN(-EINVAL);
805         }
806         cobd_exp = cobd_get_exp(obd);
807         rc = obd_queue_group_io(cobd_exp, lsm, loi, oig, cookie,
808                                 cmd, off, count, brw_flags,
809                                 async_flags);
810         RETURN(rc);
811 }
812
813 static int cobd_dt_trigger_group_io(struct obd_export *exp, 
814                                     struct lov_stripe_md *lsm, 
815                                     struct lov_oinfo *loi,
816                                     struct obd_io_group *oig)
817 {
818         struct obd_device *obd = class_exp2obd(exp);
819         struct obd_export *cobd_exp;
820         int rc = 0;
821         ENTRY;
822
823         if (obd == NULL) {
824                 CERROR("invalid client cookie "LPX64"\n", 
825                        exp->exp_handle.h_cookie);
826                 RETURN(-EINVAL);
827         }
828         cobd_exp = cobd_get_exp(obd);
829         rc = obd_trigger_group_io(cobd_exp, lsm, loi, oig);
830         RETURN(rc);
831 }
832
833 static int cobd_dt_teardown_async_page(struct obd_export *exp,
834                                        struct lov_stripe_md *lsm,
835                                        struct lov_oinfo *loi,
836                                        void *cookie)
837 {
838         struct obd_device *obd = class_exp2obd(exp);
839         struct obd_export *cobd_exp;
840         int rc = 0;
841         ENTRY;
842
843         if (obd == NULL) {
844                 CERROR("invalid client cookie "LPX64"\n", 
845                        exp->exp_handle.h_cookie);
846                 RETURN(-EINVAL);
847         }
848         cobd_exp = cobd_get_exp(obd);
849         rc = obd_teardown_async_page(cobd_exp, lsm, loi, cookie);
850         RETURN(rc);
851 }
852
853 static int cobd_dt_punch(struct obd_export *exp, struct obdo *oa,
854                          struct lov_stripe_md *ea, obd_size start,
855                          obd_size end, struct obd_trans_info *oti)
856 {
857         struct obd_device *obd = class_exp2obd(exp);
858         struct obd_export *cobd_exp;
859         int rc = 0;
860         ENTRY;
861
862         if (obd == NULL) {
863                 CERROR("invalid client cookie "LPX64"\n", 
864                        exp->exp_handle.h_cookie);
865                 RETURN(-EINVAL);
866         }
867         cobd_exp = cobd_get_exp(obd);
868         rc = obd_punch(cobd_exp, oa, ea, start, end, oti);
869         RETURN(rc);
870 }
871
872 static int cobd_dt_sync(struct obd_export *exp, struct obdo *oa,
873                         struct lov_stripe_md *ea, obd_size start, 
874                         obd_size end)
875 {
876         struct obd_device *obd = class_exp2obd(exp);
877         struct obd_export *cobd_exp;
878         int rc = 0;
879         ENTRY;
880
881         if (obd == NULL) {
882                 CERROR("invalid client cookie "LPX64"\n", 
883                        exp->exp_handle.h_cookie);
884                 RETURN(-EINVAL);
885         }
886         cobd_exp = cobd_get_exp(obd);
887         rc = obd_sync(cobd_exp, oa, ea, start, end);
888         RETURN(rc);
889 }
890
891 static int cobd_dt_enqueue(struct obd_export *exp, struct lov_stripe_md *ea,
892                            __u32 type, ldlm_policy_data_t *policy,
893                            __u32 mode, int *flags, void *bl_cb, void *cp_cb,
894                            void *gl_cb, void *data, __u32 lvb_len,
895                            void *lvb_swabber, struct lustre_handle *lockh)
896 {
897         struct obd_device *obd = class_exp2obd(exp);
898         struct obd_export *cobd_exp;
899         int rc = 0;
900         ENTRY;
901
902         if (obd == NULL) {
903                 CERROR("invalid client cookie "LPX64"\n", 
904                        exp->exp_handle.h_cookie);
905                 RETURN(-EINVAL);
906         }
907         cobd_exp = cobd_get_exp(obd);
908         rc = obd_enqueue(cobd_exp, ea, type, policy, mode, flags, 
909                          bl_cb, cp_cb, gl_cb, data, lvb_len,
910                          lvb_swabber, lockh);
911         RETURN(rc);
912 }
913
914 static int cobd_dt_match(struct obd_export *exp, struct lov_stripe_md *ea,
915                          __u32 type, ldlm_policy_data_t *policy, __u32 mode,
916                          int *flags, void *data, struct lustre_handle *lockh)
917 {
918         struct obd_device *obd = class_exp2obd(exp);
919         struct obd_export *cobd_exp;
920         int rc = 0;
921         ENTRY;
922
923         if (obd == NULL) {
924                 CERROR("invalid client cookie "LPX64"\n", 
925                        exp->exp_handle.h_cookie);
926                 RETURN(-EINVAL);
927         }
928         cobd_exp = cobd_get_exp(obd);
929         rc = obd_match(cobd_exp, ea, type, policy, mode, flags,
930                        data, lockh);
931         RETURN(rc);
932 }
933 static int cobd_dt_change_cbdata(struct obd_export *exp,
934                                  struct lov_stripe_md *lsm, 
935                                  ldlm_iterator_t it, void *data)
936 {
937         struct obd_device *obd = class_exp2obd(exp);
938         struct obd_export *cobd_exp;
939         int rc = 0;
940         ENTRY;
941
942         if (obd == NULL) {
943                 CERROR("invalid client cookie "LPX64"\n", 
944                        exp->exp_handle.h_cookie);
945                 RETURN(-EINVAL);
946         }
947         cobd_exp = cobd_get_exp(obd);
948         rc = obd_change_cbdata(cobd_exp, lsm, it, data);
949         RETURN(rc);
950 }
951
952 static int cobd_dt_cancel(struct obd_export *exp,
953                           struct lov_stripe_md *ea, __u32 mode,
954                           struct lustre_handle *lockh)
955 {
956         struct obd_device *obd = class_exp2obd(exp);
957         struct obd_export *cobd_exp;
958         int rc = 0;
959         ENTRY;
960
961         if (obd == NULL) {
962                 CERROR("invalid client cookie "LPX64"\n", 
963                        exp->exp_handle.h_cookie);
964                 RETURN(-EINVAL);
965         }
966         cobd_exp = cobd_get_exp(obd);
967         rc = obd_cancel(cobd_exp, ea, mode, lockh);
968         RETURN(rc);
969 }
970
971 static int cobd_dt_cancel_unused(struct obd_export *exp,
972                                  struct lov_stripe_md *ea,
973                                  int flags, void *opaque)
974 {
975         struct obd_device *obd = class_exp2obd(exp);
976         struct obd_export *cobd_exp;
977         int rc = 0;
978         ENTRY;
979         
980         if (obd == NULL) {
981                 CERROR("invalid client cookie "LPX64"\n", 
982                        exp->exp_handle.h_cookie);
983                 RETURN(-EINVAL);
984         }
985         cobd_exp = cobd_get_exp(obd);
986         rc = obd_cancel_unused(cobd_exp, ea, flags, opaque);
987         RETURN(rc);
988 }
989
990 static int cobd_dt_preprw(int cmd, struct obd_export *exp,
991                           struct obdo *oa, int objcount,
992                           struct obd_ioobj *obj, int niocount,
993                           struct niobuf_remote *nb,
994                           struct niobuf_local *res,
995                           struct obd_trans_info *oti)
996 {
997         struct obd_device *obd = class_exp2obd(exp);
998         struct obd_export *cobd_exp;
999         int rc = 0;
1000         ENTRY;
1001
1002         if (obd == NULL) {
1003                 CERROR("invalid client cookie "LPX64"\n", 
1004                        exp->exp_handle.h_cookie);
1005                 RETURN(-EINVAL);
1006         }
1007         cobd_exp = cobd_get_exp(obd);
1008         rc = obd_preprw(cmd, cobd_exp, oa, objcount, obj,
1009                         niocount, nb, res, oti);
1010         RETURN(rc);
1011 }
1012
1013 static int cobd_dt_commitrw(int cmd, struct obd_export *exp, struct obdo *oa,
1014                             int objcount, struct obd_ioobj *obj,
1015                             int niocount, struct niobuf_local *local,
1016                             struct obd_trans_info *oti, int rc)
1017 {
1018         struct obd_device *obd = class_exp2obd(exp);
1019         struct obd_export *cobd_exp;
1020         int err = 0;
1021         ENTRY;
1022
1023         if (obd == NULL) {
1024                 CERROR("invalid client cookie "LPX64"\n", 
1025                        exp->exp_handle.h_cookie);
1026                 RETURN(-EINVAL);
1027         }
1028         cobd_exp = cobd_get_exp(obd);
1029         err = obd_commitrw(cmd, cobd_exp, oa, objcount, obj,
1030                            niocount, local, oti, rc);
1031         RETURN(err);
1032 }
1033
1034 static int cobd_dt_adjust_kms(struct obd_export *exp,
1035                               struct lov_stripe_md *lsm,
1036                               obd_off size, int shrink)
1037 {
1038         struct obd_device *obd = class_exp2obd(exp);
1039         struct obd_export *cobd_exp;
1040         int rc = 0;
1041         ENTRY;
1042
1043         if (obd == NULL) {
1044                 CERROR("invalid client cookie "LPX64"\n", 
1045                        exp->exp_handle.h_cookie);
1046                 RETURN(-EINVAL);
1047         }
1048         cobd_exp = cobd_get_exp(obd);
1049         rc = obd_adjust_kms(cobd_exp, lsm, size, shrink);
1050         
1051         RETURN(rc);
1052 }
1053
1054 static int cobd_dt_llog_init(struct obd_device *obd,
1055                              struct obd_llogs *llogs, 
1056                              struct obd_device *disk_obd,
1057                              int count, struct llog_catid *logid)
1058 {
1059         struct obd_export *cobd_exp;
1060         struct obd_device *cobd_obd;
1061         int rc = 0;
1062         ENTRY;
1063
1064         cobd_exp = cobd_get_exp(obd);
1065         cobd_obd = class_exp2obd(cobd_exp);
1066         
1067         rc = obd_llog_init(cobd_obd, &cobd_obd->obd_llogs, 
1068                            disk_obd, count, logid);
1069         RETURN(rc);
1070 }
1071
1072 static int cobd_dt_llog_finish(struct obd_device *obd,
1073                                struct obd_llogs *llogs, 
1074                                int count)
1075 {
1076         struct obd_export *cobd_exp;
1077         struct obd_device *cobd_obd;
1078         int rc = 0;
1079         ENTRY;
1080
1081         cobd_exp = cobd_get_exp(obd);
1082         cobd_obd = class_exp2obd(cobd_exp);
1083
1084         rc = obd_llog_finish(cobd_obd, &cobd_obd->obd_llogs, count);
1085         RETURN(rc);
1086 }
1087
1088 static int cobd_dt_notify(struct obd_device *obd, struct obd_device *watched,
1089                           int active, void *data)
1090 {
1091         struct obd_export *cobd_exp;
1092         int rc = 0;
1093         ENTRY;
1094
1095         cobd_exp = cobd_get_exp(obd);
1096         rc = obd_notify(class_exp2obd(cobd_exp), watched, active, data);
1097         RETURN(rc);
1098 }
1099
1100 static int cobd_dt_pin(struct obd_export *exp, obd_id ino, __u32 gen,
1101                        int type, struct obd_client_handle *handle,
1102                        int flag)
1103 {
1104         struct obd_device *obd = class_exp2obd(exp);
1105         struct obd_export *cobd_exp;
1106         int rc = 0;
1107         ENTRY;
1108
1109         if (obd == NULL) {
1110                 CERROR("invalid client cookie "LPX64"\n", 
1111                        exp->exp_handle.h_cookie);
1112                 RETURN(-EINVAL);
1113         }
1114         cobd_exp = cobd_get_exp(obd);
1115         rc = obd_pin(cobd_exp, ino, gen, type, handle, flag);
1116         RETURN(rc);
1117 }
1118
1119 static int cobd_dt_unpin(struct obd_export *exp,
1120                          struct obd_client_handle *handle,
1121                          int flag)
1122 {
1123         struct obd_device *obd = class_exp2obd(exp);
1124         struct obd_export *cobd_exp;
1125         int rc = 0;
1126         ENTRY;
1127
1128         if (obd == NULL) {
1129                 CERROR("invalid client cookie "LPX64"\n", 
1130                        exp->exp_handle.h_cookie);
1131                 RETURN(-EINVAL);
1132         }
1133         cobd_exp = cobd_get_exp(obd);
1134         rc = obd_unpin(cobd_exp, handle, flag);
1135         RETURN(rc);
1136 }
1137
1138 static int cobd_dt_init_ea_size(struct obd_export *exp, int easize,
1139                                 int cookiesize)
1140 {
1141         struct obd_export *cobd_exp;
1142         int rc = 0;
1143         ENTRY;
1144
1145         cobd_exp = cobd_get_exp(exp->exp_obd);
1146         rc = obd_init_ea_size(cobd_exp, easize, cookiesize);
1147         RETURN(rc);
1148 }
1149
1150 static int cobd_dt_import_event(struct obd_device *obd,
1151                                 struct obd_import *imp,
1152                                 enum obd_import_event event)
1153 {
1154         struct obd_export *cobd_exp;
1155         ENTRY;
1156
1157         cobd_exp = cobd_get_exp(obd);
1158         obd_import_event(class_exp2obd(cobd_exp), imp, event);
1159         RETURN(0); 
1160 }
1161
1162 static int cobd_md_getstatus(struct obd_export *exp,
1163                              struct lustre_id *rootid)
1164 {
1165         struct obd_device *obd = class_exp2obd(exp);
1166         struct obd_export *cobd_exp;
1167         int rc = 0;
1168         ENTRY;
1169
1170         if (obd == NULL) {
1171                 CERROR("invalid client cookie "LPX64"\n", 
1172                        exp->exp_handle.h_cookie);
1173                 RETURN(-EINVAL);
1174         }
1175         cobd_exp = cobd_get_exp(obd);
1176         rc = md_getstatus(cobd_exp, rootid);
1177         RETURN(rc);
1178 }
1179
1180 static int cobd_md_getattr(struct obd_export *exp, struct lustre_id *id,
1181                            __u64 valid, const char *xattr_name,
1182                            const void *xattr_data, unsigned int xattr_datalen,
1183                            unsigned int ea_size,
1184                            struct ptlrpc_request **request)
1185 {
1186         struct obd_device *obd = class_exp2obd(exp);
1187         struct obd_export *cobd_exp;
1188         int rc = 0;
1189         ENTRY;
1190
1191         if (obd == NULL) {
1192                 CERROR("invalid client cookie "LPX64"\n", 
1193                        exp->exp_handle.h_cookie);
1194                 RETURN(-EINVAL);
1195         }
1196         cobd_exp = cobd_get_exp(obd);
1197         rc = md_getattr(cobd_exp, id, valid, xattr_name,
1198                         xattr_data, xattr_datalen, ea_size, request);
1199         RETURN(rc);
1200 }
1201
1202 static int cobd_md_req2lustre_md(struct obd_export *mdc_exp, 
1203                                  struct ptlrpc_request *req,
1204                                  unsigned int offset,
1205                                  struct obd_export *osc_exp,
1206                                  struct lustre_md *md)
1207 {
1208         struct obd_device *obd = class_exp2obd(mdc_exp);
1209         struct obd_export *cobd_exp;
1210         int rc = 0;
1211         ENTRY;
1212
1213         if (obd == NULL) {
1214                 CERROR("invalid client cookie "LPX64"\n", 
1215                        mdc_exp->exp_handle.h_cookie);
1216                 RETURN(-EINVAL);
1217         }
1218         cobd_exp = cobd_get_exp(obd);
1219         rc = md_req2lustre_md(cobd_exp, req, offset, osc_exp, md);
1220         RETURN(rc);
1221 }
1222
1223 static int cobd_md_change_cbdata(struct obd_export *exp, struct lustre_id *id, 
1224                                  ldlm_iterator_t it, void *data)
1225 {
1226         struct obd_device *obd = class_exp2obd(exp);
1227         struct obd_export *cobd_exp;
1228         int rc = 0;
1229         ENTRY;
1230
1231         if (obd == NULL) {
1232                 CERROR("invalid client cookie "LPX64"\n", 
1233                        exp->exp_handle.h_cookie);
1234                 RETURN(-EINVAL);
1235         }
1236         cobd_exp = cobd_get_exp(obd);
1237         rc = md_change_cbdata(cobd_exp, id, it, data);
1238         RETURN(rc);
1239 }
1240
1241 static int cobd_md_getattr_lock(struct obd_export *exp, struct lustre_id *id,
1242                                 char *filename, int namelen, __u64 valid,
1243                                 unsigned int ea_size, struct ptlrpc_request **request)
1244 {
1245         struct obd_device *obd = class_exp2obd(exp);
1246         struct obd_export *cobd_exp;
1247         int rc = 0;
1248         ENTRY;
1249
1250         if (obd == NULL) {
1251                 CERROR("invalid client cookie "LPX64"\n", 
1252                        exp->exp_handle.h_cookie);
1253                 RETURN(-EINVAL);
1254         }
1255         cobd_exp = cobd_get_exp(obd);
1256         rc = md_getattr_lock(cobd_exp, id, filename, namelen,
1257                              valid, ea_size, request);
1258         RETURN(rc);
1259 }
1260
1261 static int cobd_md_create(struct obd_export *exp, struct mdc_op_data *op_data,
1262                           const void *data, int datalen, int mode, 
1263                           __u32 uid, __u32 gid, __u64 rdev, 
1264                           struct ptlrpc_request **request)
1265 {
1266         struct obd_device *obd = class_exp2obd(exp);
1267         struct obd_export *cobd_exp;
1268         int rc = 0;
1269         ENTRY;
1270
1271         if (obd == NULL) {
1272                 CERROR("invalid client cookie "LPX64"\n", 
1273                        exp->exp_handle.h_cookie);
1274                 RETURN(-EINVAL);
1275         }
1276         cobd_exp = cobd_get_exp(obd);
1277         rc = md_create(cobd_exp, op_data, data, datalen, mode,
1278                        uid, gid, rdev, request);
1279         RETURN(rc);
1280 }
1281
1282 static int cobd_md_unlink(struct obd_export *exp,
1283                           struct mdc_op_data *data,
1284                           struct ptlrpc_request **request)
1285 {
1286         struct obd_device *obd = class_exp2obd(exp);
1287         struct obd_export *cobd_exp;
1288         int rc = 0;
1289         ENTRY;
1290
1291         if (obd == NULL) {
1292                 CERROR("invalid client cookie "LPX64"\n", 
1293                        exp->exp_handle.h_cookie);
1294                 RETURN(-EINVAL);
1295         }
1296         cobd_exp = cobd_get_exp(obd);
1297         rc = md_unlink(cobd_exp, data, request);
1298         RETURN(rc);
1299 }
1300
1301 static int cobd_md_valid_attrs(struct obd_export *exp,
1302                                struct lustre_id *id)
1303 {
1304         struct obd_device *obd = class_exp2obd(exp);
1305         struct obd_export *cobd_exp;
1306         int rc = 0;
1307         ENTRY;
1308
1309         if (obd == NULL) {
1310                 CERROR("invalid client cookie "LPX64"\n", 
1311                        exp->exp_handle.h_cookie);
1312                 RETURN(-EINVAL);
1313         }
1314         cobd_exp = cobd_get_exp(obd);
1315         rc = md_valid_attrs(cobd_exp, id);
1316         RETURN(rc);
1317 }
1318
1319 static int cobd_md_rename(struct obd_export *exp, struct mdc_op_data *data,
1320                           const char *old, int oldlen, const char *new, 
1321                           int newlen, struct ptlrpc_request **request)
1322 {
1323         struct obd_device *obd = class_exp2obd(exp);
1324         struct obd_export *cobd_exp;
1325         int rc = 0;
1326         ENTRY;
1327
1328         if (obd == NULL) {
1329                 CERROR("invalid client cookie "LPX64"\n", 
1330                        exp->exp_handle.h_cookie);
1331                 RETURN(-EINVAL);
1332         }
1333         cobd_exp = cobd_get_exp(obd);
1334         rc = md_rename(cobd_exp, data, old, oldlen, new, newlen, request);
1335         RETURN(rc);
1336 }
1337
1338 static int cobd_md_link(struct obd_export *exp, struct mdc_op_data *data,
1339                         struct ptlrpc_request **request)
1340 {
1341         struct obd_device *obd = class_exp2obd(exp);
1342         struct obd_export *cobd_exp;
1343         int rc = 0;
1344         ENTRY;
1345
1346         if (obd == NULL) {
1347                 CERROR("invalid client cookie "LPX64"\n", 
1348                        exp->exp_handle.h_cookie);
1349                 RETURN(-EINVAL);
1350         }
1351         cobd_exp = cobd_get_exp(obd);
1352         rc = md_link(cobd_exp, data, request);
1353         RETURN(rc);
1354 }
1355
1356 static int cobd_md_setattr(struct obd_export *exp, struct mdc_op_data *data,
1357                            struct iattr *iattr, void *ea, int ealen, void *ea2, 
1358                            int ea2len, void *ea3, int ea3len, 
1359                            struct ptlrpc_request **request)
1360 {
1361         struct obd_device *obd = class_exp2obd(exp);
1362         struct obd_export *cobd_exp;
1363         int rc = 0;
1364         ENTRY;
1365
1366         if (obd == NULL) {
1367                 CERROR("invalid client cookie "LPX64"\n", 
1368                        exp->exp_handle.h_cookie);
1369                 RETURN(-EINVAL);
1370         }
1371         cobd_exp = cobd_get_exp(obd);
1372         rc = md_setattr(cobd_exp, data, iattr, ea,
1373                           ealen, ea2, ea2len, ea3, ea3len, request);
1374         RETURN(rc);
1375 }
1376
1377 static int cobd_md_readpage(struct obd_export *exp,
1378                             struct lustre_id *mdc_id,
1379                             __u64 offset, struct page *page, 
1380                             struct ptlrpc_request **request)
1381 {
1382         struct obd_device *obd = class_exp2obd(exp);
1383         struct obd_export *cobd_exp;
1384         int rc = 0;
1385         ENTRY;
1386
1387         if (obd == NULL) {
1388                 CERROR("invalid client cookie "LPX64"\n", 
1389                        exp->exp_handle.h_cookie);
1390                 RETURN(-EINVAL);
1391         }
1392         cobd_exp = cobd_get_exp(obd);
1393         rc = md_readpage(cobd_exp, mdc_id, offset, page, request);
1394         RETURN(rc);
1395 }
1396
1397 static int cobd_md_close(struct obd_export *exp, struct obdo *obdo,
1398                          struct obd_client_handle *och, 
1399                          struct ptlrpc_request **request)
1400 {
1401         struct obd_device *obd = class_exp2obd(exp);
1402         struct obd_export *cobd_exp;
1403         int rc = 0;
1404         ENTRY;
1405
1406         if (obd == NULL) {
1407                 CERROR("invalid client cookie "LPX64"\n", 
1408                        exp->exp_handle.h_cookie);
1409                 RETURN(-EINVAL);
1410         }
1411         cobd_exp = cobd_get_exp(obd);
1412         rc = md_close(cobd_exp, obdo, och, request);
1413         RETURN(rc);
1414 }
1415
1416 static int cobd_md_done_writing(struct obd_export *exp,
1417                                 struct obdo *obdo)
1418 {
1419         struct obd_device *obd = class_exp2obd(exp);
1420         struct obd_export *cobd_exp;
1421         int rc = 0;
1422         ENTRY;
1423
1424         if (obd == NULL) {
1425                 CERROR("invalid client cookie "LPX64"\n", 
1426                        exp->exp_handle.h_cookie);
1427                 RETURN(-EINVAL);
1428         }
1429         cobd_exp = cobd_get_exp(obd);
1430         rc = md_done_writing(cobd_exp, obdo);
1431         RETURN(rc);
1432 }
1433
1434 static int cobd_md_sync(struct obd_export *exp, struct lustre_id *id,
1435                         struct ptlrpc_request **request)
1436 {
1437         struct obd_device *obd = class_exp2obd(exp);
1438         struct obd_export *cobd_exp;
1439         int rc = 0;
1440         ENTRY;
1441
1442         if (obd == NULL) {
1443                 CERROR("invalid client cookie "LPX64"\n", 
1444                        exp->exp_handle.h_cookie);
1445                 RETURN(-EINVAL);
1446         }
1447         cobd_exp = cobd_get_exp(obd);
1448         rc = md_sync(cobd_exp, id, request);
1449         RETURN(rc);
1450 }
1451
1452 static int cobd_md_set_open_replay_data(struct obd_export *exp,
1453                                         struct obd_client_handle *och,
1454                                         struct ptlrpc_request *open_req)
1455 {
1456         struct obd_device *obd = class_exp2obd(exp);
1457         struct obd_export *cobd_exp;
1458         int rc = 0;
1459         ENTRY;
1460
1461         if (obd == NULL) {
1462                 CERROR("invalid client cookie "LPX64"\n", 
1463                        exp->exp_handle.h_cookie);
1464                 RETURN(-EINVAL);
1465         }
1466         cobd_exp = cobd_get_exp(obd);
1467         rc = md_set_open_replay_data(cobd_exp, och, open_req);
1468         RETURN(rc);
1469 }
1470
1471 static int cobd_md_clear_open_replay_data(struct obd_export *exp,
1472                                           struct obd_client_handle *och)
1473 {
1474         struct obd_device *obd = class_exp2obd(exp);
1475         struct obd_export *cobd_exp;
1476         int rc = 0;
1477         ENTRY;
1478
1479         if (obd == NULL) {
1480                 CERROR("invalid client cookie "LPX64"\n", 
1481                        exp->exp_handle.h_cookie);
1482                 RETURN(-EINVAL);
1483         }
1484         cobd_exp = cobd_get_exp(obd);
1485         rc = md_clear_open_replay_data(cobd_exp, och);
1486         RETURN(rc);
1487 }
1488
1489 static int cobd_md_store_inode_generation(struct obd_export *exp,
1490                                           struct ptlrpc_request *req, 
1491                                           int reqoff, int repoff)
1492 {
1493         struct obd_device *obd = class_exp2obd(exp);
1494         struct obd_export *cobd_exp;
1495         int rc = 0;
1496         ENTRY;
1497
1498         if (obd == NULL) {
1499                 CERROR("invalid client cookie "LPX64"\n", 
1500                        exp->exp_handle.h_cookie);
1501                 RETURN(-EINVAL);
1502         }
1503         cobd_exp = cobd_get_exp(obd);
1504         rc = md_store_inode_generation(cobd_exp, req, reqoff, repoff);
1505         RETURN(rc);
1506 }
1507
1508 static int cobd_md_set_lock_data(struct obd_export *exp,
1509                                  __u64 *l, void *data)
1510 {
1511         struct obd_device *obd = class_exp2obd(exp);
1512         struct obd_export *cobd_exp;
1513         int rc = 0;
1514         ENTRY;
1515
1516         if (obd == NULL) {
1517                 CERROR("invalid client cookie "LPX64"\n", 
1518                        exp->exp_handle.h_cookie);
1519                 RETURN(-EINVAL);
1520         }
1521         cobd_exp = cobd_get_exp(obd);
1522         rc = md_set_lock_data(cobd_exp, l, data);
1523         RETURN(rc);
1524 }
1525
1526 static int cobd_md_enqueue(struct obd_export *exp, int lock_type,
1527                            struct lookup_intent *it, int lock_mode,
1528                            struct mdc_op_data *data, struct lustre_handle *lockh,
1529                            void *lmm, int lmmsize, 
1530                            ldlm_completion_callback cb_completion,
1531                            ldlm_blocking_callback cb_blocking, void *cb_data)
1532 {
1533         struct obd_device *obd = class_exp2obd(exp);
1534         struct obd_export *cobd_exp;
1535         int rc = 0;
1536         ENTRY;
1537
1538         if (obd == NULL) {
1539                 CERROR("invalid client cookie "LPX64"\n", 
1540                        exp->exp_handle.h_cookie);
1541                 RETURN(-EINVAL);
1542         }
1543         cobd_exp = cobd_get_exp(obd);
1544         rc = md_enqueue(cobd_exp, lock_type, it, lock_mode, data,
1545                         lockh, lmm, lmmsize, cb_completion, cb_blocking,
1546                         cb_data);
1547         RETURN(rc);
1548 }
1549
1550 static int cobd_md_intent_lock(struct obd_export *exp, struct lustre_id *pid, 
1551                                const char *name, int len, void *lmm, int lmmsize,
1552                                struct lustre_id *cid, struct lookup_intent *it,
1553                                int lookup_flags, struct ptlrpc_request **reqp,
1554                                ldlm_blocking_callback cb_blocking)
1555 {
1556         struct obd_device *obd = class_exp2obd(exp);
1557         struct obd_export *cobd_exp;
1558         int rc = 0;
1559         ENTRY;
1560
1561         if (obd == NULL) {
1562                 CERROR("invalid client cookie "LPX64"\n", 
1563                        exp->exp_handle.h_cookie);
1564                 RETURN(-EINVAL);
1565         }
1566         lookup_flags |= LOOKUP_COBD;
1567         cobd_exp = cobd_get_exp(obd);
1568         
1569         rc = md_intent_lock(cobd_exp, pid, name, len, lmm, lmmsize,
1570                             cid, it, lookup_flags, reqp, cb_blocking);
1571         RETURN(rc);
1572 }
1573
1574 static struct obd_device *cobd_md_get_real_obd(struct obd_export *exp,
1575                                                struct lustre_id *id)
1576 {
1577         struct obd_device *obd = class_exp2obd(exp);
1578         struct obd_export *cobd_exp;
1579         ENTRY;
1580
1581         if (obd == NULL) {
1582                 CERROR("invalid client cookie "LPX64"\n", 
1583                        exp->exp_handle.h_cookie);
1584                 RETURN(NULL);
1585         }
1586         cobd_exp = cobd_get_exp(obd);
1587         RETURN(md_get_real_obd(cobd_exp, id));
1588 }
1589
1590 static int cobd_md_change_cbdata_name(struct obd_export *exp,
1591                                       struct lustre_id *id, char *name,
1592                                       int namelen, struct lustre_id *id2,
1593                                       ldlm_iterator_t it, void *data)
1594 {
1595         struct obd_device *obd = class_exp2obd(exp);
1596         struct obd_export *cobd_exp;
1597         int rc = 0;
1598
1599         if (obd == NULL) {
1600                 CERROR("invalid client cookie "LPX64"\n", 
1601                        exp->exp_handle.h_cookie);
1602                 RETURN(-EINVAL);
1603         }
1604         cobd_exp = cobd_get_exp(obd);
1605         rc = md_change_cbdata_name(cobd_exp, id, name, namelen,
1606                                    id2, it, data);
1607         RETURN(rc);
1608 }
1609
1610 static struct obd_ops cobd_obd_ops = {
1611         .o_owner                  = THIS_MODULE,
1612         .o_attach                 = cobd_attach,
1613         .o_detach                 = cobd_detach,
1614         .o_setup                  = cobd_setup,
1615         .o_cleanup                = cobd_cleanup,
1616         .o_connect                = cobd_connect,
1617         .o_disconnect             = cobd_disconnect,
1618         .o_set_info               = cobd_set_info,
1619         .o_get_info               = cobd_get_info,
1620         .o_statfs                 = cobd_statfs,
1621         .o_iocontrol              = cobd_iocontrol,
1622
1623         .o_packmd                 = cobd_dt_packmd,
1624         .o_unpackmd               = cobd_dt_unpackmd,
1625         .o_create                 = cobd_dt_create,
1626         .o_destroy                = cobd_dt_destroy,
1627         .o_precleanup             = cobd_dt_precleanup,
1628         .o_getattr                = cobd_dt_getattr,
1629         .o_getattr_async          = cobd_dt_getattr_async,
1630         .o_setattr                = cobd_dt_setattr,
1631         .o_brw                    = cobd_dt_brw,
1632         .o_brw_async              = cobd_dt_brw_async,
1633         .o_prep_async_page        = cobd_dt_prep_async_page,
1634         .o_queue_async_io         = cobd_dt_queue_async_io,
1635         .o_set_async_flags        = cobd_dt_set_async_flags,
1636         .o_queue_group_io         = cobd_dt_queue_group_io,
1637         .o_trigger_group_io       = cobd_dt_trigger_group_io,
1638         .o_teardown_async_page    = cobd_dt_teardown_async_page,
1639         .o_preprw                 = cobd_dt_preprw,
1640         .o_punch                  = cobd_dt_punch,
1641         .o_sync                   = cobd_dt_sync,
1642         .o_enqueue                = cobd_dt_enqueue,
1643         .o_match                  = cobd_dt_match,
1644         .o_change_cbdata          = cobd_dt_change_cbdata,
1645         .o_cancel                 = cobd_dt_cancel,
1646         .o_cancel_unused          = cobd_dt_cancel_unused,
1647         .o_commitrw               = cobd_dt_commitrw,
1648         .o_llog_init              = cobd_dt_llog_init,
1649         .o_llog_finish            = cobd_dt_llog_finish,
1650         .o_notify                 = cobd_dt_notify,
1651         .o_pin                    = cobd_dt_pin,
1652         .o_unpin                  = cobd_dt_unpin,
1653         .o_import_event           = cobd_dt_import_event,
1654         .o_init_ea_size           = cobd_dt_init_ea_size,
1655         .o_adjust_kms             = cobd_dt_adjust_kms,
1656 };
1657
1658 struct md_ops cobd_md_ops = {
1659         .m_getstatus              = cobd_md_getstatus,
1660         .m_getattr                = cobd_md_getattr,
1661         .m_req2lustre_md          = cobd_md_req2lustre_md,
1662         .m_change_cbdata          = cobd_md_change_cbdata,
1663         .m_getattr_lock           = cobd_md_getattr_lock,
1664         .m_create                 = cobd_md_create,
1665         .m_unlink                 = cobd_md_unlink,
1666         .m_valid_attrs            = cobd_md_valid_attrs,
1667         .m_rename                 = cobd_md_rename,
1668         .m_link                   = cobd_md_link,
1669         .m_setattr                = cobd_md_setattr,
1670         .m_readpage               = cobd_md_readpage,
1671         .m_close                  = cobd_md_close,
1672         .m_done_writing           = cobd_md_done_writing,
1673         .m_sync                   = cobd_md_sync,
1674         .m_set_open_replay_data   = cobd_md_set_open_replay_data,
1675         .m_clear_open_replay_data = cobd_md_clear_open_replay_data,
1676         .m_store_inode_generation = cobd_md_store_inode_generation,
1677         .m_set_lock_data          = cobd_md_set_lock_data,
1678         .m_enqueue                = cobd_md_enqueue,
1679         .m_get_real_obd           = cobd_md_get_real_obd,
1680         .m_intent_lock            = cobd_md_intent_lock,
1681         .m_change_cbdata_name     = cobd_md_change_cbdata_name,
1682 };
1683
1684 static int __init cobd_init(void)
1685 {
1686         struct lprocfs_static_vars lvars;
1687         ENTRY;
1688
1689         printk(KERN_INFO "Lustre: Caching OBD driver; info@clusterfs.com\n");
1690
1691         lprocfs_init_vars(cobd, &lvars);
1692         RETURN(class_register_type(&cobd_obd_ops, &cobd_md_ops,
1693                                    lvars.module_vars, OBD_CACHE_DEVICENAME));
1694 }
1695
1696 static void /*__exit*/ cobd_exit(void)
1697 {
1698         class_unregister_type(OBD_CACHE_DEVICENAME);
1699 }
1700
1701 MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
1702 MODULE_DESCRIPTION("Lustre Caching OBD driver");
1703 MODULE_LICENSE("GPL");
1704
1705 module_init(cobd_init);
1706 module_exit(cobd_exit);