Whamcloud - gitweb
- generate capability in open resend case
[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 nothing 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_SWITCH  (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  *
318  * bias == COBD_SWITCH do both (disconnect old and connect new). This will also
319  * set ->cache_on  to passed @cache_on value.
320  */
321 static int cobd_switch(struct obd_device *obd,
322                        int cache_on, int bias)
323 {
324         struct cache_obd *cobd = &obd->u.cobd;
325         struct obd_device *cli_obd = NULL;
326         struct lustre_handle conn = {0,};
327         struct obd_export *discon_exp;
328         struct obd_export *conn_exp;
329         int rc = 0;
330         ENTRY;
331
332         if (cache_on) {
333                 discon_exp = cobd->master_real_exp;
334                 conn_exp = cobd->cache_exp;
335         } else {
336                 discon_exp = cobd->cache_real_exp;
337                 conn_exp = cobd->master_exp;
338         }
339
340         /* disconnect old export */
341         if (bias == COBD_SWITCH || bias == COBD_DISCON) {
342                 if (discon_exp) {
343                         rc = cobd_disconnect_client(obd, discon_exp, 0);
344                         if (rc) {
345                                 CWARN("can't disconnect export %p, err %d\n",
346                                       discon_exp, rc);
347                         }
348                 }
349                 
350                 if (cache_on)
351                         cobd->master_real_exp = NULL;
352                 else
353                         cobd->cache_real_exp = NULL; 
354         }
355
356         /* connect new export */
357         if (bias == COBD_SWITCH || bias == COBD_CONNECT) {
358                 int connected;
359
360                 connected = cache_on ? (cobd->cache_real_exp != NULL) :
361                         (cobd->master_real_exp != NULL);
362
363                 /* correct export already may be connected */
364                 if (!connected) {
365                         rc = cobd_connect_client(obd, conn_exp, &conn,
366                                                  NULL, OBD_OPT_REAL_CLIENT);
367                         if (rc) {
368                                 CERROR("can't connect export %p, err %d\n",
369                                        conn_exp, rc);
370                                 RETURN(rc);
371                         }
372
373                         if (cache_on) {
374                                 cobd->cache_real_exp = class_conn2export(&conn);
375                                 cli_obd = class_exp2obd(cobd->cache_exp);
376                         } else {
377                                 cobd->master_real_exp = class_conn2export(&conn);
378                                 cli_obd = class_exp2obd(cobd->master_exp);
379                         }
380
381                         /* change flag only if connect is allowed to keep
382                          * ->cache_on coherent with real export connected. */
383                         cobd->cache_on = cache_on;
384                 
385                         /* re-init EA size for new selected export. This should
386                          * be done after assigining new state to @cobd->cache_on
387                          * to not call disconnected old export. */
388                         if (obd_md_type(cli_obd)) {
389                                 rc = cobd_init_dt_desc(obd);
390                                 if (rc == 0) {
391                                         rc = cobd_init_ea_size(obd);
392                                         if (rc) {
393                                                 CERROR("can't initialize EA size, "
394                                                        "err %d\n", rc);
395                                         }
396                                 } else {
397                                         CERROR("can't initialize data lovdesc, "
398                                                "err %d\n", rc);
399                                         /* ignore cases when we did not manage
400                                          * to init lovdesc. This is because some
401                                          * devices may not know "lovdesc" info
402                                          * command. */
403                                         rc = 0;
404                                 }
405                         }
406                 }
407         }
408
409         RETURN(rc);
410 }
411
412 static int
413 cobd_connect(struct lustre_handle *conn, struct obd_device *obd,
414              struct obd_uuid *cluuid, struct obd_connect_data *data,
415              unsigned long flags)
416 {
417         struct cache_obd *cobd = &obd->u.cobd;
418         struct obd_export *exp;
419         int rc = 0;
420         ENTRY;
421
422         rc = class_connect(conn, obd, cluuid);
423         if (rc)
424                 RETURN(rc);
425
426         exp = class_conn2export(conn);
427         rc = cobd_switch(obd, cobd->cache_on,
428                          COBD_CONNECT);
429         if (rc)
430                 class_disconnect(exp, 0);
431         else
432                 class_export_put(exp);
433         RETURN(rc);
434 }
435
436 static int
437 cobd_disconnect(struct obd_export *exp, unsigned long flags)
438 {
439         struct cache_obd *cobd;
440         struct obd_device *obd;
441         int rc = 0;
442         ENTRY;
443         
444         LASSERT(exp != NULL);
445         obd = class_exp2obd(exp);
446         if (obd == NULL) {
447                 CDEBUG(D_IOCTL, "invalid client cookie "
448                        LPX64"\n", exp->exp_handle.h_cookie);
449                 RETURN(-EINVAL);
450         }
451
452         /* here would be nice also to check that disconnect goes to the same
453          * export as connect did. But as now we are accepting the notion that
454          * cache should be switched after client umount this is not needed.
455          * --umka. */
456         cobd = &obd->u.cobd;
457         rc = cobd_switch(obd, !cobd->cache_on, COBD_DISCON);
458         class_disconnect(exp, flags);
459
460         RETURN(rc);
461 }
462
463 static int cobd_get_info(struct obd_export *exp, __u32 keylen,
464                          void *key, __u32 *vallen, void *val)
465 {
466         struct obd_device *obd = class_exp2obd(exp);
467         struct obd_export *cobd_exp;
468         int rc = 0;
469         ENTRY;
470         
471         if (obd == NULL) {
472                 CERROR("invalid client cookie "LPX64"\n", 
473                        exp->exp_handle.h_cookie);
474                 RETURN(-EINVAL);
475         }
476         cobd_exp = cobd_get_exp(obd);
477
478         /* intercept cache utilisation info? */
479         rc = obd_get_info(cobd_exp, keylen, key, vallen, val);
480         RETURN(rc);
481 }
482
483 static int cobd_set_info(struct obd_export *exp, obd_count keylen,
484                          void *key, obd_count vallen, void *val)
485 {
486         struct obd_device *obd = class_exp2obd(exp);
487         struct obd_export *cobd_exp;
488         int rc = 0;
489         ENTRY;
490
491         if (obd == NULL) {
492                 CERROR("invalid client cookie "LPX64"\n", 
493                        exp->exp_handle.h_cookie);
494                 RETURN(-EINVAL);
495         }
496         cobd_exp = cobd_get_exp(obd);
497        
498         LASSERT(cobd_exp);
499         
500         /* intercept cache utilisation info? */
501         rc = obd_set_info(cobd_exp, keylen, key, vallen, val);
502         RETURN(rc);
503 }
504
505 static int cobd_statfs(struct obd_device *obd,
506                        struct obd_statfs *osfs,
507                        unsigned long max_age)
508 {
509         struct obd_export *cobd_exp;
510         int rc = 0;
511         ENTRY;
512
513         cobd_exp = cobd_get_exp(obd);
514         rc = obd_statfs(class_exp2obd(cobd_exp), osfs, max_age);
515         RETURN(rc);
516 }
517
518 static int cobd_iocontrol(unsigned int cmd, struct obd_export *exp,
519                           int len, void *karg, void *uarg)
520 {
521         struct obd_device *obd = class_exp2obd(exp);
522         struct cache_obd  *cobd = &obd->u.cobd;
523         struct obd_export *cobd_exp;
524         int rc = 0;
525         ENTRY;
526
527         down(&cobd->sem);
528         
529         /* here would be nice also to make sure somehow that there are no
530          * out-standing requests which go to wrong MDS after cache switch (close
531          * RPCs). But how to check that from COBD? I do not know. --umka */
532         switch (cmd) {
533         case OBD_IOC_COBD_CON:
534                 if (!cobd->cache_on)
535                         rc = cobd_switch(obd, 1, COBD_SWITCH);
536                 break;
537         case OBD_IOC_COBD_COFF: 
538                 if (cobd->cache_on)
539                         rc = cobd_switch(obd, 0, COBD_SWITCH);
540                 break;
541         default:
542                 cobd_exp = cobd_get_exp(obd);
543                 rc = obd_iocontrol(cmd, cobd_exp, len, karg, uarg);
544         }
545
546         up(&cobd->sem);
547         RETURN(rc);
548 }
549
550 static int cobd_notify(struct obd_device *obd, struct obd_device *watched,
551                        int active, void *data)
552 {
553         struct obd_export *cobd_exp;
554         int rc = 0;
555         ENTRY;
556
557         cobd_exp = cobd_get_exp(obd);
558         rc = obd_notify(class_exp2obd(cobd_exp), watched, active, data);
559         RETURN(rc);
560 }
561
562 static int cobd_pin(struct obd_export *exp, obd_id ino, __u32 gen,
563                     int type, struct obd_client_handle *handle,
564                     int flag)
565 {
566         struct obd_device *obd = class_exp2obd(exp);
567         struct obd_export *cobd_exp;
568         int rc = 0;
569         ENTRY;
570
571         if (obd == NULL) {
572                 CERROR("invalid client cookie "LPX64"\n", 
573                        exp->exp_handle.h_cookie);
574                 RETURN(-EINVAL);
575         }
576         cobd_exp = cobd_get_exp(obd);
577         rc = obd_pin(cobd_exp, ino, gen, type, handle, flag);
578         RETURN(rc);
579 }
580
581 static int cobd_unpin(struct obd_export *exp,
582                       struct obd_client_handle *handle,
583                       int flag)
584 {
585         struct obd_device *obd = class_exp2obd(exp);
586         struct obd_export *cobd_exp;
587         int rc = 0;
588         ENTRY;
589
590         if (obd == NULL) {
591                 CERROR("invalid client cookie "LPX64"\n", 
592                        exp->exp_handle.h_cookie);
593                 RETURN(-EINVAL);
594         }
595         cobd_exp = cobd_get_exp(obd);
596         rc = obd_unpin(cobd_exp, handle, flag);
597         RETURN(rc);
598 }
599
600 /* data related stuff */
601 static int cobd_dt_packmd(struct obd_export *exp,
602                           struct lov_mds_md **disk_tgt,
603                           struct lov_stripe_md *mem_src)
604 {
605         struct obd_device *obd = class_exp2obd(exp);
606         struct obd_export *cobd_exp;
607         int rc = 0;
608         ENTRY;
609
610         if (obd == NULL) {
611                 CERROR("invalid client cookie "LPX64"\n", 
612                        exp->exp_handle.h_cookie);
613                 RETURN(-EINVAL);
614         }
615         cobd_exp = cobd_get_exp(obd);
616         rc = obd_packmd(cobd_exp, disk_tgt, mem_src);
617         RETURN(rc);
618 }
619
620 static int cobd_dt_unpackmd(struct obd_export *exp,
621                             struct lov_stripe_md **mem_tgt,
622                             struct lov_mds_md *disk_src,
623                             int disk_len)
624 {
625         struct obd_device *obd = class_exp2obd(exp);
626         struct obd_export *cobd_exp;
627         int rc = 0;
628         ENTRY;
629
630         if (obd == NULL) {
631                 CERROR("invalid client cookie "LPX64"\n", 
632                        exp->exp_handle.h_cookie);
633                 RETURN(-EINVAL);
634         }
635         cobd_exp = cobd_get_exp(obd);
636         rc = obd_unpackmd(cobd_exp, mem_tgt, disk_src, disk_len);
637         RETURN(rc);
638 }
639
640 static int cobd_dt_create(struct obd_export *exp,
641                           struct obdo *obdo,
642                           void *acl, int acl_size,
643                           struct lov_stripe_md **ea,
644                           struct obd_trans_info *oti)
645 {
646         struct obd_device *obd = class_exp2obd(exp);
647         struct obd_export *cobd_exp;
648         int rc = 0;
649         ENTRY;
650
651         if (obd == NULL) {
652                 CERROR("invalid client cookie "LPX64"\n", 
653                        exp->exp_handle.h_cookie);
654                 RETURN(-EINVAL);
655         }
656         cobd_exp = cobd_get_exp(obd);
657         rc = obd_create(cobd_exp, obdo, acl, acl_size, ea, oti);
658         RETURN(rc);
659 }
660
661 static int cobd_dt_destroy(struct obd_export *exp,
662                            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_destroy(cobd_exp, obdo, ea, oti);
678         RETURN(rc);
679 }
680
681 static int cobd_dt_precleanup(struct obd_device *obd, int flags)
682 {
683         /* FIXME: do we need some cleanup here? */
684         ENTRY;
685         RETURN(0);
686 }
687
688 static int cobd_dt_getattr(struct obd_export *exp, struct obdo *oa,
689                            struct lov_stripe_md *ea)
690 {
691         struct obd_device *obd = class_exp2obd(exp);
692         struct obd_export *cobd_exp;
693         int rc = 0;
694         ENTRY;
695
696         if (obd == NULL) {
697                 CERROR("invalid client cookie "LPX64"\n", 
698                        exp->exp_handle.h_cookie);
699                 RETURN(-EINVAL);
700         }
701         cobd_exp = cobd_get_exp(obd);
702         rc = obd_getattr(cobd_exp, oa, ea);
703         RETURN(rc);
704 }
705
706 static int cobd_dt_getattr_async(struct obd_export *exp,
707                                  struct obdo *obdo, struct lov_stripe_md *ea,
708                                  struct ptlrpc_request_set *set)
709 {
710         struct obd_device *obd = class_exp2obd(exp);
711         struct obd_export *cobd_exp;
712         int rc = 0;
713         ENTRY;
714
715         if (obd == NULL) {
716                 CERROR("invalid client cookie "LPX64"\n", 
717                        exp->exp_handle.h_cookie);
718                 RETURN(-EINVAL);
719         }
720         cobd_exp = cobd_get_exp(obd);
721         rc = obd_getattr_async(cobd_exp, obdo, ea, set);
722         RETURN(rc);
723 }
724
725 static int cobd_dt_setattr(struct obd_export *exp, struct obdo *obdo,
726                            struct lov_stripe_md *ea,
727                            struct obd_trans_info *oti,
728                            struct lustre_capa *capa)
729 {
730         struct obd_device *obd = class_exp2obd(exp);
731         struct obd_export *cobd_exp;
732         int rc = 0;
733         ENTRY;
734
735         if (obd == NULL) {
736                 CERROR("invalid client cookie "LPX64"\n", 
737                        exp->exp_handle.h_cookie);
738                 RETURN(-EINVAL);
739         }
740         cobd_exp = cobd_get_exp(obd);
741         rc = obd_setattr(cobd_exp, obdo, ea, oti, capa);
742         RETURN(rc);
743 }
744
745 static int cobd_dt_brw(int cmd, struct obd_export *exp, struct obdo *oa,
746                        struct lov_stripe_md *ea, obd_count oa_bufs,
747                        struct brw_page *pg, struct obd_trans_info *oti)
748 {
749         struct obd_device *obd = class_exp2obd(exp);
750         struct obd_export *cobd_exp;
751         int rc = 0;
752         ENTRY;
753
754         if (obd == NULL) {
755                 CERROR("invalid client cookie "LPX64"\n", 
756                        exp->exp_handle.h_cookie);
757                 RETURN(-EINVAL);
758         }
759         cobd_exp = cobd_get_exp(obd);
760         rc = obd_brw(cmd, cobd_exp, oa, ea, oa_bufs, pg, oti);
761         RETURN(rc);
762 }
763
764 static int cobd_dt_brw_async(int cmd, struct obd_export *exp,
765                              struct obdo *oa, struct lov_stripe_md *ea,
766                              obd_count oa_bufs, struct brw_page *pg,
767                              struct ptlrpc_request_set *set,
768                              struct obd_trans_info *oti)
769 {
770         struct obd_device *obd = class_exp2obd(exp);
771         struct obd_export *cobd_exp;
772         int rc = 0;
773         ENTRY;
774
775         if (obd == NULL) {
776                 CERROR("invalid client cookie "LPX64"\n", 
777                        exp->exp_handle.h_cookie);
778                 RETURN(-EINVAL);
779         }
780         cobd_exp = cobd_get_exp(obd);
781         rc = obd_brw_async(cmd, cobd_exp, oa, ea, oa_bufs, 
782                            pg, set, oti);
783         RETURN(rc);
784 }
785
786 static int cobd_dt_prep_async_page(struct obd_export *exp, 
787                                    struct lov_stripe_md *lsm,
788                                    struct lov_oinfo *loi, 
789                                    struct page *page, obd_off offset, 
790                                    struct obd_async_page_ops *ops, 
791                                    void *data, void **res)
792 {
793         struct obd_device *obd = class_exp2obd(exp);
794         struct obd_export *cobd_exp;
795         int rc = 0;
796         ENTRY;
797
798         if (obd == NULL) {
799                 CERROR("invalid client cookie "LPX64"\n", 
800                        exp->exp_handle.h_cookie);
801                 RETURN(-EINVAL);
802         }
803         cobd_exp = cobd_get_exp(obd);
804         rc = obd_prep_async_page(cobd_exp, lsm, loi, page,
805                                  offset, ops, data, res);
806         RETURN(rc);
807 }
808
809 static int cobd_dt_queue_async_io(struct obd_export *exp,
810                                   struct lov_stripe_md *lsm,
811                                   struct lov_oinfo *loi, void *cookie,
812                                   int cmd, obd_off off, int count,
813                                   obd_flags brw_flags, obd_flags async_flags)
814 {
815         struct obd_device *obd = class_exp2obd(exp);
816         struct obd_export *cobd_exp;
817         int rc = 0;
818         ENTRY;
819
820         if (obd == NULL) {
821                 CERROR("invalid client cookie "LPX64"\n", 
822                        exp->exp_handle.h_cookie);
823                 RETURN(-EINVAL);
824         }
825         cobd_exp = cobd_get_exp(obd);
826         rc = obd_queue_async_io(cobd_exp, lsm, loi, cookie, cmd, off,
827                                 count, brw_flags, async_flags);
828         RETURN(rc);
829 }
830
831 static int cobd_dt_set_async_flags(struct obd_export *exp,
832                                    struct lov_stripe_md *lsm,
833                                    struct lov_oinfo *loi, void *cookie,
834                                    obd_flags async_flags)
835 {
836         struct obd_device *obd = class_exp2obd(exp);
837         struct obd_export *cobd_exp;
838         int rc = 0;
839         ENTRY;
840
841         if (obd == NULL) {
842                 CERROR("invalid client cookie "LPX64"\n", 
843                        exp->exp_handle.h_cookie);
844                 RETURN(-EINVAL);
845         }
846         cobd_exp = cobd_get_exp(obd);
847         rc = obd_set_async_flags(cobd_exp, lsm, loi, cookie,
848                                  async_flags);
849         RETURN(rc);
850 }
851
852 static int cobd_dt_queue_group_io(struct obd_export *exp, 
853                                   struct lov_stripe_md *lsm, 
854                                   struct lov_oinfo *loi, 
855                                   struct obd_io_group *oig, 
856                                   void *cookie, int cmd, obd_off off, 
857                                   int count, obd_flags brw_flags,
858                                   obd_flags async_flags)
859 {
860         struct obd_device *obd = class_exp2obd(exp);
861         struct obd_export *cobd_exp;
862         int rc = 0;
863         ENTRY;
864
865         if (obd == NULL) {
866                 CERROR("invalid client cookie "LPX64"\n", 
867                        exp->exp_handle.h_cookie);
868                 RETURN(-EINVAL);
869         }
870         cobd_exp = cobd_get_exp(obd);
871         rc = obd_queue_group_io(cobd_exp, lsm, loi, oig, cookie,
872                                 cmd, off, count, brw_flags,
873                                 async_flags);
874         RETURN(rc);
875 }
876
877 static int cobd_dt_trigger_group_io(struct obd_export *exp, 
878                                     struct lov_stripe_md *lsm, 
879                                     struct lov_oinfo *loi,
880                                     struct obd_io_group *oig)
881 {
882         struct obd_device *obd = class_exp2obd(exp);
883         struct obd_export *cobd_exp;
884         int rc = 0;
885         ENTRY;
886
887         if (obd == NULL) {
888                 CERROR("invalid client cookie "LPX64"\n", 
889                        exp->exp_handle.h_cookie);
890                 RETURN(-EINVAL);
891         }
892         cobd_exp = cobd_get_exp(obd);
893         rc = obd_trigger_group_io(cobd_exp, lsm, loi, oig);
894         RETURN(rc);
895 }
896
897 static int cobd_dt_teardown_async_page(struct obd_export *exp,
898                                        struct lov_stripe_md *lsm,
899                                        struct lov_oinfo *loi,
900                                        void *cookie)
901 {
902         struct obd_device *obd = class_exp2obd(exp);
903         struct obd_export *cobd_exp;
904         int rc = 0;
905         ENTRY;
906
907         if (obd == NULL) {
908                 CERROR("invalid client cookie "LPX64"\n", 
909                        exp->exp_handle.h_cookie);
910                 RETURN(-EINVAL);
911         }
912         cobd_exp = cobd_get_exp(obd);
913         rc = obd_teardown_async_page(cobd_exp, lsm, loi, cookie);
914         RETURN(rc);
915 }
916
917 static int cobd_dt_punch(struct obd_export *exp, struct obdo *oa,
918                          struct lov_stripe_md *ea, obd_size start,
919                          obd_size end, struct obd_trans_info *oti,
920                          struct lustre_capa *capa)
921 {
922         struct obd_device *obd = class_exp2obd(exp);
923         struct obd_export *cobd_exp;
924         int rc = 0;
925         ENTRY;
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         rc = obd_punch(cobd_exp, oa, ea, start, end, oti, capa);
934         RETURN(rc);
935 }
936
937 static int cobd_dt_sync(struct obd_export *exp, struct obdo *oa,
938                         struct lov_stripe_md *ea, obd_size start, 
939                         obd_size end)
940 {
941         struct obd_device *obd = class_exp2obd(exp);
942         struct obd_export *cobd_exp;
943         int rc = 0;
944         ENTRY;
945
946         if (obd == NULL) {
947                 CERROR("invalid client cookie "LPX64"\n", 
948                        exp->exp_handle.h_cookie);
949                 RETURN(-EINVAL);
950         }
951         cobd_exp = cobd_get_exp(obd);
952         rc = obd_sync(cobd_exp, oa, ea, start, end);
953         RETURN(rc);
954 }
955
956 static int cobd_dt_enqueue(struct obd_export *exp, struct lov_stripe_md *ea,
957                            __u32 type, ldlm_policy_data_t *policy,
958                            __u32 mode, int *flags, void *bl_cb, void *cp_cb,
959                            void *gl_cb, void *data, __u32 lvb_len,
960                            void *lvb_swabber, struct lustre_handle *lockh)
961 {
962         struct obd_device *obd = class_exp2obd(exp);
963         struct obd_export *cobd_exp;
964         int rc = 0;
965         ENTRY;
966
967         if (obd == NULL) {
968                 CERROR("invalid client cookie "LPX64"\n", 
969                        exp->exp_handle.h_cookie);
970                 RETURN(-EINVAL);
971         }
972         cobd_exp = cobd_get_exp(obd);
973         rc = obd_enqueue(cobd_exp, ea, type, policy, mode, flags, 
974                          bl_cb, cp_cb, gl_cb, data, lvb_len,
975                          lvb_swabber, lockh);
976         RETURN(rc);
977 }
978
979 static int cobd_dt_match(struct obd_export *exp, struct lov_stripe_md *ea,
980                          __u32 type, ldlm_policy_data_t *policy, __u32 mode,
981                          int *flags, void *data, struct lustre_handle *lockh)
982 {
983         struct obd_device *obd = class_exp2obd(exp);
984         struct obd_export *cobd_exp;
985         int rc = 0;
986         ENTRY;
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         rc = obd_match(cobd_exp, ea, type, policy, mode, flags,
995                        data, lockh);
996         RETURN(rc);
997 }
998 static int cobd_dt_change_cbdata(struct obd_export *exp,
999                                  struct lov_stripe_md *lsm, 
1000                                  ldlm_iterator_t it, void *data)
1001 {
1002         struct obd_device *obd = class_exp2obd(exp);
1003         struct obd_export *cobd_exp;
1004         int rc = 0;
1005         ENTRY;
1006
1007         if (obd == NULL) {
1008                 CERROR("invalid client cookie "LPX64"\n", 
1009                        exp->exp_handle.h_cookie);
1010                 RETURN(-EINVAL);
1011         }
1012         cobd_exp = cobd_get_exp(obd);
1013         rc = obd_change_cbdata(cobd_exp, lsm, it, data);
1014         RETURN(rc);
1015 }
1016
1017 static int cobd_dt_cancel(struct obd_export *exp,
1018                           struct lov_stripe_md *ea, __u32 mode,
1019                           struct lustre_handle *lockh)
1020 {
1021         struct obd_device *obd = class_exp2obd(exp);
1022         struct obd_export *cobd_exp;
1023         int rc = 0;
1024         ENTRY;
1025
1026         if (obd == NULL) {
1027                 CERROR("invalid client cookie "LPX64"\n", 
1028                        exp->exp_handle.h_cookie);
1029                 RETURN(-EINVAL);
1030         }
1031         cobd_exp = cobd_get_exp(obd);
1032         rc = obd_cancel(cobd_exp, ea, mode, lockh);
1033         RETURN(rc);
1034 }
1035
1036 static int cobd_dt_cancel_unused(struct obd_export *exp,
1037                                  struct lov_stripe_md *ea,
1038                                  int flags, void *opaque)
1039 {
1040         struct obd_device *obd = class_exp2obd(exp);
1041         struct obd_export *cobd_exp;
1042         int rc = 0;
1043         ENTRY;
1044         
1045         if (obd == NULL) {
1046                 CERROR("invalid client cookie "LPX64"\n", 
1047                        exp->exp_handle.h_cookie);
1048                 RETURN(-EINVAL);
1049         }
1050         cobd_exp = cobd_get_exp(obd);
1051         rc = obd_cancel_unused(cobd_exp, ea, flags, opaque);
1052         RETURN(rc);
1053 }
1054
1055 static int cobd_dt_preprw(int cmd, struct obd_export *exp,
1056                           struct obdo *oa, int objcount,
1057                           struct obd_ioobj *obj, int niocount,
1058                           struct niobuf_remote *nb,
1059                           struct niobuf_local *res,
1060                           struct obd_trans_info *oti,
1061                           struct lustre_capa *capa)
1062 {
1063         struct obd_device *obd = class_exp2obd(exp);
1064         struct obd_export *cobd_exp;
1065         int rc = 0;
1066         ENTRY;
1067
1068         if (obd == NULL) {
1069                 CERROR("invalid client cookie "LPX64"\n", 
1070                        exp->exp_handle.h_cookie);
1071                 RETURN(-EINVAL);
1072         }
1073         cobd_exp = cobd_get_exp(obd);
1074         rc = obd_preprw(cmd, cobd_exp, oa, objcount, obj,
1075                           niocount, nb, res, oti, capa);
1076         RETURN(rc);
1077 }
1078
1079 static int cobd_dt_commitrw(int cmd, struct obd_export *exp, struct obdo *oa,
1080                             int objcount, struct obd_ioobj *obj,
1081                             int niocount, struct niobuf_local *local,
1082                             struct obd_trans_info *oti, int rc)
1083 {
1084         struct obd_device *obd = class_exp2obd(exp);
1085         struct obd_export *cobd_exp;
1086         int err = 0;
1087         ENTRY;
1088
1089         if (obd == NULL) {
1090                 CERROR("invalid client cookie "LPX64"\n", 
1091                        exp->exp_handle.h_cookie);
1092                 RETURN(-EINVAL);
1093         }
1094         cobd_exp = cobd_get_exp(obd);
1095         err = obd_commitrw(cmd, cobd_exp, oa, objcount, obj,
1096                            niocount, local, oti, rc);
1097         RETURN(err);
1098 }
1099
1100 static int cobd_dt_adjust_kms(struct obd_export *exp,
1101                               struct lov_stripe_md *lsm,
1102                               obd_off size, int shrink)
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_adjust_kms(cobd_exp, lsm, size, shrink);
1116         
1117         RETURN(rc);
1118 }
1119
1120 static int cobd_dt_llog_init(struct obd_device *obd,
1121                              struct obd_llogs *llogs, 
1122                              struct obd_device *disk_obd,
1123                              int count, struct llog_catid *logid)
1124 {
1125         struct obd_export *cobd_exp;
1126         struct obd_device *cobd_obd;
1127         int rc = 0;
1128         ENTRY;
1129
1130         cobd_exp = cobd_get_exp(obd);
1131         cobd_obd = class_exp2obd(cobd_exp);
1132         
1133         rc = obd_llog_init(cobd_obd, &cobd_obd->obd_llogs, 
1134                            disk_obd, count, logid);
1135         RETURN(rc);
1136 }
1137
1138 static int cobd_dt_llog_finish(struct obd_device *obd,
1139                                struct obd_llogs *llogs, 
1140                                int count)
1141 {
1142         struct obd_export *cobd_exp;
1143         struct obd_device *cobd_obd;
1144         int rc = 0;
1145         ENTRY;
1146
1147         cobd_exp = cobd_get_exp(obd);
1148         cobd_obd = class_exp2obd(cobd_exp);
1149
1150         rc = obd_llog_finish(cobd_obd, &cobd_obd->obd_llogs, count);
1151         RETURN(rc);
1152 }
1153
1154 static int cobd_dt_init_ea_size(struct obd_export *exp, int easize,
1155                                 int cookiesize)
1156 {
1157         struct obd_export *cobd_exp;
1158         int rc = 0;
1159         ENTRY;
1160
1161         cobd_exp = cobd_get_exp(exp->exp_obd);
1162         rc = obd_init_ea_size(cobd_exp, easize, cookiesize);
1163         RETURN(rc);
1164 }
1165
1166 static int cobd_dt_import_event(struct obd_device *obd,
1167                                 struct obd_import *imp,
1168                                 enum obd_import_event event)
1169 {
1170         struct obd_export *cobd_exp;
1171         ENTRY;
1172
1173         cobd_exp = cobd_get_exp(obd);
1174         obd_import_event(class_exp2obd(cobd_exp), imp, event);
1175         RETURN(0); 
1176 }
1177
1178 /* metadata related stuff */
1179 static int cobd_md_getstatus(struct obd_export *exp,
1180                              struct lustre_id *rootid)
1181 {
1182         struct obd_device *obd = class_exp2obd(exp);
1183         struct obd_export *cobd_exp;
1184         int rc = 0;
1185         ENTRY;
1186
1187         if (obd == NULL) {
1188                 CERROR("invalid client cookie "LPX64"\n", 
1189                        exp->exp_handle.h_cookie);
1190                 RETURN(-EINVAL);
1191         }
1192         cobd_exp = cobd_get_exp(obd);
1193         rc = md_getstatus(cobd_exp, rootid);
1194         RETURN(rc);
1195 }
1196
1197 static int cobd_md_getattr(struct obd_export *exp, struct lustre_id *id,
1198                            __u64 valid, const char *xattr_name,
1199                            const void *xattr_data, unsigned int xattr_datalen,
1200                            unsigned int ea_size, struct obd_capa *ocapa,
1201                            struct ptlrpc_request **request)
1202 {
1203         struct obd_device *obd = class_exp2obd(exp);
1204         struct obd_export *cobd_exp;
1205         int rc = 0;
1206         ENTRY;
1207
1208         if (obd == NULL) {
1209                 CERROR("invalid client cookie "LPX64"\n", 
1210                        exp->exp_handle.h_cookie);
1211                 RETURN(-EINVAL);
1212         }
1213         cobd_exp = cobd_get_exp(obd);
1214         rc = md_getattr(cobd_exp, id, valid, xattr_name, xattr_data,
1215                           xattr_datalen, ea_size, ocapa, request);
1216         RETURN(rc);
1217 }
1218
1219 static int cobd_md_req2lustre_md(struct obd_export *mdc_exp, 
1220                                  struct ptlrpc_request *req,
1221                                  unsigned int offset,
1222                                  struct obd_export *osc_exp,
1223                                  struct lustre_md *md)
1224 {
1225         struct obd_device *obd = class_exp2obd(mdc_exp);
1226         struct obd_export *cobd_exp;
1227         int rc = 0;
1228         ENTRY;
1229
1230         if (obd == NULL) {
1231                 CERROR("invalid client cookie "LPX64"\n", 
1232                        mdc_exp->exp_handle.h_cookie);
1233                 RETURN(-EINVAL);
1234         }
1235         cobd_exp = cobd_get_exp(obd);
1236         rc = md_req2lustre_md(cobd_exp, req, offset, osc_exp, md);
1237         RETURN(rc);
1238 }
1239
1240 static int cobd_md_change_cbdata(struct obd_export *exp, struct lustre_id *id, 
1241                                  ldlm_iterator_t it, void *data)
1242 {
1243         struct obd_device *obd = class_exp2obd(exp);
1244         struct obd_export *cobd_exp;
1245         int rc = 0;
1246         ENTRY;
1247
1248         if (obd == NULL) {
1249                 CERROR("invalid client cookie "LPX64"\n", 
1250                        exp->exp_handle.h_cookie);
1251                 RETURN(-EINVAL);
1252         }
1253         cobd_exp = cobd_get_exp(obd);
1254         rc = md_change_cbdata(cobd_exp, id, it, data);
1255         RETURN(rc);
1256 }
1257
1258 static int cobd_md_getattr_lock(struct obd_export *exp, struct lustre_id *id,
1259                                 char *filename, int namelen, __u64 valid,
1260                                 unsigned int ea_size, struct ptlrpc_request **request)
1261 {
1262         struct obd_device *obd = class_exp2obd(exp);
1263         struct obd_export *cobd_exp;
1264         int rc = 0;
1265         ENTRY;
1266
1267         if (obd == NULL) {
1268                 CERROR("invalid client cookie "LPX64"\n", 
1269                        exp->exp_handle.h_cookie);
1270                 RETURN(-EINVAL);
1271         }
1272         cobd_exp = cobd_get_exp(obd);
1273         rc = md_getattr_lock(cobd_exp, id, filename, namelen,
1274                              valid, ea_size, request);
1275         RETURN(rc);
1276 }
1277
1278 static int cobd_md_create(struct obd_export *exp, struct mdc_op_data *op_data,
1279                           const void *data, int datalen, int mode, 
1280                           __u32 uid, __u32 gid, __u64 rdev, 
1281                           struct ptlrpc_request **request)
1282 {
1283         struct obd_device *obd = class_exp2obd(exp);
1284         struct obd_export *cobd_exp;
1285         int rc = 0;
1286         ENTRY;
1287
1288         if (obd == NULL) {
1289                 CERROR("invalid client cookie "LPX64"\n", 
1290                        exp->exp_handle.h_cookie);
1291                 RETURN(-EINVAL);
1292         }
1293         cobd_exp = cobd_get_exp(obd);
1294         rc = md_create(cobd_exp, op_data, data, datalen, mode,
1295                        uid, gid, rdev, request);
1296         RETURN(rc);
1297 }
1298
1299 static int cobd_md_unlink(struct obd_export *exp,
1300                           struct mdc_op_data *data,
1301                           struct ptlrpc_request **request)
1302 {
1303         struct obd_device *obd = class_exp2obd(exp);
1304         struct obd_export *cobd_exp;
1305         int rc = 0;
1306         ENTRY;
1307
1308         if (obd == NULL) {
1309                 CERROR("invalid client cookie "LPX64"\n", 
1310                        exp->exp_handle.h_cookie);
1311                 RETURN(-EINVAL);
1312         }
1313         cobd_exp = cobd_get_exp(obd);
1314         rc = md_unlink(cobd_exp, data, request);
1315         RETURN(rc);
1316 }
1317
1318 static int cobd_md_valid_attrs(struct obd_export *exp,
1319                                struct lustre_id *id)
1320 {
1321         struct obd_device *obd = class_exp2obd(exp);
1322         struct obd_export *cobd_exp;
1323         int rc = 0;
1324         ENTRY;
1325
1326         if (obd == NULL) {
1327                 CERROR("invalid client cookie "LPX64"\n", 
1328                        exp->exp_handle.h_cookie);
1329                 RETURN(-EINVAL);
1330         }
1331         cobd_exp = cobd_get_exp(obd);
1332         rc = md_valid_attrs(cobd_exp, id);
1333         RETURN(rc);
1334 }
1335
1336 static int cobd_md_rename(struct obd_export *exp, struct mdc_op_data *data,
1337                           const char *old, int oldlen, const char *new, 
1338                           int newlen, struct ptlrpc_request **request)
1339 {
1340         struct obd_device *obd = class_exp2obd(exp);
1341         struct obd_export *cobd_exp;
1342         int rc = 0;
1343         ENTRY;
1344
1345         if (obd == NULL) {
1346                 CERROR("invalid client cookie "LPX64"\n", 
1347                        exp->exp_handle.h_cookie);
1348                 RETURN(-EINVAL);
1349         }
1350         cobd_exp = cobd_get_exp(obd);
1351         rc = md_rename(cobd_exp, data, old, oldlen, new, newlen, request);
1352         RETURN(rc);
1353 }
1354
1355 static int cobd_md_link(struct obd_export *exp, struct mdc_op_data *data,
1356                         struct ptlrpc_request **request)
1357 {
1358         struct obd_device *obd = class_exp2obd(exp);
1359         struct obd_export *cobd_exp;
1360         int rc = 0;
1361         ENTRY;
1362
1363         if (obd == NULL) {
1364                 CERROR("invalid client cookie "LPX64"\n", 
1365                        exp->exp_handle.h_cookie);
1366                 RETURN(-EINVAL);
1367         }
1368         cobd_exp = cobd_get_exp(obd);
1369         rc = md_link(cobd_exp, data, request);
1370         RETURN(rc);
1371 }
1372
1373 static int cobd_md_setattr(struct obd_export *exp, struct mdc_op_data *data,
1374                            struct iattr *iattr, void *ea, int ealen, void *ea2, 
1375                            int ea2len, void *ea3, int ea3len, 
1376                            struct ptlrpc_request **request)
1377 {
1378         struct obd_device *obd = class_exp2obd(exp);
1379         struct obd_export *cobd_exp;
1380         int rc = 0;
1381         ENTRY;
1382
1383         if (obd == NULL) {
1384                 CERROR("invalid client cookie "LPX64"\n", 
1385                        exp->exp_handle.h_cookie);
1386                 RETURN(-EINVAL);
1387         }
1388         cobd_exp = cobd_get_exp(obd);
1389         rc = md_setattr(cobd_exp, data, iattr, ea,
1390                           ealen, ea2, ea2len, ea3, ea3len, request);
1391         RETURN(rc);
1392 }
1393
1394 static int cobd_md_readpage(struct obd_export *exp,
1395                             struct lustre_id *mdc_id,
1396                             __u64 offset, struct page *page, 
1397                             struct ptlrpc_request **request)
1398 {
1399         struct obd_device *obd = class_exp2obd(exp);
1400         struct obd_export *cobd_exp;
1401         int rc = 0;
1402         ENTRY;
1403
1404         if (obd == NULL) {
1405                 CERROR("invalid client cookie "LPX64"\n", 
1406                        exp->exp_handle.h_cookie);
1407                 RETURN(-EINVAL);
1408         }
1409         cobd_exp = cobd_get_exp(obd);
1410         rc = md_readpage(cobd_exp, mdc_id, offset, page, request);
1411         RETURN(rc);
1412 }
1413
1414 static int cobd_md_close(struct obd_export *exp, struct mdc_op_data *op_data,
1415                          struct obd_client_handle *och, 
1416                          struct ptlrpc_request **request)
1417 {
1418         struct obd_device *obd = class_exp2obd(exp);
1419         struct obd_export *cobd_exp;
1420         int rc = 0;
1421         ENTRY;
1422
1423         if (obd == NULL) {
1424                 CERROR("invalid client cookie "LPX64"\n", 
1425                        exp->exp_handle.h_cookie);
1426                 RETURN(-EINVAL);
1427         }
1428         cobd_exp = cobd_get_exp(obd);
1429         rc = md_close(cobd_exp, op_data, och, request);
1430         RETURN(rc);
1431 }
1432
1433 static int cobd_md_done_writing(struct obd_export *exp,
1434                                 struct obdo *obdo)
1435 {
1436         struct obd_device *obd = class_exp2obd(exp);
1437         struct obd_export *cobd_exp;
1438         int rc = 0;
1439         ENTRY;
1440
1441         if (obd == NULL) {
1442                 CERROR("invalid client cookie "LPX64"\n", 
1443                        exp->exp_handle.h_cookie);
1444                 RETURN(-EINVAL);
1445         }
1446         cobd_exp = cobd_get_exp(obd);
1447         rc = md_done_writing(cobd_exp, obdo);
1448         RETURN(rc);
1449 }
1450
1451 static int cobd_md_sync(struct obd_export *exp, struct lustre_id *id,
1452                         struct ptlrpc_request **request)
1453 {
1454         struct obd_device *obd = class_exp2obd(exp);
1455         struct obd_export *cobd_exp;
1456         int rc = 0;
1457         ENTRY;
1458
1459         if (obd == NULL) {
1460                 CERROR("invalid client cookie "LPX64"\n", 
1461                        exp->exp_handle.h_cookie);
1462                 RETURN(-EINVAL);
1463         }
1464         cobd_exp = cobd_get_exp(obd);
1465         rc = md_sync(cobd_exp, id, request);
1466         RETURN(rc);
1467 }
1468
1469 static int cobd_md_set_open_replay_data(struct obd_export *exp,
1470                                         struct obd_client_handle *och,
1471                                         struct ptlrpc_request *open_req)
1472 {
1473         struct obd_device *obd = class_exp2obd(exp);
1474         struct obd_export *cobd_exp;
1475         int rc = 0;
1476         ENTRY;
1477
1478         if (obd == NULL) {
1479                 CERROR("invalid client cookie "LPX64"\n", 
1480                        exp->exp_handle.h_cookie);
1481                 RETURN(-EINVAL);
1482         }
1483         cobd_exp = cobd_get_exp(obd);
1484         rc = md_set_open_replay_data(cobd_exp, och, open_req);
1485         RETURN(rc);
1486 }
1487
1488 static int cobd_md_clear_open_replay_data(struct obd_export *exp,
1489                                           struct obd_client_handle *och)
1490 {
1491         struct obd_device *obd = class_exp2obd(exp);
1492         struct obd_export *cobd_exp;
1493         int rc = 0;
1494         ENTRY;
1495
1496         if (obd == NULL) {
1497                 CERROR("invalid client cookie "LPX64"\n", 
1498                        exp->exp_handle.h_cookie);
1499                 RETURN(-EINVAL);
1500         }
1501         cobd_exp = cobd_get_exp(obd);
1502         rc = md_clear_open_replay_data(cobd_exp, och);
1503         RETURN(rc);
1504 }
1505
1506 static int cobd_md_store_inode_generation(struct obd_export *exp,
1507                                           struct ptlrpc_request *req, 
1508                                           int reqoff, int repoff)
1509 {
1510         struct obd_device *obd = class_exp2obd(exp);
1511         struct obd_export *cobd_exp;
1512         int rc = 0;
1513         ENTRY;
1514
1515         if (obd == NULL) {
1516                 CERROR("invalid client cookie "LPX64"\n", 
1517                        exp->exp_handle.h_cookie);
1518                 RETURN(-EINVAL);
1519         }
1520         cobd_exp = cobd_get_exp(obd);
1521         rc = md_store_inode_generation(cobd_exp, req, reqoff, repoff);
1522         RETURN(rc);
1523 }
1524
1525 static int cobd_md_set_lock_data(struct obd_export *exp,
1526                                  __u64 *l, void *data)
1527 {
1528         struct obd_device *obd = class_exp2obd(exp);
1529         struct obd_export *cobd_exp;
1530         int rc = 0;
1531         ENTRY;
1532
1533         if (obd == NULL) {
1534                 CERROR("invalid client cookie "LPX64"\n", 
1535                        exp->exp_handle.h_cookie);
1536                 RETURN(-EINVAL);
1537         }
1538         cobd_exp = cobd_get_exp(obd);
1539         rc = md_set_lock_data(cobd_exp, l, data);
1540         RETURN(rc);
1541 }
1542
1543 static int cobd_md_enqueue(struct obd_export *exp, int lock_type,
1544                            struct lookup_intent *it, int lock_mode,
1545                            struct mdc_op_data *data, struct lustre_handle *lockh,
1546                            void *lmm, int lmmsize, 
1547                            ldlm_completion_callback cb_completion,
1548                            ldlm_blocking_callback cb_blocking, void *cb_data)
1549 {
1550         struct obd_device *obd = class_exp2obd(exp);
1551         struct obd_export *cobd_exp;
1552         int rc = 0;
1553         ENTRY;
1554
1555         if (obd == NULL) {
1556                 CERROR("invalid client cookie "LPX64"\n", 
1557                        exp->exp_handle.h_cookie);
1558                 RETURN(-EINVAL);
1559         }
1560         cobd_exp = cobd_get_exp(obd);
1561         rc = md_enqueue(cobd_exp, lock_type, it, lock_mode, data,
1562                         lockh, lmm, lmmsize, cb_completion, cb_blocking,
1563                         cb_data);
1564         RETURN(rc);
1565 }
1566
1567 static int cobd_md_intent_lock(struct obd_export *exp, struct lustre_id *pid, 
1568                                const char *name, int len, void *lmm, int lmmsize,
1569                                struct lustre_id *cid, struct lookup_intent *it,
1570                                int lookup_flags, struct ptlrpc_request **reqp,
1571                                ldlm_blocking_callback cb_blocking)
1572 {
1573         struct obd_device *obd = class_exp2obd(exp);
1574         struct obd_export *cobd_exp;
1575         int rc = 0;
1576         ENTRY;
1577
1578         if (obd == NULL) {
1579                 CERROR("invalid client cookie "LPX64"\n", 
1580                        exp->exp_handle.h_cookie);
1581                 RETURN(-EINVAL);
1582         }
1583         lookup_flags |= LOOKUP_COBD;
1584         cobd_exp = cobd_get_exp(obd);
1585         
1586         rc = md_intent_lock(cobd_exp, pid, name, len, lmm, lmmsize,
1587                             cid, it, lookup_flags, reqp, cb_blocking);
1588         RETURN(rc);
1589 }
1590
1591 static struct obd_device *cobd_md_get_real_obd(struct obd_export *exp,
1592                                                struct lustre_id *id)
1593 {
1594         struct obd_device *obd = class_exp2obd(exp);
1595         struct obd_export *cobd_exp;
1596         ENTRY;
1597
1598         if (obd == NULL) {
1599                 CERROR("invalid client cookie "LPX64"\n", 
1600                        exp->exp_handle.h_cookie);
1601                 RETURN(NULL);
1602         }
1603         cobd_exp = cobd_get_exp(obd);
1604         RETURN(md_get_real_obd(cobd_exp, id));
1605 }
1606
1607 static int cobd_md_change_cbdata_name(struct obd_export *exp,
1608                                       struct lustre_id *id, char *name,
1609                                       int namelen, struct lustre_id *id2,
1610                                       ldlm_iterator_t it, void *data)
1611 {
1612         struct obd_device *obd = class_exp2obd(exp);
1613         struct obd_export *cobd_exp;
1614         int rc = 0;
1615
1616         if (obd == NULL) {
1617                 CERROR("invalid client cookie "LPX64"\n", 
1618                        exp->exp_handle.h_cookie);
1619                 RETURN(-EINVAL);
1620         }
1621         cobd_exp = cobd_get_exp(obd);
1622         rc = md_change_cbdata_name(cobd_exp, id, name, namelen,
1623                                    id2, it, data);
1624         RETURN(rc);
1625 }
1626
1627 static struct obd_ops cobd_obd_ops = {
1628         .o_owner                  = THIS_MODULE,
1629         .o_attach                 = cobd_attach,
1630         .o_detach                 = cobd_detach,
1631         .o_setup                  = cobd_setup,
1632         .o_cleanup                = cobd_cleanup,
1633         .o_connect                = cobd_connect,
1634         .o_disconnect             = cobd_disconnect,
1635         .o_set_info               = cobd_set_info,
1636         .o_get_info               = cobd_get_info,
1637         .o_statfs                 = cobd_statfs,
1638         .o_iocontrol              = cobd_iocontrol,
1639         .o_notify                 = cobd_notify,
1640         .o_pin                    = cobd_pin,
1641         .o_unpin                  = cobd_unpin,
1642
1643         .o_packmd                 = cobd_dt_packmd,
1644         .o_unpackmd               = cobd_dt_unpackmd,
1645         .o_create                 = cobd_dt_create,
1646         .o_destroy                = cobd_dt_destroy,
1647         .o_precleanup             = cobd_dt_precleanup,
1648         .o_getattr                = cobd_dt_getattr,
1649         .o_getattr_async          = cobd_dt_getattr_async,
1650         .o_setattr                = cobd_dt_setattr,
1651         .o_brw                    = cobd_dt_brw,
1652         .o_brw_async              = cobd_dt_brw_async,
1653         .o_prep_async_page        = cobd_dt_prep_async_page,
1654         .o_queue_async_io         = cobd_dt_queue_async_io,
1655         .o_set_async_flags        = cobd_dt_set_async_flags,
1656         .o_queue_group_io         = cobd_dt_queue_group_io,
1657         .o_trigger_group_io       = cobd_dt_trigger_group_io,
1658         .o_teardown_async_page    = cobd_dt_teardown_async_page,
1659         .o_preprw                 = cobd_dt_preprw,
1660         .o_punch                  = cobd_dt_punch,
1661         .o_sync                   = cobd_dt_sync,
1662         .o_enqueue                = cobd_dt_enqueue,
1663         .o_match                  = cobd_dt_match,
1664         .o_change_cbdata          = cobd_dt_change_cbdata,
1665         .o_cancel                 = cobd_dt_cancel,
1666         .o_cancel_unused          = cobd_dt_cancel_unused,
1667         .o_commitrw               = cobd_dt_commitrw,
1668         .o_llog_init              = cobd_dt_llog_init,
1669         .o_llog_finish            = cobd_dt_llog_finish,
1670         .o_import_event           = cobd_dt_import_event,
1671         .o_init_ea_size           = cobd_dt_init_ea_size,
1672         .o_adjust_kms             = cobd_dt_adjust_kms,
1673 };
1674
1675 struct md_ops cobd_md_ops = {
1676         .m_getstatus              = cobd_md_getstatus,
1677         .m_getattr                = cobd_md_getattr,
1678         .m_req2lustre_md          = cobd_md_req2lustre_md,
1679         .m_change_cbdata          = cobd_md_change_cbdata,
1680         .m_getattr_lock           = cobd_md_getattr_lock,
1681         .m_create                 = cobd_md_create,
1682         .m_unlink                 = cobd_md_unlink,
1683         .m_valid_attrs            = cobd_md_valid_attrs,
1684         .m_rename                 = cobd_md_rename,
1685         .m_link                   = cobd_md_link,
1686         .m_setattr                = cobd_md_setattr,
1687         .m_readpage               = cobd_md_readpage,
1688         .m_close                  = cobd_md_close,
1689         .m_done_writing           = cobd_md_done_writing,
1690         .m_sync                   = cobd_md_sync,
1691         .m_set_open_replay_data   = cobd_md_set_open_replay_data,
1692         .m_clear_open_replay_data = cobd_md_clear_open_replay_data,
1693         .m_store_inode_generation = cobd_md_store_inode_generation,
1694         .m_set_lock_data          = cobd_md_set_lock_data,
1695         .m_enqueue                = cobd_md_enqueue,
1696         .m_get_real_obd           = cobd_md_get_real_obd,
1697         .m_intent_lock            = cobd_md_intent_lock,
1698         .m_change_cbdata_name     = cobd_md_change_cbdata_name,
1699 };
1700
1701 static int __init cobd_init(void)
1702 {
1703         struct lprocfs_static_vars lvars;
1704         ENTRY;
1705
1706         printk(KERN_INFO "Lustre: Caching OBD driver; info@clusterfs.com\n");
1707
1708         lprocfs_init_vars(cobd, &lvars);
1709         RETURN(class_register_type(&cobd_obd_ops, &cobd_md_ops,
1710                                    lvars.module_vars, OBD_CACHE_DEVICENAME));
1711 }
1712
1713 static void /*__exit*/ cobd_exit(void)
1714 {
1715         class_unregister_type(OBD_CACHE_DEVICENAME);
1716 }
1717
1718 MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
1719 MODULE_DESCRIPTION("Lustre Caching OBD driver");
1720 MODULE_LICENSE("GPL");
1721
1722 module_init(cobd_init);
1723 module_exit(cobd_exit);