Whamcloud - gitweb
- fixes and cleanups in error messages and in code.
[fs/lustre-release.git] / lustre / lmv / lmv_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, 2003 Cluster File Systems, Inc.
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 #ifndef EXPORT_SYMTAB
23 # define EXPORT_SYMTAB
24 #endif
25 #define DEBUG_SUBSYSTEM S_LMV
26 #ifdef __KERNEL__
27 #include <linux/slab.h>
28 #include <linux/module.h>
29 #include <linux/init.h>
30 #include <linux/slab.h>
31 #include <linux/pagemap.h>
32 #include <asm/div64.h>
33 #include <linux/seq_file.h>
34 #else
35 #include <liblustre.h>
36 #endif
37 #include <linux/ext2_fs.h>
38
39 #include <linux/obd_support.h>
40 #include <linux/lustre_lib.h>
41 #include <linux/lustre_net.h>
42 #include <linux/lustre_idl.h>
43 #include <linux/lustre_dlm.h>
44 #include <linux/lustre_mds.h>
45 #include <linux/obd_class.h>
46 #include <linux/obd_ost.h>
47 #include <linux/lprocfs_status.h>
48 #include <linux/lustre_fsfilt.h>
49 #include <linux/obd_lmv.h>
50 #include "lmv_internal.h"
51
52 /* object cache. */
53 kmem_cache_t *obj_cache;
54 atomic_t obj_cache_count = ATOMIC_INIT(0);
55
56 static void lmv_activate_target(struct lmv_obd *lmv,
57                                 struct lmv_tgt_desc *tgt,
58                                 int activate)
59 {
60         if (tgt->active == activate)
61                 return;
62         
63         tgt->active = activate;
64         lmv->desc.ld_active_tgt_count += (activate ? 1 : -1);
65 }
66
67 /* Error codes:
68  *
69  *  -EINVAL  : UUID can't be found in the LMV's target list
70  *  -ENOTCONN: The UUID is found, but the target connection is bad (!)
71  *  -EBADF   : The UUID is found, but the OBD of the wrong type (!)
72  */
73 static int lmv_set_mdc_active(struct lmv_obd *lmv, struct obd_uuid *uuid,
74                               int activate)
75 {
76         struct obd_device *obd;
77         struct lmv_tgt_desc *tgt;
78         int i, rc = 0;
79         ENTRY;
80
81         CDEBUG(D_INFO, "Searching in lmv %p for uuid %s (activate=%d)\n",
82                lmv, uuid->uuid, activate);
83
84         spin_lock(&lmv->lmv_lock);
85         for (i = 0, tgt = lmv->tgts; i < lmv->desc.ld_tgt_count; i++, tgt++) {
86                 if (tgt->ltd_exp == NULL)
87                         continue;
88
89                 CDEBUG(D_INFO, "lmv idx %d is %s conn "LPX64"\n",
90                        i, tgt->uuid.uuid, tgt->ltd_exp->exp_handle.h_cookie);
91
92                 if (strncmp(uuid->uuid, tgt->uuid.uuid, sizeof uuid->uuid) == 0)
93                         break;
94         }
95
96         if (i == lmv->desc.ld_tgt_count)
97                 GOTO(out_lmv_lock, rc = -EINVAL);
98
99         obd = class_exp2obd(tgt->ltd_exp);
100         if (obd == NULL)
101                 GOTO(out_lmv_lock, rc = -ENOTCONN);
102
103         CDEBUG(D_INFO, "Found OBD %s=%s device %d (%p) type %s at LMV idx %d\n",
104                obd->obd_name, obd->obd_uuid.uuid, obd->obd_minor, obd,
105                obd->obd_type->typ_name, i);
106         LASSERT(strcmp(obd->obd_type->typ_name, LUSTRE_MDC_NAME) == 0);
107
108         if (tgt->active == activate) {
109                 CDEBUG(D_INFO, "OBD %p already %sactive!\n", obd,
110                        activate ? "" : "in");
111                 GOTO(out_lmv_lock, rc);
112         }
113
114         CDEBUG(D_INFO, "Marking OBD %p %sactive\n",
115                obd, activate ? "" : "in");
116
117         lmv_activate_target(lmv, tgt, activate);
118
119         EXIT;
120         
121  out_lmv_lock:
122         spin_unlock(&lmv->lmv_lock);
123         return rc;
124 }
125
126 static int lmv_notify(struct obd_device *obd, struct obd_device *watched,
127                       int active, void *data)
128 {
129         int rc;
130         struct obd_uuid *uuid;
131
132         if (strcmp(watched->obd_type->typ_name, LUSTRE_MDC_NAME)) {
133                 CERROR("unexpected notification of %s %s!\n",
134                        watched->obd_type->typ_name,
135                        watched->obd_name);
136                 return -EINVAL;
137         }
138         uuid = &watched->u.cli.cl_import->imp_target_uuid;
139
140         /* Set MDC as active before notifying the observer, so the observer can
141          * use the MDC normally.
142          */
143         rc = lmv_set_mdc_active(&obd->u.lmv, uuid, active);
144         if (rc) {
145                 CERROR("%sactivation of %s failed: %d\n",
146                        active ? "" : "de", uuid->uuid, rc);
147                 RETURN(rc);
148         }
149
150         if (obd->obd_observer)
151                 /* Pass the notification up the chain. */
152                 rc = obd_notify(obd->obd_observer, watched, active, data);
153
154         RETURN(rc);
155 }
156
157 int lmv_attach(struct obd_device *dev, obd_count len, void *data)
158 {
159         struct lprocfs_static_vars lvars;
160         int rc;
161         ENTRY;
162
163         lprocfs_init_vars(lmv, &lvars);
164         rc = lprocfs_obd_attach(dev, lvars.obd_vars);
165 #ifdef __KERNEL__
166         if (rc == 0) {
167                 struct proc_dir_entry *entry;
168                 
169                 entry = create_proc_entry("target_obd_status", 0444, 
170                                            dev->obd_proc_entry);
171                 if (entry == NULL)
172                         RETURN(-ENOMEM);
173                 entry->proc_fops = &lmv_proc_target_fops; 
174                 entry->data = dev;
175        }
176 #endif
177         RETURN (rc);
178 }
179
180 int lmv_detach(struct obd_device *dev)
181 {
182         return lprocfs_obd_detach(dev);
183 }
184
185 /* this is fake connect function. Its purpose is to initialize lmv and say
186  * caller that everything is okay. Real connection will be performed later. */
187 static int lmv_connect(struct lustre_handle *conn, struct obd_device *obd,
188                        struct obd_uuid *cluuid, unsigned long flags)
189 {
190 #ifdef __KERNEL__
191         struct proc_dir_entry *lmv_proc_dir;
192 #endif
193         struct lmv_obd *lmv = &obd->u.lmv;
194         struct obd_export *exp;
195         int rc = 0;
196         ENTRY;
197
198         rc = class_connect(conn, obd, cluuid);
199         if (rc) {
200                 CERROR("class_connection() returned %d\n", rc);
201                 RETURN(rc);
202         }
203
204         exp = class_conn2export(conn);
205         
206         /* we don't want to actually do the underlying connections more than
207          * once, so keep track. */
208         lmv->refcount++;
209         if (lmv->refcount > 1) {
210                 class_export_put(exp);
211                 RETURN(0);
212         }
213
214         lmv->exp = exp;
215         lmv->connected = 0;
216         lmv->cluuid = *cluuid;
217         lmv->connect_flags = flags;
218         sema_init(&lmv->init_sem, 1);
219
220 #ifdef __KERNEL__
221         lmv_proc_dir = lprocfs_register("target_obds", obd->obd_proc_entry,
222                                         NULL, NULL);
223         if (IS_ERR(lmv_proc_dir)) {
224                 CERROR("could not register /proc/fs/lustre/%s/%s/target_obds.",
225                        obd->obd_type->typ_name, obd->obd_name);
226                 lmv_proc_dir = NULL;
227         }
228 #endif
229
230         /* 
231          * all real clients shouls perform actual connection rightaway, because
232          * it is possible, that LMV will not have opportunity to connect
233          * targets, as MDC stuff will bit called directly, for instance while
234          * reading ../mdc/../kbytesfree procfs file, etc.
235          */
236         if (flags & OBD_OPT_REAL_CLIENT)
237                 rc = lmv_check_connect(obd);
238
239 #ifdef __KERNEL__
240         if (rc) {
241                 if (lmv_proc_dir)
242                         lprocfs_remove(lmv_proc_dir);
243         }
244 #endif
245
246         RETURN(rc);
247 }
248
249 void lmv_set_timeouts(struct obd_device *obd)
250 {
251         struct lmv_tgt_desc *tgts;
252         struct lmv_obd *lmv;
253         int i;
254
255         lmv = &obd->u.lmv;
256         if (lmv->server_timeout == 0)
257                 return;
258
259         if (lmv->connected == 0)
260                 return;
261
262         for (i = 0, tgts = lmv->tgts; i < lmv->desc.ld_tgt_count; i++, tgts++) {
263                 if (tgts->ltd_exp == NULL)
264                         continue;
265                 
266                 obd_set_info(tgts->ltd_exp, strlen("inter_mds"),
267                              "inter_mds", 0, NULL);
268         }
269 }
270
271 #define MAX_STRING_SIZE 128
272
273 /* performs a check if passed obd is connected. If no - connect it. */
274 int lmv_check_connect(struct obd_device *obd)
275 {
276 #ifdef __KERNEL__
277         struct proc_dir_entry *lmv_proc_dir;
278 #endif
279         struct lmv_obd *lmv = &obd->u.lmv;
280         struct lmv_tgt_desc *tgts;
281         struct obd_uuid *cluuid;
282         struct obd_export *exp;
283         int rc, rc2, i;
284
285         if (lmv->connected)
286                 return 0;
287         
288         down(&lmv->init_sem);
289         if (lmv->connected) {
290                 up(&lmv->init_sem);
291                 return 0;
292         }
293
294         cluuid = &lmv->cluuid;
295         exp = lmv->exp;
296         
297         CDEBUG(D_OTHER, "time to connect %s to %s\n",
298                cluuid->uuid, obd->obd_name);
299
300         for (i = 0, tgts = lmv->tgts; i < lmv->desc.ld_tgt_count; i++, tgts++) {
301                 struct obd_device *tgt_obd;
302                 struct lustre_handle conn = {0, };
303                 struct obd_uuid lmv_mdc_uuid = { "LMV_MDC_UUID" };
304
305                 LASSERT(tgts != NULL);
306
307                 tgt_obd = class_find_client_obd(&tgts->uuid, LUSTRE_MDC_NAME, 
308                                                 &obd->obd_uuid);
309                 if (!tgt_obd) {
310                         CERROR("target %s not attached\n", tgts->uuid.uuid);
311                         GOTO(out_disc, rc = -EINVAL);
312                 }
313
314                 /* for MDS: don't connect to yourself */
315                 if (obd_uuid_equals(&tgts->uuid, cluuid)) {
316                         CDEBUG(D_OTHER, "don't connect back to %s\n",
317                                cluuid->uuid);
318                         tgts->ltd_exp = NULL;
319                         continue;
320                 }
321
322                 CDEBUG(D_OTHER, "connect to %s(%s) - %s, %s FOR %s\n",
323                         tgt_obd->obd_name, tgt_obd->obd_uuid.uuid,
324                         tgts->uuid.uuid, obd->obd_uuid.uuid,
325                         cluuid->uuid);
326
327                 if (!tgt_obd->obd_set_up) {
328                         CERROR("target %s not set up\n", tgts->uuid.uuid);
329                         GOTO(out_disc, rc = -EINVAL);
330                 }
331                 
332                 rc = obd_connect(&conn, tgt_obd, &lmv_mdc_uuid,
333                                  lmv->connect_flags);
334                 if (rc) {
335                         CERROR("target %s connect error %d\n",
336                                 tgts->uuid.uuid, rc);
337                         GOTO(out_disc, rc);
338                 }
339                 tgts->ltd_exp = class_conn2export(&conn);
340
341                 obd_init_ea_size(tgts->ltd_exp, lmv->max_easize,
342                                  lmv->max_cookiesize);
343
344                 rc = obd_register_observer(tgt_obd, obd);
345                 if (rc) {
346                         CERROR("target %s register_observer error %d\n",
347                                tgts->uuid.uuid, rc);
348                         obd_disconnect(tgts->ltd_exp, 0);
349                         GOTO(out_disc, rc);
350                 }
351
352                 lmv->desc.ld_active_tgt_count++;
353                 tgts->active = 1;
354
355                 CDEBUG(D_OTHER, "connected to %s(%s) successfully (%d)\n",
356                         tgt_obd->obd_name, tgt_obd->obd_uuid.uuid,
357                         atomic_read(&obd->obd_refcount));
358
359 #ifdef __KERNEL__
360                 lmv_proc_dir = lprocfs_srch(obd->obd_proc_entry, "target_obds");
361                 if (lmv_proc_dir) {
362                         struct obd_device *mdc_obd = class_conn2obd(&conn);
363                         struct proc_dir_entry *mdc_symlink;
364                         char name[MAX_STRING_SIZE + 1];
365
366                         LASSERT(mdc_obd != NULL);
367                         LASSERT(mdc_obd->obd_type != NULL);
368                         LASSERT(mdc_obd->obd_type->typ_name != NULL);
369                         name[MAX_STRING_SIZE] = '\0';
370                         snprintf(name, MAX_STRING_SIZE, "../../../%s/%s",
371                                  mdc_obd->obd_type->typ_name,
372                                  mdc_obd->obd_name);
373                         mdc_symlink = proc_symlink(mdc_obd->obd_name,
374                                                    lmv_proc_dir, name);
375                         if (mdc_symlink == NULL) {
376                                 CERROR("could not register LMV target "
377                                        "/proc/fs/lustre/%s/%s/target_obds/%s.",
378                                        obd->obd_type->typ_name, obd->obd_name,
379                                        mdc_obd->obd_name);
380                                 lprocfs_remove(lmv_proc_dir);
381                                 lmv_proc_dir = NULL;
382                         }
383                 }
384 #endif
385         }
386
387         lmv_set_timeouts(obd);
388         class_export_put(exp);
389         lmv->connected = 1;
390         up(&lmv->init_sem);
391         return 0;
392
393  out_disc:
394         while (i-- > 0) {
395                 struct obd_uuid uuid;
396                 --tgts;
397                 --lmv->desc.ld_active_tgt_count;
398                 tgts->active = 0;
399                 /* save for CERROR below; (we know it's terminated) */
400                 uuid = tgts->uuid;
401                 rc2 = obd_disconnect(tgts->ltd_exp, 0);
402                 if (rc2)
403                         CERROR("error: LMV target %s disconnect on MDC idx %d: "
404                                "error %d\n", uuid.uuid, i, rc2);
405         }
406         class_disconnect(exp, 0);
407         up(&lmv->init_sem);
408         RETURN (rc);
409 }
410
411 static int lmv_disconnect(struct obd_export *exp, unsigned long flags)
412 {
413         struct obd_device *obd = class_exp2obd(exp);
414         struct lmv_obd *lmv = &obd->u.lmv;
415
416 #ifdef __KERNEL__
417         struct proc_dir_entry *lmv_proc_dir;
418 #endif
419         int rc, i;
420         ENTRY;
421
422         if (!lmv->tgts)
423                 goto out_local;
424
425         /* Only disconnect the underlying layers on the final disconnect. */
426         lmv->refcount--;
427         if (lmv->refcount != 0)
428                 goto out_local;
429
430 #ifdef __KERNEL__
431         lmv_proc_dir = lprocfs_srch(obd->obd_proc_entry, "target_obds");
432 #endif
433
434         for (i = 0; i < lmv->desc.ld_tgt_count; i++) {
435                 struct obd_device *mdc_obd; 
436                 
437                 if (lmv->tgts[i].ltd_exp == NULL)
438                         continue;
439
440                 mdc_obd = class_exp2obd(lmv->tgts[i].ltd_exp);
441
442 #ifdef __KERNEL__
443                 if (lmv_proc_dir) {
444                         struct proc_dir_entry *mdc_symlink;
445
446                         mdc_symlink = lprocfs_srch(lmv_proc_dir, mdc_obd->obd_name);
447                         if (mdc_symlink) {
448                                 lprocfs_remove(mdc_symlink);
449                         } else {
450                                 CERROR("/proc/fs/lustre/%s/%s/target_obds/%s missing\n",
451                                        obd->obd_type->typ_name, obd->obd_name,
452                                        mdc_obd->obd_name);
453                         }
454                 }
455 #endif
456                 if (obd->obd_no_recov) {
457                         if (mdc_obd)
458                                 mdc_obd->obd_no_recov = 1;
459                 }
460                 CDEBUG(D_OTHER, "disconnected from %s(%s) successfully\n",
461                         lmv->tgts[i].ltd_exp->exp_obd->obd_name,
462                         lmv->tgts[i].ltd_exp->exp_obd->obd_uuid.uuid);
463
464                 obd_register_observer(lmv->tgts[i].ltd_exp->exp_obd, NULL);
465                 rc = obd_disconnect(lmv->tgts[i].ltd_exp, flags);
466                 if (rc) {
467                         if (lmv->tgts[i].active) {
468                                 CERROR("Target %s disconnect error %d\n",
469                                        lmv->tgts[i].uuid.uuid, rc);
470                         }
471                         rc = 0;
472                 }
473                 
474                 lmv_activate_target(lmv, &lmv->tgts[i], 0);
475                 lmv->tgts[i].ltd_exp = NULL;
476         }
477
478 #ifdef __KERNEL__
479         if (lmv_proc_dir) {
480                 lprocfs_remove(lmv_proc_dir);
481         } else {
482                 CERROR("/proc/fs/lustre/%s/%s/target_obds missing\n",
483                        obd->obd_type->typ_name, obd->obd_name);
484         }
485 #endif
486
487 out_local:
488         /* this is the case when no real connection is established by
489          * lmv_check_connect(). */
490         if (!lmv->connected)
491                 class_export_put(exp);
492         rc = class_disconnect(exp, 0);
493         if (lmv->refcount == 0)
494                 lmv->connected = 0;
495         RETURN(rc);
496 }
497
498 static int lmv_iocontrol(unsigned int cmd, struct obd_export *exp,
499                          int len, void *karg, void *uarg)
500 {
501         struct obd_device *obddev = class_exp2obd(exp);
502         struct lmv_obd *lmv = &obddev->u.lmv;
503         int i, rc = 0, set = 0;
504         ENTRY;
505
506         if (lmv->desc.ld_tgt_count == 0)
507                 RETURN(-ENOTTY);
508         
509         for (i = 0; i < lmv->desc.ld_tgt_count; i++) {
510                 int err;
511
512                 if (lmv->tgts[i].ltd_exp == NULL)
513                         continue;
514
515                 err = obd_iocontrol(cmd, lmv->tgts[i].ltd_exp, len, karg, uarg);
516                 if (err) {
517                         if (lmv->tgts[i].active) {
518                                 CERROR("error: iocontrol MDC %s on MDT"
519                                        "idx %d: err = %d\n",
520                                        lmv->tgts[i].uuid.uuid, i, err);
521                                 if (!rc)
522                                         rc = err;
523                         }
524                 } else
525                         set = 1;
526         }
527         if (!set && !rc)
528                 rc = -EIO;
529
530         RETURN(rc);
531 }
532
533 static int lmv_setup(struct obd_device *obd, obd_count len, void *buf)
534 {
535         int i, rc = 0;
536         struct lmv_desc *desc;
537         struct obd_uuid *uuids;
538         struct lmv_tgt_desc *tgts;
539         struct obd_device *tgt_obd;
540         struct lustre_cfg *lcfg = buf;
541         struct lmv_obd *lmv = &obd->u.lmv;
542         ENTRY;
543
544         if (lcfg->lcfg_inllen1 < 1) {
545                 CERROR("LMV setup requires a descriptor\n");
546                 RETURN(-EINVAL);
547         }
548
549         if (lcfg->lcfg_inllen2 < 1) {
550                 CERROR("LMV setup requires an MDT UUID list\n");
551                 RETURN(-EINVAL);
552         }
553
554         desc = (struct lmv_desc *)lcfg->lcfg_inlbuf1;
555         if (sizeof(*desc) > lcfg->lcfg_inllen1) {
556                 CERROR("descriptor size wrong: %d > %d\n",
557                        (int)sizeof(*desc), lcfg->lcfg_inllen1);
558                 RETURN(-EINVAL);
559         }
560
561         uuids = (struct obd_uuid *)lcfg->lcfg_inlbuf2;
562         if (sizeof(*uuids) * desc->ld_tgt_count != lcfg->lcfg_inllen2) {
563                 CERROR("UUID array size wrong: %u * %u != %u\n",
564                        sizeof(*uuids), desc->ld_tgt_count, lcfg->lcfg_inllen2);
565                 RETURN(-EINVAL);
566         }
567
568         lmv->tgts_size = sizeof(struct lmv_tgt_desc) * desc->ld_tgt_count;
569         OBD_ALLOC(lmv->tgts, lmv->tgts_size);
570         if (lmv->tgts == NULL) {
571                 CERROR("Out of memory\n");
572                 RETURN(-ENOMEM);
573         }
574
575         lmv->desc = *desc;
576         spin_lock_init(&lmv->lmv_lock);
577         
578         for (i = 0, tgts = lmv->tgts; i < desc->ld_tgt_count; i++, tgts++)
579                 tgts->uuid = uuids[i];
580         
581         lmv->max_cookiesize = 0;
582
583         lmv->max_easize = sizeof(struct lustre_id) *
584                 desc->ld_tgt_count + sizeof(struct mea);
585         
586         rc = lmv_setup_mgr(obd);
587         if (rc) {
588                 CERROR("Can't setup LMV object manager, "
589                        "error %d.\n", rc);
590                 OBD_FREE(lmv->tgts, lmv->tgts_size);
591         }
592
593         tgt_obd = class_find_client_obd(&lmv->tgts->uuid, LUSTRE_MDC_NAME,
594                                         &obd->obd_uuid);
595         if (!tgt_obd) {
596                 CERROR("Target %s not attached\n", lmv->tgts->uuid.uuid);
597                 RETURN(-EINVAL);
598         }
599
600         RETURN(rc);
601 }
602
603 static int lmv_cleanup(struct obd_device *obd, int flags) 
604 {
605         struct lmv_obd *lmv = &obd->u.lmv;
606         ENTRY;
607
608         lmv_cleanup_mgr(obd);
609         OBD_FREE(lmv->tgts, lmv->tgts_size);
610         
611         RETURN(0);
612 }
613
614 static int lmv_statfs(struct obd_device *obd, struct obd_statfs *osfs,
615                       unsigned long max_age)
616 {
617         struct lmv_obd *lmv = &obd->u.lmv;
618         struct obd_statfs temp;
619         int rc = 0, i;
620         ENTRY;
621         
622         rc = lmv_check_connect(obd);
623         if (rc)
624                 RETURN(rc);
625                 
626         for (i = 0; i < lmv->desc.ld_tgt_count; i++) {
627                 if (lmv->tgts[i].ltd_exp == NULL) {
628                         CWARN("%s: NULL export for %d\n", obd->obd_name, i);
629                         continue;
630                 }
631
632                 rc = obd_statfs(lmv->tgts[i].ltd_exp->exp_obd, &temp, max_age);
633                 if (rc) {
634                         CERROR("can't stat MDS #%d (%s), error %d\n", i,
635                                lmv->tgts[i].ltd_exp->exp_obd->obd_name,
636                                rc);
637                         RETURN(rc);
638                 }
639                 if (i == 0) {
640                         memcpy(osfs, &temp, sizeof(temp));
641                 } else {
642                         osfs->os_bavail += temp.os_bavail;
643                         osfs->os_blocks += temp.os_blocks;
644                         osfs->os_ffree += temp.os_ffree;
645                         osfs->os_files += temp.os_files;
646                 }
647         }
648         RETURN(rc);
649 }
650
651 static int lmv_getstatus(struct obd_export *exp, struct lustre_id *id)
652 {
653         struct obd_device *obd = exp->exp_obd;
654         struct lmv_obd *lmv = &obd->u.lmv;
655         int rc;
656         ENTRY;
657
658         rc = lmv_check_connect(obd);
659         if (rc)
660                 RETURN(rc);
661
662         rc = md_getstatus(lmv->tgts[0].ltd_exp, id);
663         id_group(id) = 0;
664         
665         RETURN(rc);
666 }
667
668 static int lmv_getattr(struct obd_export *exp, struct lustre_id *id,
669                        __u64 valid, unsigned int ea_size,
670                        struct ptlrpc_request **request)
671 {
672         struct obd_device *obd = exp->exp_obd;
673         struct lmv_obd *lmv = &obd->u.lmv;
674         int rc, i = id_group(id);
675         struct lmv_obj *obj;
676         ENTRY;
677
678         rc = lmv_check_connect(obd);
679         if (rc)
680                 RETURN(rc);
681
682         LASSERT(i < lmv->desc.ld_tgt_count);
683
684         rc = md_getattr(lmv->tgts[i].ltd_exp, id, valid,
685                         ea_size, request);
686         if (rc)
687                 RETURN(rc);
688         
689         obj = lmv_grab_obj(obd, id);
690         
691         CDEBUG(D_OTHER, "GETATTR for "DLID4" %s\n",
692                OLID4(id), obj ? "(splitted)" : "");
693
694         /*
695          * if object is splitted, then we loop over all the slaves and gather
696          * size attribute. In ideal world we would have to gather also mds field
697          * from all slaves, as object is spread over the cluster and this is
698          * definitely interesting information and it is not good to loss it,
699          * but...
700          */
701         if (obj) {
702                 struct mds_body *body;
703
704                 if (*request == NULL) {
705                         lmv_put_obj(obj);
706                         RETURN(rc);
707                 }
708                         
709                 body = lustre_msg_buf((*request)->rq_repmsg, 0,
710                                       sizeof(*body));
711                 LASSERT(body != NULL);
712
713                 lmv_lock_obj(obj);
714         
715                 for (i = 0; i < obj->objcount; i++) {
716
717                         if (lmv->tgts[i].ltd_exp == NULL) {
718                                 CWARN("%s: NULL export for %d\n",
719                                       obd->obd_name, i);
720                                 continue;
721                         }
722
723                         /* skip master obj. */
724                         if (id_equal_fid(&obj->id, &obj->objs[i].id))
725                                 continue;
726                         
727                         body->size += obj->objs[i].size;
728                 }
729
730                 lmv_unlock_obj(obj);
731                 lmv_put_obj(obj);
732         }
733         
734         RETURN(rc);
735 }
736
737 static int lmv_change_cbdata(struct obd_export *exp,
738                              struct lustre_id *id, 
739                              ldlm_iterator_t it,
740                              void *data)
741 {
742         struct obd_device *obd = exp->exp_obd;
743         struct lmv_obd *lmv = &obd->u.lmv;
744         int rc = 0;
745         ENTRY;
746         
747         rc = lmv_check_connect(obd);
748         if (rc)
749                 RETURN(rc);
750         
751         CDEBUG(D_OTHER, "CBDATA for "DLID4"\n", OLID4(id));
752         LASSERT(id_group(id) < lmv->desc.ld_tgt_count);
753
754         rc = md_change_cbdata(lmv->tgts[id_group(id)].ltd_exp,
755                               id, it, data);
756         
757         RETURN(rc);
758 }
759
760 static int lmv_change_cbdata_name(struct obd_export *exp,
761                                   struct lustre_id *pid,
762                                   char *name, int len,
763                                   struct lustre_id *cid,
764                                   ldlm_iterator_t it,
765                                   void *data)
766 {
767         struct obd_device *obd = exp->exp_obd;
768         struct lmv_obd *lmv = &obd->u.lmv;
769         struct lustre_id rcid = *cid;
770         struct lmv_obj *obj;
771         int rc = 0, mds;
772         ENTRY;
773
774         rc = lmv_check_connect(obd);
775         if (rc)
776                 RETURN(rc);
777
778         LASSERT(id_group(pid) < lmv->desc.ld_tgt_count);
779         LASSERT(id_group(cid) < lmv->desc.ld_tgt_count);
780         
781         CDEBUG(D_OTHER, "CBDATA for "DLID4":%*s -> "DLID4"\n",
782                OLID4(pid), len, name, OLID4(cid));
783
784         /* this is default mds for directory name belongs to. */
785         mds = id_group(pid);
786         obj = lmv_grab_obj(obd, pid);
787         if (obj) {
788                 /* directory is splitted. look for right mds for this name. */
789                 mds = raw_name2idx(obj->hashtype, obj->objcount, name, len);
790                 rcid = obj->objs[mds].id;
791                 mds = id_group(&rcid);
792                 lmv_put_obj(obj);
793         }
794         rc = md_change_cbdata(lmv->tgts[mds].ltd_exp, &rcid, it, data);
795         RETURN(rc);
796 }
797
798 static int lmv_valid_attrs(struct obd_export *exp, struct lustre_id *id) 
799 {
800         struct obd_device *obd = exp->exp_obd;
801         struct lmv_obd *lmv = &obd->u.lmv;
802         int rc = 0;
803         ENTRY;
804
805         rc = lmv_check_connect(obd);
806         if (rc)
807                 RETURN(rc);
808
809         CDEBUG(D_OTHER, "validate "DLID4"\n", OLID4(id));
810         LASSERT(id_group(id) < lmv->desc.ld_tgt_count);
811         rc = md_valid_attrs(lmv->tgts[id_group(id)].ltd_exp, id);
812         RETURN(rc);
813 }
814
815 int lmv_close(struct obd_export *exp, struct obdo *obdo,
816               struct obd_client_handle *och,
817               struct ptlrpc_request **request)
818 {
819         struct obd_device *obd = exp->exp_obd;
820         struct lmv_obd *lmv = &obd->u.lmv;
821         int rc, i = obdo->o_mds;
822         ENTRY;
823         
824         rc = lmv_check_connect(obd);
825         if (rc)
826                 RETURN(rc);
827
828         LASSERT(i < lmv->desc.ld_tgt_count);
829         CDEBUG(D_OTHER, "CLOSE %lu/%lu/%lu\n", (unsigned long)obdo->o_mds,
830                (unsigned long)obdo->o_id, (unsigned long)obdo->o_generation);
831         rc = md_close(lmv->tgts[i].ltd_exp, obdo, och, request);
832         RETURN(rc);
833 }
834
835 int lmv_get_mea_and_update_object(struct obd_export *exp, 
836                                   struct lustre_id *id)
837 {
838         struct obd_device *obd = exp->exp_obd;
839         struct lmv_obd *lmv = &obd->u.lmv;
840         struct ptlrpc_request *req = NULL;
841         struct lmv_obj *obj;
842         struct lustre_md md;
843         __u64 valid;
844         int mealen, rc;
845
846         md.mea = NULL;
847         mealen = MEA_SIZE_LMV(lmv);
848         
849         valid = OBD_MD_FLEASIZE | OBD_MD_FLDIREA;
850
851         /* time to update mea of parent id */
852         rc = md_getattr(lmv->tgts[id_group(id)].ltd_exp,
853                         id, valid, mealen, &req);
854         if (rc) {
855                 CERROR("md_getattr() failed, error %d\n", rc);
856                 GOTO(cleanup, rc);
857         }
858
859         rc = mdc_req2lustre_md(exp, req, 0, NULL, &md);
860         if (rc) {
861                 CERROR("mdc_req2lustre_md() failed, error %d\n", rc);
862                 GOTO(cleanup, rc);
863         }
864
865         if (md.mea == NULL)
866                 GOTO(cleanup, rc = -ENODATA);
867
868         obj = lmv_create_obj(exp, id, md.mea);
869         if (IS_ERR(obj))
870                 rc = PTR_ERR(obj);
871         
872         lmv_put_obj(obj);
873         obd_free_memmd(exp, (struct lov_stripe_md **)&md.mea);
874
875 cleanup:
876         if (req)
877                 ptlrpc_req_finished(req);
878         RETURN(rc);
879 }
880
881 int lmv_create(struct obd_export *exp, struct mdc_op_data *op_data,
882                const void *data, int datalen, int mode, __u32 uid,
883                __u32 gid, __u64 rdev, struct ptlrpc_request **request)
884 {
885         struct obd_device *obd = exp->exp_obd;
886         struct lmv_obd *lmv = &obd->u.lmv;
887         struct mds_body *body;
888         struct lmv_obj *obj;
889         int rc, mds, loop = 0;
890         ENTRY;
891
892         rc = lmv_check_connect(obd);
893         if (rc)
894                 RETURN(rc);
895
896         if (!lmv->desc.ld_active_tgt_count)
897                 RETURN(-EIO);
898 repeat:
899         LASSERT(++loop <= 2);
900         obj = lmv_grab_obj(obd, &op_data->id1);
901         if (obj) {
902                 mds = raw_name2idx(obj->hashtype, obj->objcount, 
903                                    op_data->name, op_data->namelen);
904                 op_data->id1 = obj->objs[mds].id;
905                 lmv_put_obj(obj);
906         }
907
908         CDEBUG(D_OTHER, "CREATE '%*s' on "DLID4"\n", op_data->namelen,
909                op_data->name, OLID4(&op_data->id1));
910         
911         rc = md_create(lmv->tgts[id_group(&op_data->id1)].ltd_exp, 
912                        op_data, data, datalen, mode, uid, gid, rdev,
913                        request);
914         if (rc == 0) {
915                 if (*request == NULL)
916                         RETURN(rc);
917
918                 body = lustre_msg_buf((*request)->rq_repmsg, 0,
919                                       sizeof(*body));
920                 if (body == NULL)
921                         RETURN(-ENOMEM);
922                 
923                 CDEBUG(D_OTHER, "created. "DLID4"\n", OLID4(&op_data->id1));
924         } else if (rc == -ERESTART) {
925                 /*
926                  * directory got splitted. time to update local object and
927                  * repeat the request with proper MDS.
928                  */
929                 rc = lmv_get_mea_and_update_object(exp, &op_data->id1);
930                 if (rc == 0) {
931                         ptlrpc_req_finished(*request);
932                         goto repeat;
933                 }
934         }
935         RETURN(rc);
936 }
937
938 int lmv_done_writing(struct obd_export *exp, struct obdo *obdo)
939 {
940         struct obd_device *obd = exp->exp_obd;
941         struct lmv_obd *lmv = &obd->u.lmv;
942         int rc;
943         ENTRY;
944         rc = lmv_check_connect(obd);
945         if (rc)
946                 RETURN(rc);
947
948         /* FIXME: choose right MDC here */
949         CWARN("this method isn't implemented yet\n");
950         rc = md_done_writing(lmv->tgts[0].ltd_exp, obdo);
951         RETURN(rc);
952 }
953
954 int lmv_enqueue_slaves(struct obd_export *exp, int locktype,
955                        struct lookup_intent *it, int lockmode,
956                        struct mdc_op_data *data, struct lustre_handle *lockh,
957                        void *lmm, int lmmsize, ldlm_completion_callback cb_compl,
958                        ldlm_blocking_callback cb_blocking, void *cb_data)
959 {
960         struct obd_device *obd = exp->exp_obd;
961         struct lmv_obd *lmv = &obd->u.lmv;
962         struct mea *mea = data->mea1;
963         struct mdc_op_data data2;
964         int i, rc, mds;
965         ENTRY;
966
967         LASSERT(mea != NULL);
968         for (i = 0; i < mea->mea_count; i++) {
969                 memset(&data2, 0, sizeof(data2));
970                 data2.id1 = mea->mea_ids[i];
971                 mds = id_group(&data2.id1);
972                 
973                 if (lmv->tgts[mds].ltd_exp == NULL)
974                         continue;
975
976                 rc = md_enqueue(lmv->tgts[mds].ltd_exp, locktype, it, 
977                                 lockmode, &data2, lockh + i, lmm, lmmsize, 
978                                 cb_compl, cb_blocking, cb_data);
979                 
980                 CDEBUG(D_OTHER, "take lock on slave "DLID4" -> %d/%d\n",
981                        OLID4(&mea->mea_ids[i]), rc, it->d.lustre.it_status);
982                 if (rc)
983                         GOTO(cleanup, rc);
984                 if (it->d.lustre.it_data) {
985                         struct ptlrpc_request *req;
986                         req = (struct ptlrpc_request *) it->d.lustre.it_data;
987                         ptlrpc_req_finished(req);
988                 }
989                 
990                 if (it->d.lustre.it_status)
991                         GOTO(cleanup, rc = it->d.lustre.it_status);
992         }
993         RETURN(0);
994         
995 cleanup:
996         /* drop all taken locks */
997         while (--i >= 0) {
998                 if (lockh[i].cookie)
999                         ldlm_lock_decref(lockh + i, lockmode);
1000                 lockh[i].cookie = 0;
1001         }
1002         RETURN(rc);
1003 }
1004
1005 int lmv_enqueue(struct obd_export *exp, int lock_type,
1006                 struct lookup_intent *it, int lock_mode,
1007                 struct mdc_op_data *data, struct lustre_handle *lockh,
1008                 void *lmm, int lmmsize, ldlm_completion_callback cb_compl,
1009                 ldlm_blocking_callback cb_blocking, void *cb_data)
1010 {
1011         struct obd_device *obd = exp->exp_obd;
1012         struct lmv_obd *lmv = &obd->u.lmv;
1013         struct lmv_obj *obj;
1014         int rc, mds;
1015         ENTRY;
1016
1017         rc = lmv_check_connect(obd);
1018         if (rc)
1019                 RETURN(rc);
1020
1021         if (data->mea1 && it->it_op == IT_UNLINK) {
1022                 rc = lmv_enqueue_slaves(exp, lock_type, it, lock_mode,
1023                                         data, lockh, lmm, lmmsize,
1024                                         cb_compl, cb_blocking, cb_data);
1025                 RETURN(rc);
1026         }
1027
1028         if (data->namelen) {
1029                 obj = lmv_grab_obj(obd, &data->id1);
1030                 if (obj) {
1031                         /* directory is splitted. look for right mds for this
1032                          * name */
1033                         mds = raw_name2idx(obj->hashtype, obj->objcount,
1034                                            (char *)data->name, data->namelen);
1035                         data->id1 = obj->objs[mds].id;
1036                         lmv_put_obj(obj);
1037                 }
1038         }
1039         CDEBUG(D_OTHER, "ENQUEUE '%s' on "DLID4"\n", LL_IT2STR(it),
1040                OLID4(&data->id1));
1041         
1042         rc = md_enqueue(lmv->tgts[id_group(&data->id1)].ltd_exp, 
1043                         lock_type, it, lock_mode, data, lockh, lmm, 
1044                         lmmsize, cb_compl, cb_blocking, cb_data);
1045         RETURN(rc);
1046 }
1047
1048 int lmv_getattr_lock(struct obd_export *exp, struct lustre_id *id,
1049                      char *filename, int namelen, __u64 valid,
1050                      unsigned int ea_size, struct ptlrpc_request **request)
1051 {
1052         int rc, mds = id_group(id), loop = 0;
1053         struct obd_device *obd = exp->exp_obd;
1054         struct lmv_obd *lmv = &obd->u.lmv;
1055         struct lustre_id rid = *id;
1056         struct mds_body *body;
1057         struct lmv_obj *obj;
1058         __u64 old_valid;
1059         ENTRY;
1060         
1061         rc = lmv_check_connect(obd);
1062         if (rc)
1063                 RETURN(rc);
1064 repeat:
1065         LASSERT(++loop <= 2);
1066         obj = lmv_grab_obj(obd, id);
1067         if (obj) {
1068                 /* directory is splitted. look for right mds for this name */
1069                 mds = raw_name2idx(obj->hashtype, obj->objcount, 
1070                                    filename, namelen - 1);
1071                 rid = obj->objs[mds].id;
1072                 lmv_put_obj(obj);
1073         }
1074         
1075         CDEBUG(D_OTHER, "getattr_lock for %*s on "DLID4" -> "DLID4"\n",
1076                namelen, filename, OLID4(id), OLID4(&rid));
1077
1078         old_valid = valid;
1079
1080         /*
1081          * here should be applied OBD_MD_FID to ->valid, because otherwise,
1082          * mds_getattr_lock() will not fetch fid component of lustre_id and
1083          * thus, next call to md_getattr_lock() will be performed to wrong mds.
1084          */
1085         if (!(old_valid & OBD_MD_FID))
1086                 valid |= OBD_MD_FID;
1087         
1088         rc = md_getattr_lock(lmv->tgts[id_group(&rid)].ltd_exp, 
1089                              &rid, filename, namelen, valid,
1090                              ea_size, request);
1091         if (rc == 0) {
1092                 /*
1093                  * this could be cross-node reference. in this case all we have
1094                  * right now is lustre_id triple. we'd like to find other
1095                  * attributes.
1096                  */
1097                 body = lustre_msg_buf((*request)->rq_repmsg, 0, sizeof(*body));
1098                 LASSERT(body != NULL);
1099                 if (body->valid & OBD_MD_MDS) {
1100                         struct ptlrpc_request *req = NULL;
1101                         
1102                         rid = body->id1;
1103                         CDEBUG(D_OTHER, "request attrs for "DLID4"\n", OLID4(&rid));
1104
1105                         /* 
1106                          * turning OBD_MD_FID fetching off, as we already have
1107                          * full lustre_id and do need to fetch fid component
1108                          * again. This will help to make thing slightly faster.
1109                          */
1110                         if (!(old_valid & OBD_MD_FID))
1111                                 valid &= ~OBD_MD_FID;
1112                         
1113                         rc = md_getattr_lock(lmv->tgts[id_group(&rid)].ltd_exp, 
1114                                              &rid, NULL, 1, valid, ea_size, &req);
1115                         ptlrpc_req_finished(*request);
1116                         *request = req;
1117                 }
1118         } else if (rc == -ERESTART) {
1119                 /* directory got splitted. time to update local object and
1120                  * repeat the request with proper MDS */
1121                 rc = lmv_get_mea_and_update_object(exp, &rid);
1122                 if (rc == 0) {
1123                         ptlrpc_req_finished(*request);
1124                         goto repeat;
1125                 }
1126         }
1127         RETURN(rc);
1128 }
1129
1130 /*
1131  * llite passes id of an target inode in data->id1 and id of directory in
1132  * data->id2
1133  */
1134 int lmv_link(struct obd_export *exp, struct mdc_op_data *data,
1135              struct ptlrpc_request **request)
1136 {
1137         struct obd_device *obd = exp->exp_obd;
1138         struct lmv_obd *lmv = &obd->u.lmv;
1139         struct lmv_obj *obj;
1140         int rc;
1141         ENTRY;
1142         
1143         rc = lmv_check_connect(obd);
1144         if (rc)
1145                 RETURN(rc);
1146
1147         if (data->namelen != 0) {
1148                 /* usual link request */
1149                 obj = lmv_grab_obj(obd, &data->id1);
1150                 if (obj) {
1151                         rc = raw_name2idx(obj->hashtype, obj->objcount, 
1152                                           data->name, data->namelen);
1153                         data->id1 = obj->objs[rc].id;
1154                         lmv_put_obj(obj);
1155                 }
1156                 
1157                 CDEBUG(D_OTHER,"link "DLID4":%*s to "DLID4"\n",
1158                        OLID4(&data->id2), data->namelen, data->name,
1159                        OLID4(&data->id1));
1160         } else {
1161                 /* request from MDS to acquire i_links for inode by id1 */
1162                 CDEBUG(D_OTHER, "inc i_nlinks for "DLID4"\n",
1163                        OLID4(&data->id1));
1164         }
1165                         
1166         rc = md_link(lmv->tgts[id_group(&data->id1)].ltd_exp, 
1167                      data, request);
1168         RETURN(rc);
1169 }
1170
1171 int lmv_rename(struct obd_export *exp, struct mdc_op_data *data,
1172                const char *old, int oldlen, const char *new, int newlen,
1173                struct ptlrpc_request **request)
1174 {
1175         struct obd_device *obd = exp->exp_obd;
1176         struct lmv_obd *lmv = &obd->u.lmv;
1177         struct lmv_obj *obj;
1178         int rc, mds;
1179         ENTRY;
1180
1181         CDEBUG(D_OTHER, "rename %*s in "DLID4" to %*s in "DLID4"\n",
1182                oldlen, old, OLID4(&data->id1), newlen, new, OLID4(&data->id2));
1183
1184         rc = lmv_check_connect(obd);
1185         if (rc)
1186                 RETURN(rc);
1187
1188         if (oldlen == 0) {
1189                 /*
1190                  * MDS with old dir entry is asking another MDS to create name
1191                  * there.
1192                  */
1193                 CDEBUG(D_OTHER,
1194                        "create %*s(%d/%d) in "DLID4" pointing "
1195                        "to "DLID4"\n", newlen, new, oldlen, newlen,
1196                        OLID4(&data->id2), OLID4(&data->id1));
1197
1198                 mds = id_group(&data->id2);
1199
1200                 /* 
1201                  * target directory can be splitted, sowe should forward request
1202                  * to the right MDS.
1203                  */
1204                 obj = lmv_grab_obj(obd, &data->id2);
1205                 if (obj) {
1206                         mds = raw_name2idx(obj->hashtype, obj->objcount, 
1207                                            (char *)new, newlen);
1208                         data->id2 = obj->objs[mds].id;
1209                         CDEBUG(D_OTHER, "forward to MDS #%u ("DLID4")\n", mds,
1210                                OLID4(&data->id2));
1211                         lmv_put_obj(obj);
1212                 }
1213                 goto request;
1214         }
1215
1216         obj = lmv_grab_obj(obd, &data->id1);
1217         if (obj) {
1218                 /*
1219                  * directory is already splitted, so we have to forward request
1220                  * to the right MDS.
1221                  */
1222                 mds = raw_name2idx(obj->hashtype, obj->objcount, 
1223                                    (char *)old, oldlen);
1224                 data->id1 = obj->objs[mds].id;
1225                 CDEBUG(D_OTHER, "forward to MDS #%u ("DLID4")\n", mds,
1226                        OLID4(&data->id1));
1227                 lmv_put_obj(obj);
1228         }
1229
1230         obj = lmv_grab_obj(obd, &data->id2);
1231         if (obj) {
1232                 /*
1233                  * directory is already splitted, so we have to forward request
1234                  * to the right MDS.
1235                  */
1236                 mds = raw_name2idx(obj->hashtype, obj->objcount, 
1237                                    (char *)new, newlen);
1238                 
1239                 data->id2 = obj->objs[mds].id;
1240                 CDEBUG(D_OTHER, "forward to MDS #%u ("DLID4")\n", mds,
1241                        OLID4(&data->id2));
1242                 lmv_put_obj(obj);
1243         }
1244         
1245         mds = id_group(&data->id1);
1246
1247 request:
1248         if (id_group(&data->id1) != id_group(&data->id2)) {
1249                 CDEBUG(D_OTHER,"cross-node rename "DLID4"/%*s to "DLID4"/%*s\n",
1250                        OLID4(&data->id1), oldlen, old, OLID4(&data->id2),
1251                        newlen, new);
1252         }
1253
1254         rc = md_rename(lmv->tgts[mds].ltd_exp, data, old, oldlen,
1255                        new, newlen, request); 
1256         RETURN(rc);
1257 }
1258
1259 int lmv_setattr(struct obd_export *exp, struct mdc_op_data *data,
1260                 struct iattr *iattr, void *ea, int ealen, void *ea2,
1261                 int ea2len, struct ptlrpc_request **request)
1262 {
1263         struct obd_device *obd = exp->exp_obd;
1264         struct lmv_obd *lmv = &obd->u.lmv;
1265         struct ptlrpc_request *req;
1266         struct mds_body *body;
1267         struct lmv_obj *obj;
1268         int rc = 0, i;
1269         ENTRY;
1270
1271         rc = lmv_check_connect(obd);
1272         if (rc)
1273                 RETURN(rc);
1274
1275         obj = lmv_grab_obj(obd, &data->id1);
1276         
1277         CDEBUG(D_OTHER, "SETATTR for "DLID4", valid 0x%x%s\n",
1278                OLID4(&data->id1), iattr->ia_valid, obj ? ", splitted" : "");
1279         
1280         if (obj) {
1281                 for (i = 0; i < obj->objcount; i++) {
1282                         data->id1 = obj->objs[i].id;
1283                         
1284                         rc = md_setattr(lmv->tgts[id_group(&data->id1)].ltd_exp, 
1285                                         data, iattr, ea, ealen, ea2, ea2len, &req);
1286
1287                         if (id_equal_fid(&obj->id, &obj->objs[i].id)) {
1288                                 /*
1289                                  * this is master object and this request should
1290                                  * be returned back to llite.
1291                                  */
1292                                 *request = req;
1293                         } else {
1294                                 ptlrpc_req_finished(req);
1295                         }
1296
1297                         if (rc)
1298                                 break;
1299                 }
1300                 lmv_put_obj(obj);
1301         } else {
1302                 LASSERT(id_group(&data->id1) < lmv->desc.ld_tgt_count);
1303                 rc = md_setattr(lmv->tgts[id_group(&data->id1)].ltd_exp,
1304                                 data, iattr, ea, ealen, ea2, ea2len, request); 
1305                 if (rc == 0) {
1306                         body = lustre_msg_buf((*request)->rq_repmsg, 0,
1307                                               sizeof(*body));
1308                         LASSERT(body != NULL);
1309                         LASSERT(id_group(&body->id1) == id_group(&data->id1));
1310                 }
1311         }
1312         RETURN(rc);
1313 }
1314
1315 int lmv_sync(struct obd_export *exp, struct lustre_id *id,
1316              struct ptlrpc_request **request)
1317 {
1318         struct obd_device *obd = exp->exp_obd;
1319         struct lmv_obd *lmv = &obd->u.lmv;
1320         int rc;
1321         ENTRY;
1322
1323         rc = lmv_check_connect(obd);
1324         if (rc)
1325                 RETURN(rc);
1326
1327         rc = md_sync(lmv->tgts[id_group(id)].ltd_exp, 
1328                      id, request);
1329         RETURN(rc);
1330 }
1331
1332 int lmv_dirobj_blocking_ast(struct ldlm_lock *lock, 
1333                             struct ldlm_lock_desc *desc,
1334                             void *data, int flag)
1335 {
1336         struct lustre_handle lockh;
1337         struct lmv_obj *obj;
1338         int rc;
1339         ENTRY;
1340
1341         switch (flag) {
1342         case LDLM_CB_BLOCKING:
1343                 ldlm_lock2handle(lock, &lockh);
1344                 rc = ldlm_cli_cancel(&lockh);
1345                 if (rc < 0) {
1346                         CDEBUG(D_INODE, "ldlm_cli_cancel: %d\n", rc);
1347                         RETURN(rc);
1348                 }
1349                 break;
1350         case LDLM_CB_CANCELING:
1351                 /* time to drop cached attrs for dirobj */
1352                 obj = lock->l_ast_data;
1353                 if (obj) {
1354                         CDEBUG(D_OTHER, "cancel %s on "LPU64"/"LPU64
1355                                ", master "DLID4"\n",
1356                                lock->l_resource->lr_name.name[3] == 1 ?
1357                                "LOOKUP" : "UPDATE",
1358                                lock->l_resource->lr_name.name[0],
1359                                lock->l_resource->lr_name.name[1], 
1360                                OLID4(&obj->id));
1361                         lmv_put_obj(obj);
1362                 }
1363                 break;
1364         default:
1365                 LBUG();
1366         }
1367         RETURN(0);
1368 }
1369
1370 void lmv_remove_dots(struct page *page)
1371 {
1372         char *kaddr = page_address(page);
1373         unsigned limit = PAGE_CACHE_SIZE;
1374         unsigned offs, rec_len;
1375         struct ext2_dir_entry_2 *p;
1376
1377         for (offs = 0; offs <= limit - EXT2_DIR_REC_LEN(1); offs += rec_len) {
1378                 p = (struct ext2_dir_entry_2 *)(kaddr + offs);
1379                 rec_len = le16_to_cpu(p->rec_len);
1380
1381                 if ((p->name_len == 1 && p->name[0] == '.') ||
1382                     (p->name_len == 2 && p->name[0] == '.' && p->name[1] == '.'))
1383                         p->inode = 0;
1384         }
1385 }
1386
1387 int lmv_readpage(struct obd_export *exp, struct lustre_id *id,
1388                  __u64 offset, struct page *page,
1389                  struct ptlrpc_request **request)
1390 {
1391         struct obd_device *obd = exp->exp_obd;
1392         struct lmv_obd *lmv = &obd->u.lmv;
1393         struct lustre_id rid = *id;
1394         struct lmv_obj *obj;
1395         int rc, i;
1396         ENTRY;
1397
1398 #warning "we need well-desgined readdir() implementation"
1399         rc = lmv_check_connect(obd);
1400         if (rc)
1401                 RETURN(rc);
1402
1403         LASSERT(id_group(id) < lmv->desc.ld_tgt_count);
1404         CDEBUG(D_OTHER, "READPAGE at %llu from "DLID4"\n",
1405                offset, OLID4(&rid));
1406
1407         obj = lmv_grab_obj(obd, id);
1408         if (obj) {
1409                 lmv_lock_obj(obj);
1410
1411                 /* find dirobj containing page with requested offset. */
1412                 for (i = 0; i < obj->objcount; i++) {
1413                         if (offset < obj->objs[i].size)
1414                                 break;
1415                         offset -= obj->objs[i].size;
1416                 }
1417                 rid = obj->objs[i].id;
1418                 
1419                 lmv_unlock_obj(obj);
1420                 lmv_put_obj(obj);
1421                 
1422                 CDEBUG(D_OTHER, "forward to "DLID4" with offset %lu\n",
1423                        OLID4(&rid), (unsigned long)offset);
1424         }
1425         rc = md_readpage(lmv->tgts[id_group(&rid)].ltd_exp, &rid, 
1426                          offset, page, request);
1427         
1428         if (rc == 0 && !id_equal_fid(&rid, id))
1429                 /* this page isn't from master object. To avoid "." and ".." 
1430                  * duplication in directory, we have to remove them from all
1431                  * slave objects */
1432                 lmv_remove_dots(page);
1433         
1434         RETURN(rc);
1435 }
1436
1437 int lmv_unlink_slaves(struct obd_export *exp, struct mdc_op_data *data,
1438                       struct ptlrpc_request **req)
1439 {
1440         struct obd_device *obd = exp->exp_obd;
1441         struct lmv_obd *lmv = &obd->u.lmv;
1442         struct mea *mea = data->mea1;
1443         struct mdc_op_data data2;
1444         int i, rc = 0;
1445         ENTRY;
1446
1447         LASSERT(mea != NULL);
1448         for (i = 0; i < mea->mea_count; i++) {
1449                 memset(&data2, 0, sizeof(data2));
1450                 data2.id1 = mea->mea_ids[i];
1451                 data2.create_mode = MDS_MODE_DONT_LOCK | S_IFDIR;
1452                 
1453                 if (lmv->tgts[id_group(&data2.id1)].ltd_exp == NULL)
1454                         continue;
1455
1456                 rc = md_unlink(lmv->tgts[id_group(&data2.id1)].ltd_exp,
1457                                &data2, req);
1458                 
1459                 CDEBUG(D_OTHER, "unlink slave "DLID4" -> %d\n",
1460                        OLID4(&mea->mea_ids[i]), rc);
1461                 
1462                 if (*req) {
1463                         ptlrpc_req_finished(*req);
1464                         *req = NULL;
1465                 }
1466                 if (rc)
1467                         RETURN(rc);
1468         }
1469         RETURN(rc);
1470 }
1471
1472 int lmv_delete_inode(struct obd_export *exp, struct lustre_id *id)
1473 {
1474         LASSERT(exp && id);
1475         
1476         ENTRY;
1477         if (lmv_delete_obj(exp, id)) {
1478                 CDEBUG(D_OTHER, "lmv object "DLID4" is destroyed.\n",
1479                        OLID4(id));
1480         }
1481         RETURN(0);
1482 }
1483
1484 int lmv_unlink(struct obd_export *exp, struct mdc_op_data *data,
1485                struct ptlrpc_request **request)
1486 {
1487         struct obd_device *obd = exp->exp_obd;
1488         struct lmv_obd *lmv = &obd->u.lmv;
1489         int rc, i = 0;
1490         ENTRY;
1491         
1492         rc = lmv_check_connect(obd);
1493         if (rc)
1494                 RETURN(rc);
1495
1496         if (data->namelen == 0 && data->mea1 != NULL) {
1497                 /* mds asks to remove slave objects */
1498                 rc = lmv_unlink_slaves(exp, data, request);
1499                 RETURN(rc);
1500         }
1501
1502         if (data->namelen != 0) {
1503                 struct lmv_obj *obj;
1504                 
1505                 obj = lmv_grab_obj(obd, &data->id1);
1506                 if (obj) {
1507                         i = raw_name2idx(obj->hashtype, obj->objcount,
1508                                          data->name, data->namelen);
1509                         data->id1 = obj->objs[i].id;
1510                         lmv_put_obj(obj);
1511                 }
1512                 CDEBUG(D_OTHER, "unlink '%*s' in "DLID4" -> %u\n",
1513                        data->namelen, data->name, OLID4(&data->id1),
1514                        i);
1515         } else {
1516                 CDEBUG(D_OTHER, "drop i_nlink on "DLID4"\n",
1517                        OLID4(&data->id1));
1518         }
1519         rc = md_unlink(lmv->tgts[id_group(&data->id1)].ltd_exp, 
1520                        data, request);
1521         RETURN(rc);
1522 }
1523
1524 struct obd_device *lmv_get_real_obd(struct obd_export *exp,
1525                                     char *name, int len)
1526 {
1527         struct obd_device *obd = exp->exp_obd;
1528         struct lmv_obd *lmv = &obd->u.lmv;
1529         int rc;
1530         ENTRY;
1531
1532         rc = lmv_check_connect(obd);
1533         if (rc)
1534                 RETURN(ERR_PTR(rc));
1535         obd = lmv->tgts[0].ltd_exp->exp_obd;
1536         EXIT;
1537         
1538         return obd;
1539 }
1540
1541 int lmv_init_ea_size(struct obd_export *exp, int easize,
1542                      int cookiesize)
1543 {
1544         struct obd_device *obd = exp->exp_obd;
1545         struct lmv_obd *lmv = &obd->u.lmv;
1546         int i, rc = 0, change = 0;
1547         ENTRY;
1548
1549         if (lmv->max_easize < easize) {
1550                 lmv->max_easize = easize;
1551                 change = 1;
1552         }
1553         if (lmv->max_cookiesize < cookiesize) {
1554                 lmv->max_cookiesize = cookiesize;
1555                 change = 1;
1556         }
1557         if (change == 0)
1558                 RETURN(0);
1559         
1560         if (lmv->connected == 0)
1561                 RETURN(0);
1562
1563         for (i = 0; i < lmv->desc.ld_tgt_count; i++) {
1564                 if (lmv->tgts[i].ltd_exp == NULL) {
1565                         CWARN("%s: NULL export for %d\n", obd->obd_name, i);
1566                         continue;
1567                 }
1568
1569                 rc = obd_init_ea_size(lmv->tgts[i].ltd_exp, easize, cookiesize);
1570                 if (rc) {
1571                         CERROR("obd_init_ea_size() failed on MDT target %d, "
1572                                "error %d.\n", i, rc);
1573                         break;
1574                 }
1575         }
1576         RETURN(rc);
1577 }
1578
1579 int lmv_obd_create_single(struct obd_export *exp, struct obdo *oa,
1580                           struct lov_stripe_md **ea, struct obd_trans_info *oti)
1581 {
1582         struct obd_device *obd = exp->exp_obd;
1583         struct lmv_obd *lmv = &obd->u.lmv;
1584         struct lov_stripe_md obj_md;
1585         struct lov_stripe_md *obj_mdp = &obj_md;
1586         int rc = 0;
1587         ENTRY;
1588
1589         LASSERT(ea == NULL);
1590         LASSERT(oa->o_mds < lmv->desc.ld_tgt_count);
1591
1592         rc = obd_create(lmv->tgts[oa->o_mds].ltd_exp,
1593                         oa, &obj_mdp, oti);
1594
1595         RETURN(rc);
1596 }
1597
1598 int lmv_getready(struct obd_export *exp)
1599 {
1600         struct obd_device *obd = exp->exp_obd;
1601         int rc = 0;
1602         
1603         ENTRY;
1604         rc = lmv_check_connect(obd);
1605         RETURN(rc);
1606 }
1607
1608 /*
1609  * to be called from MDS only. @oa should have correct store cookie and o_fid
1610  * values for "master" object, as it will be used.
1611  */
1612 int lmv_obd_create(struct obd_export *exp, struct obdo *oa,
1613                    struct lov_stripe_md **ea, struct obd_trans_info *oti)
1614 {
1615         struct obd_device *obd = exp->exp_obd;
1616         struct lmv_obd *lmv = &obd->u.lmv;
1617         struct lustre_id mid;
1618         int i, c, rc = 0;
1619         struct mea *mea;
1620         ENTRY;
1621
1622         rc = lmv_check_connect(obd);
1623         if (rc)
1624                 RETURN(rc);
1625
1626         LASSERT(oa != NULL);
1627         
1628         if (ea == NULL) {
1629                 rc = lmv_obd_create_single(exp, oa, NULL, oti);
1630                 if (rc)
1631                         CERROR("Can't create object, rc = %d\n", rc);
1632                 RETURN(rc);
1633         }
1634
1635         if (*ea == NULL) {
1636                 rc = obd_alloc_diskmd(exp, (struct lov_mds_md **)ea);
1637                 if (rc < 0) {
1638                         CERROR("obd_alloc_diskmd() failed, error %d\n",
1639                                rc);
1640                         RETURN(rc);
1641                 } else
1642                         rc = 0;
1643                 
1644                 if (*ea == NULL)
1645                         RETURN(-ENOMEM);
1646         }
1647
1648         /* 
1649          * here we should take care about splitted dir, so store cookie and fid
1650          * for "master" object should already be allocated and passed in @oa.
1651          */
1652         LASSERT(oa->o_id != 0);
1653         LASSERT(oa->o_fid != 0);
1654
1655         /* save "master" object id */
1656         obdo2id(&mid, oa);
1657
1658         mea = (struct mea *)*ea;
1659         mea->mea_master = -1;
1660         mea->mea_magic = MEA_MAGIC_ALL_CHARS;
1661
1662         if (!mea->mea_count || mea->mea_count > lmv->desc.ld_tgt_count)
1663                 mea->mea_count = lmv->desc.ld_tgt_count;
1664
1665         for (i = 0, c = 0; c < mea->mea_count && i < lmv->desc.ld_tgt_count; i++) {
1666                 struct lov_stripe_md obj_md;
1667                 struct lov_stripe_md *obj_mdp = &obj_md;
1668                
1669                 if (lmv->tgts[i].ltd_exp == NULL) {
1670                         /* this is "master" MDS */
1671                         mea->mea_master = i;
1672                         mea->mea_ids[c] = mid;
1673                         c++;
1674                         continue;
1675                 }
1676
1677                 /*
1678                  * "master" MDS should always be part of stripped dir,
1679                  * so scan for it.
1680                  */
1681                 if (mea->mea_master == -1 && c == mea->mea_count - 1)
1682                         continue;
1683
1684                 oa->o_valid = OBD_MD_FLGENER | OBD_MD_FLTYPE | OBD_MD_FLMODE |
1685                         OBD_MD_FLUID | OBD_MD_FLGID | OBD_MD_FLID;
1686
1687                 rc = obd_create(lmv->tgts[c].ltd_exp, oa, &obj_mdp, oti);
1688                 if (rc) {
1689                         CERROR("obd_create() failed on MDT target %d, "
1690                                "error %d\n", c, rc);
1691                         RETURN(rc);
1692                 }
1693
1694                 CDEBUG(D_OTHER, "dirobj at mds %d: "LPU64"/%u\n",
1695                        i, oa->o_id, oa->o_generation);
1696
1697
1698                 /*
1699                  * here, when object is created (or it is master and was passed
1700                  * from caller) on desired MDS we save its fid to local mea_ids.
1701                  */
1702                 LASSERT(oa->o_fid);
1703
1704                 /* 
1705                  * store cookie should be defined here for both cases (master
1706                  * object and not master), because master is already created.
1707                  */
1708                 LASSERT(oa->o_id);
1709
1710                 /* fill mea by store cookie and fid */
1711                 obdo2id(&mea->mea_ids[c], oa);
1712                 c++;
1713         }
1714         LASSERT(c == mea->mea_count);
1715
1716         CDEBUG(D_OTHER, "%d dirobjects created\n",
1717                (int)mea->mea_count);
1718         
1719         RETURN(rc);
1720 }
1721
1722 static int lmv_llog_init(struct obd_device *obd, struct obd_llogs *llogs, 
1723                          struct obd_device *tgt, int count,
1724                          struct llog_catid *logid)
1725 {
1726         struct llog_ctxt *ctxt;
1727         int rc;
1728         ENTRY;
1729
1730         rc = obd_llog_setup(obd, llogs, LLOG_CONFIG_REPL_CTXT, tgt, 0, NULL,
1731                             &llog_client_ops);
1732         if (rc == 0) {
1733                 ctxt = llog_get_context(llogs, LLOG_CONFIG_REPL_CTXT);
1734                 ctxt->loc_imp = tgt->u.cli.cl_import;
1735         }
1736
1737         RETURN(rc);
1738 }
1739
1740 static int lmv_llog_finish(struct obd_device *obd,
1741                            struct obd_llogs *llogs, int count)
1742 {
1743         int rc;
1744         ENTRY;
1745
1746         rc = obd_llog_cleanup(llog_get_context(llogs, LLOG_CONFIG_REPL_CTXT));
1747         RETURN(rc);
1748 }
1749
1750 static int lmv_get_info(struct obd_export *exp, __u32 keylen,
1751                         void *key, __u32 *vallen, void *val)
1752 {
1753         struct obd_device *obd;
1754         struct lmv_obd *lmv;
1755         int rc = 0;
1756         ENTRY;
1757
1758         obd = class_exp2obd(exp);
1759         if (obd == NULL) {
1760                 CDEBUG(D_IOCTL, "invalid client cookie "LPX64"\n",
1761                        exp->exp_handle.h_cookie);
1762                 RETURN(-EINVAL);
1763         }
1764
1765         lmv = &obd->u.lmv;
1766         if (keylen == 6 && memcmp(key, "mdsize", 6) == 0) {
1767                 __u32 *mdsize = val;
1768                 *vallen = sizeof(__u32);
1769                 *mdsize = sizeof(struct lustre_id) * lmv->desc.ld_tgt_count
1770                         + sizeof(struct mea);
1771                 RETURN(0);
1772         } else if (keylen == 6 && memcmp(key, "mdsnum", 6) == 0) {
1773                 struct obd_uuid *cluuid = &lmv->cluuid;
1774                 struct lmv_tgt_desc *tgts;
1775                 __u32 *mdsnum = val;
1776                 int i;
1777
1778                 for (i = 0, tgts = lmv->tgts; i < lmv->desc.ld_tgt_count; i++, tgts++) {
1779                         if (obd_uuid_equals(&tgts->uuid, cluuid)) {
1780                                 *vallen = sizeof(__u32);
1781                                 *mdsnum = i;
1782                                 RETURN(0);
1783                         }
1784                 }
1785                 LASSERT(0);
1786         } else if (keylen == 6 && memcmp(key, "rootid", 6) == 0) {
1787                 /* getting rootid from first MDS. */
1788                 rc = obd_get_info(lmv->tgts[0].ltd_exp, keylen, key,
1789                                   vallen, val);
1790                 RETURN(rc);
1791         } else if (keylen >= strlen("lmvdesc") && strcmp(key, "lmvdesc") == 0) {
1792                 struct lmv_desc *desc_ret = val;
1793                 *desc_ret = lmv->desc;
1794                 RETURN(0);
1795         }
1796
1797         CDEBUG(D_IOCTL, "invalid key\n");
1798         RETURN(-EINVAL);
1799 }
1800
1801 int lmv_set_info(struct obd_export *exp, obd_count keylen,
1802                  void *key, obd_count vallen, void *val)
1803 {
1804         struct obd_device *obd;
1805         struct lmv_obd *lmv;
1806         ENTRY;
1807
1808         obd = class_exp2obd(exp);
1809         if (obd == NULL) {
1810                 CDEBUG(D_IOCTL, "invalid client cookie "LPX64"\n",
1811                        exp->exp_handle.h_cookie);
1812                 RETURN(-EINVAL);
1813         }
1814         lmv = &obd->u.lmv;
1815
1816         if (keylen >= strlen("inter_mds") && strcmp(key, "inter_mds") == 0) {
1817                 lmv->server_timeout = 1;
1818                 lmv_set_timeouts(obd);
1819                 RETURN(0);
1820         }
1821         
1822         RETURN(-EINVAL);
1823 }
1824
1825 int lmv_packmd(struct obd_export *exp, struct lov_mds_md **lmmp,
1826                struct lov_stripe_md *lsm)
1827 {
1828         struct obd_device *obd = class_exp2obd(exp);
1829         struct lmv_obd *lmv = &obd->u.lmv;
1830         struct mea *meap, *lsmp;
1831         int mea_size, i;
1832         ENTRY;
1833
1834         mea_size = (sizeof(struct lustre_id) * 
1835                     lmv->desc.ld_tgt_count) + sizeof(struct mea);
1836         if (!lmmp)
1837                 RETURN(mea_size);
1838
1839         if (*lmmp && !lsm) {
1840                 OBD_FREE(*lmmp, mea_size);
1841                 *lmmp = NULL;
1842                 RETURN(0);
1843         }
1844
1845         if (*lmmp == NULL) {
1846                 OBD_ALLOC(*lmmp, mea_size);
1847                 if (*lmmp == NULL)
1848                         RETURN(-ENOMEM);
1849         }
1850
1851         if (!lsm)
1852                 RETURN(mea_size);
1853
1854         lsmp = (struct mea *)lsm;
1855         meap = (struct mea *)*lmmp;
1856
1857         meap->mea_magic = cpu_to_le32(lsmp->mea_magic);
1858         meap->mea_count = cpu_to_le32(lsmp->mea_count);
1859         meap->mea_master = cpu_to_le32(lsmp->mea_master);
1860
1861         for (i = 0; i < lmv->desc.ld_tgt_count; i++) {
1862                 meap->mea_ids[i] = meap->mea_ids[i];
1863                 id_cpu_to_le(&meap->mea_ids[i]);
1864         }
1865
1866         RETURN(mea_size);
1867 }
1868
1869 int lmv_unpackmd(struct obd_export *exp, struct lov_stripe_md **mem_tgt,
1870                  struct lov_mds_md *disk_src, int mdsize)
1871 {
1872         struct obd_device *obd = class_exp2obd(exp);
1873         struct mea **tmea = (struct mea **)mem_tgt;
1874         struct mea *mea = (struct mea *)disk_src;
1875         struct lmv_obd *lmv = &obd->u.lmv;
1876         int mea_size, i;
1877         ENTRY;
1878
1879         mea_size = sizeof(struct lustre_id) * 
1880                 lmv->desc.ld_tgt_count + sizeof(struct mea);
1881         if (mem_tgt == NULL)
1882                 return mea_size;
1883
1884         if (*mem_tgt != NULL && disk_src == NULL) {
1885                 OBD_FREE(*tmea, mea_size);
1886                 RETURN(0);
1887         }
1888
1889         LASSERT(mea_size == mdsize);
1890
1891         OBD_ALLOC(*tmea, mea_size);
1892         if (*tmea == NULL)
1893                 RETURN(-ENOMEM);
1894
1895         if (!disk_src)
1896                 RETURN(mea_size);
1897
1898         (*tmea)->mea_magic = le32_to_cpu(mea->mea_magic);
1899         (*tmea)->mea_count = le32_to_cpu(mea->mea_count);
1900         (*tmea)->mea_master = le32_to_cpu(mea->mea_master);
1901
1902         for (i = 0; i < lmv->desc.ld_tgt_count; i++) {
1903                 (*tmea)->mea_ids[i] = mea->mea_ids[i];
1904                 id_le_to_cpu(&(*tmea)->mea_ids[i]);
1905         }
1906
1907         RETURN(mea_size);
1908 }
1909
1910 int lmv_brw(int rw, struct obd_export *exp, struct obdo *oa,
1911             struct lov_stripe_md *ea, obd_count oa_bufs,
1912             struct brw_page *pgarr, struct obd_trans_info *oti)
1913 {
1914         struct obd_device *obd = exp->exp_obd;
1915         struct lmv_obd *lmv = &obd->u.lmv;
1916         struct mea *mea = (struct mea *) ea;
1917         int err;
1918       
1919         LASSERT(oa != NULL);
1920         LASSERT(ea != NULL);
1921         LASSERT(pgarr != NULL);
1922         LASSERT(oa->o_mds < lmv->desc.ld_tgt_count);
1923
1924         oa->o_gr = id_gen(&mea->mea_ids[oa->o_mds]);
1925         oa->o_id = id_ino(&mea->mea_ids[oa->o_mds]);
1926         oa->o_valid = OBD_MD_FLID | OBD_MD_FLGROUP;
1927         
1928         err = obd_brw(rw, lmv->tgts[oa->o_mds].ltd_exp,
1929                       oa, NULL, oa_bufs, pgarr, oti);
1930         RETURN(err);
1931 }
1932
1933 struct obd_ops lmv_obd_ops = {
1934         .o_owner                = THIS_MODULE,
1935         .o_attach               = lmv_attach,
1936         .o_detach               = lmv_detach,
1937         .o_setup                = lmv_setup,
1938         .o_cleanup              = lmv_cleanup,
1939         .o_connect              = lmv_connect,
1940         .o_disconnect           = lmv_disconnect,
1941         .o_statfs               = lmv_statfs,
1942         .o_llog_init            = lmv_llog_init,
1943         .o_llog_finish          = lmv_llog_finish,
1944         .o_get_info             = lmv_get_info,
1945         .o_set_info             = lmv_set_info,
1946         .o_create               = lmv_obd_create,
1947         .o_packmd               = lmv_packmd,
1948         .o_unpackmd             = lmv_unpackmd,
1949         .o_brw                  = lmv_brw,
1950         .o_init_ea_size         = lmv_init_ea_size,
1951         .o_notify               = lmv_notify,
1952         .o_iocontrol            = lmv_iocontrol,
1953         .o_getready             = lmv_getready,
1954 };
1955
1956 struct md_ops lmv_md_ops = {
1957         .m_getstatus           = lmv_getstatus,
1958         .m_getattr             = lmv_getattr,
1959         .m_change_cbdata       = lmv_change_cbdata,
1960         .m_change_cbdata_name  = lmv_change_cbdata_name,
1961         .m_close               = lmv_close,
1962         .m_create              = lmv_create,
1963         .m_done_writing        = lmv_done_writing,
1964         .m_enqueue             = lmv_enqueue,
1965         .m_getattr_lock        = lmv_getattr_lock,
1966         .m_intent_lock         = lmv_intent_lock,
1967         .m_link                = lmv_link,
1968         .m_rename              = lmv_rename,
1969         .m_setattr             = lmv_setattr,
1970         .m_sync                = lmv_sync,
1971         .m_readpage            = lmv_readpage,
1972         .m_unlink              = lmv_unlink,
1973         .m_get_real_obd        = lmv_get_real_obd,
1974         .m_valid_attrs         = lmv_valid_attrs,
1975         .m_delete_inode        = lmv_delete_inode,
1976 };
1977
1978 int __init lmv_init(void)
1979 {
1980         struct lprocfs_static_vars lvars;
1981         int rc;
1982
1983         obj_cache = kmem_cache_create("lmv_objects",
1984                                       sizeof(struct lmv_obj),
1985                                       0, 0, NULL, NULL);
1986         if (!obj_cache) {
1987                 CERROR("error allocating lmv objects cache\n");
1988                 return -ENOMEM;
1989         }
1990
1991         lprocfs_init_vars(lmv, &lvars);
1992         rc = class_register_type(&lmv_obd_ops, &lmv_md_ops,
1993                                  lvars.module_vars,
1994                                  OBD_LMV_DEVICENAME);
1995         if (rc)
1996                 kmem_cache_destroy(obj_cache);
1997         
1998         return rc;
1999 }
2000
2001 #ifdef __KERNEL__
2002 static void lmv_exit(void)
2003 {
2004         class_unregister_type(OBD_LMV_DEVICENAME);
2005
2006         LASSERTF(kmem_cache_destroy(obj_cache) == 0,
2007                  "can't free lmv objects cache, %d object(s)"
2008                  "still in use\n", atomic_read(&obj_cache_count));
2009 }
2010
2011 MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
2012 MODULE_DESCRIPTION("Lustre Logical Metadata Volume OBD driver");
2013 MODULE_LICENSE("GPL");
2014
2015 module_init(lmv_init);
2016 module_exit(lmv_exit);
2017 #endif