Whamcloud - gitweb
0e5bd5d273d03c254349940435e11d2b61e7b99c
[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, int 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 OST 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)\n", i,
635                                lmv->tgts[i].ltd_exp->exp_obd->obd_name);
636                         RETURN(rc);
637                 }
638                 if (i == 0) {
639                         memcpy(osfs, &temp, sizeof(temp));
640                 } else {
641                         osfs->os_bavail += temp.os_bavail;
642                         osfs->os_blocks += temp.os_blocks;
643                         osfs->os_ffree += temp.os_ffree;
644                         osfs->os_files += temp.os_files;
645                 }
646         }
647         RETURN(rc);
648 }
649
650 static int lmv_getstatus(struct obd_export *exp, struct lustre_id *id)
651 {
652         struct obd_device *obd = exp->exp_obd;
653         struct lmv_obd *lmv = &obd->u.lmv;
654         int rc;
655         ENTRY;
656
657         rc = lmv_check_connect(obd);
658         if (rc)
659                 RETURN(rc);
660
661         rc = md_getstatus(lmv->tgts[0].ltd_exp, id);
662         id_group(id) = 0;
663         
664         RETURN(rc);
665 }
666
667 static int lmv_getattr(struct obd_export *exp, struct lustre_id *id,
668                        unsigned long valid, unsigned int ea_size,
669                        struct ptlrpc_request **request)
670 {
671         struct obd_device *obd = exp->exp_obd;
672         struct lmv_obd *lmv = &obd->u.lmv;
673         int rc, i = id_group(id);
674         struct lmv_obj *obj;
675         ENTRY;
676
677         rc = lmv_check_connect(obd);
678         if (rc)
679                 RETURN(rc);
680
681         LASSERT(i < lmv->desc.ld_tgt_count);
682
683         rc = md_getattr(lmv->tgts[i].ltd_exp, id, valid,
684                         ea_size, request);
685         if (rc)
686                 RETURN(rc);
687         
688         obj = lmv_grab_obj(obd, id);
689         
690         CDEBUG(D_OTHER, "GETATTR for "DLID4" %s\n",
691                OLID4(id), obj ? "(splitted)" : "");
692
693         /*
694          * if object is splitted, then we loop over all the slaves and gather
695          * size attribute. In ideal world we would have to gather also mds field
696          * from all slaves, as object is spread over the cluster and this is
697          * definitely interesting information and it is not good to loss it,
698          * but...
699          */
700         if (obj) {
701                 struct mds_body *body;
702
703                 if (*request == NULL) {
704                         lmv_put_obj(obj);
705                         RETURN(rc);
706                 }
707                         
708                 body = lustre_msg_buf((*request)->rq_repmsg, 0,
709                                       sizeof(*body));
710                 LASSERT(body != NULL);
711
712                 lmv_lock_obj(obj);
713         
714                 for (i = 0; i < obj->objcount; i++) {
715
716                         if (lmv->tgts[i].ltd_exp == NULL) {
717                                 CWARN("%s: NULL export for %d\n",
718                                       obd->obd_name, i);
719                                 continue;
720                         }
721
722                         /* skip master obj. */
723                         if (id_equal_fid(&obj->id, &obj->objs[i].id))
724                                 continue;
725                         
726                         body->size += obj->objs[i].size;
727                 }
728
729                 lmv_unlock_obj(obj);
730                 lmv_put_obj(obj);
731         }
732         
733         RETURN(rc);
734 }
735
736 static int lmv_change_cbdata(struct obd_export *exp,
737                              struct lustre_id *id, 
738                              ldlm_iterator_t it,
739                              void *data)
740 {
741         struct obd_device *obd = exp->exp_obd;
742         struct lmv_obd *lmv = &obd->u.lmv;
743         int rc = 0;
744         ENTRY;
745         
746         rc = lmv_check_connect(obd);
747         if (rc)
748                 RETURN(rc);
749         
750         CDEBUG(D_OTHER, "CBDATA for "DLID4"\n", OLID4(id));
751         LASSERT(id_group(id) < lmv->desc.ld_tgt_count);
752
753         rc = md_change_cbdata(lmv->tgts[id_group(id)].ltd_exp,
754                               id, it, data);
755         
756         RETURN(rc);
757 }
758
759 static int lmv_change_cbdata_name(struct obd_export *exp,
760                                   struct lustre_id *pid,
761                                   char *name, int len,
762                                   struct lustre_id *cid,
763                                   ldlm_iterator_t it,
764                                   void *data)
765 {
766         struct obd_device *obd = exp->exp_obd;
767         struct lmv_obd *lmv = &obd->u.lmv;
768         struct lustre_id rcid = *cid;
769         struct lmv_obj *obj;
770         int rc = 0, mds;
771         ENTRY;
772
773         rc = lmv_check_connect(obd);
774         if (rc)
775                 RETURN(rc);
776
777         LASSERT(id_group(pid) < lmv->desc.ld_tgt_count);
778         LASSERT(id_group(cid) < lmv->desc.ld_tgt_count);
779         
780         CDEBUG(D_OTHER, "CBDATA for "DLID4":%*s -> "DLID4"\n",
781                OLID4(pid), len, name, OLID4(cid));
782
783         /* this is default mds for directory name belongs to. */
784         mds = id_group(pid);
785         obj = lmv_grab_obj(obd, pid);
786         if (obj) {
787                 /* directory is splitted. look for right mds for this name. */
788                 mds = raw_name2idx(obj->hashtype, obj->objcount, name, len);
789                 rcid = obj->objs[mds].id;
790                 mds = id_group(&rcid);
791                 lmv_put_obj(obj);
792         }
793         rc = md_change_cbdata(lmv->tgts[mds].ltd_exp, &rcid, it, data);
794         RETURN(rc);
795 }
796
797 static int lmv_valid_attrs(struct obd_export *exp, struct lustre_id *id) 
798 {
799         struct obd_device *obd = exp->exp_obd;
800         struct lmv_obd *lmv = &obd->u.lmv;
801         int rc = 0;
802         ENTRY;
803
804         rc = lmv_check_connect(obd);
805         if (rc)
806                 RETURN(rc);
807
808         CDEBUG(D_OTHER, "validate "DLID4"\n", OLID4(id));
809         LASSERT(id_group(id) < lmv->desc.ld_tgt_count);
810         rc = md_valid_attrs(lmv->tgts[id_group(id)].ltd_exp, id);
811         RETURN(rc);
812 }
813
814 int lmv_close(struct obd_export *exp, struct obdo *obdo,
815               struct obd_client_handle *och,
816               struct ptlrpc_request **request)
817 {
818         struct obd_device *obd = exp->exp_obd;
819         struct lmv_obd *lmv = &obd->u.lmv;
820         int rc, i = obdo->o_mds;
821         ENTRY;
822         
823         rc = lmv_check_connect(obd);
824         if (rc)
825                 RETURN(rc);
826
827         LASSERT(i < lmv->desc.ld_tgt_count);
828         CDEBUG(D_OTHER, "CLOSE %lu/%lu/%lu\n", (unsigned long)obdo->o_mds,
829                (unsigned long)obdo->o_id, (unsigned long)obdo->o_generation);
830         rc = md_close(lmv->tgts[i].ltd_exp, obdo, och, request);
831         RETURN(rc);
832 }
833
834 int lmv_get_mea_and_update_object(struct obd_export *exp, 
835                                   struct lustre_id *id)
836 {
837         struct obd_device *obd = exp->exp_obd;
838         struct lmv_obd *lmv = &obd->u.lmv;
839         struct ptlrpc_request *req = NULL;
840         struct lmv_obj *obj;
841         struct lustre_md md;
842         unsigned long valid;
843         int mealen, rc;
844
845         md.mea = NULL;
846         mealen = MEA_SIZE_LMV(lmv);
847         
848         valid = OBD_MD_FLEASIZE | OBD_MD_FLDIREA;
849
850         /* time to update mea of parent id */
851         rc = md_getattr(lmv->tgts[id_group(id)].ltd_exp,
852                         id, valid, mealen, &req);
853         if (rc) {
854                 CERROR("md_getattr() failed, error %d\n", rc);
855                 GOTO(cleanup, rc);
856         }
857
858         rc = mdc_req2lustre_md(exp, req, 0, NULL, &md);
859         if (rc) {
860                 CERROR("mdc_req2lustre_md() failed, error %d\n", rc);
861                 GOTO(cleanup, rc);
862         }
863
864         if (md.mea == NULL)
865                 GOTO(cleanup, rc = -ENODATA);
866
867         obj = lmv_create_obj(exp, id, md.mea);
868         if (IS_ERR(obj))
869                 rc = PTR_ERR(obj);
870         
871         lmv_put_obj(obj);
872         obd_free_memmd(exp, (struct lov_stripe_md **)&md.mea);
873
874 cleanup:
875         if (req)
876                 ptlrpc_req_finished(req);
877         RETURN(rc);
878 }
879
880 int lmv_create(struct obd_export *exp, struct mdc_op_data *op_data,
881                const void *data, int datalen, int mode, __u32 uid,
882                __u32 gid, __u64 rdev, struct ptlrpc_request **request)
883 {
884         struct obd_device *obd = exp->exp_obd;
885         struct lmv_obd *lmv = &obd->u.lmv;
886         struct mds_body *body;
887         struct lmv_obj *obj;
888         int rc, mds, loop = 0;
889         ENTRY;
890
891         rc = lmv_check_connect(obd);
892         if (rc)
893                 RETURN(rc);
894
895         if (!lmv->desc.ld_active_tgt_count)
896                 RETURN(-EIO);
897 repeat:
898         LASSERT(++loop <= 2);
899         obj = lmv_grab_obj(obd, &op_data->id1);
900         if (obj) {
901                 mds = raw_name2idx(obj->hashtype, obj->objcount, 
902                                    op_data->name, op_data->namelen);
903                 op_data->id1 = obj->objs[mds].id;
904                 lmv_put_obj(obj);
905         }
906
907         CDEBUG(D_OTHER, "CREATE '%*s' on "DLID4"\n", op_data->namelen,
908                op_data->name, OLID4(&op_data->id1));
909         
910         rc = md_create(lmv->tgts[id_group(&op_data->id1)].ltd_exp, 
911                        op_data, data, datalen, mode, uid, gid, rdev,
912                        request);
913         if (rc == 0) {
914                 if (*request == NULL)
915                         RETURN(rc);
916
917                 body = lustre_msg_buf((*request)->rq_repmsg, 0,
918                                       sizeof(*body));
919                 if (body == NULL)
920                         RETURN(-ENOMEM);
921                 
922                 CDEBUG(D_OTHER, "created. "DLID4"\n", OLID4(&op_data->id1));
923         } else if (rc == -ERESTART) {
924                 /*
925                  * directory got splitted. time to update local object and
926                  * repeat the request with proper MDS.
927                  */
928                 rc = lmv_get_mea_and_update_object(exp, &op_data->id1);
929                 if (rc == 0) {
930                         ptlrpc_req_finished(*request);
931                         goto repeat;
932                 }
933         }
934         RETURN(rc);
935 }
936
937 int lmv_done_writing(struct obd_export *exp, struct obdo *obdo)
938 {
939         struct obd_device *obd = exp->exp_obd;
940         struct lmv_obd *lmv = &obd->u.lmv;
941         int rc;
942         ENTRY;
943         rc = lmv_check_connect(obd);
944         if (rc)
945                 RETURN(rc);
946
947         /* FIXME: choose right MDC here */
948         CWARN("this method isn't implemented yet\n");
949         rc = md_done_writing(lmv->tgts[0].ltd_exp, obdo);
950         RETURN(rc);
951 }
952
953 int lmv_enqueue_slaves(struct obd_export *exp, int locktype,
954                        struct lookup_intent *it, int lockmode,
955                        struct mdc_op_data *data, struct lustre_handle *lockh,
956                        void *lmm, int lmmsize, ldlm_completion_callback cb_compl,
957                        ldlm_blocking_callback cb_blocking, void *cb_data)
958 {
959         struct obd_device *obd = exp->exp_obd;
960         struct lmv_obd *lmv = &obd->u.lmv;
961         struct mea *mea = data->mea1;
962         struct mdc_op_data data2;
963         int i, rc, mds;
964         ENTRY;
965
966         LASSERT(mea != NULL);
967         for (i = 0; i < mea->mea_count; i++) {
968                 memset(&data2, 0, sizeof(data2));
969                 data2.id1 = mea->mea_ids[i];
970                 mds = id_group(&data2.id1);
971                 
972                 if (lmv->tgts[mds].ltd_exp == NULL)
973                         continue;
974
975                 rc = md_enqueue(lmv->tgts[mds].ltd_exp, locktype, it, 
976                                 lockmode, &data2, lockh + i, lmm, lmmsize, 
977                                 cb_compl, cb_blocking, cb_data);
978                 
979                 CDEBUG(D_OTHER, "take lock on slave "DLID4" -> %d/%d\n",
980                        OLID4(&mea->mea_ids[i]), rc, it->d.lustre.it_status);
981                 if (rc)
982                         GOTO(cleanup, rc);
983                 if (it->d.lustre.it_data) {
984                         struct ptlrpc_request *req;
985                         req = (struct ptlrpc_request *) it->d.lustre.it_data;
986                         ptlrpc_req_finished(req);
987                 }
988                 
989                 if (it->d.lustre.it_status)
990                         GOTO(cleanup, rc = it->d.lustre.it_status);
991         }
992         RETURN(0);
993         
994 cleanup:
995         /* drop all taken locks */
996         while (--i >= 0) {
997                 if (lockh[i].cookie)
998                         ldlm_lock_decref(lockh + i, lockmode);
999                 lockh[i].cookie = 0;
1000         }
1001         RETURN(rc);
1002 }
1003
1004 int lmv_enqueue(struct obd_export *exp, int lock_type,
1005                 struct lookup_intent *it, int lock_mode,
1006                 struct mdc_op_data *data, struct lustre_handle *lockh,
1007                 void *lmm, int lmmsize, ldlm_completion_callback cb_compl,
1008                 ldlm_blocking_callback cb_blocking, void *cb_data)
1009 {
1010         struct obd_device *obd = exp->exp_obd;
1011         struct lmv_obd *lmv = &obd->u.lmv;
1012         struct lmv_obj *obj;
1013         int rc, mds;
1014         ENTRY;
1015
1016         rc = lmv_check_connect(obd);
1017         if (rc)
1018                 RETURN(rc);
1019
1020         if (data->mea1 && it->it_op == IT_UNLINK) {
1021                 rc = lmv_enqueue_slaves(exp, lock_type, it, lock_mode,
1022                                         data, lockh, lmm, lmmsize,
1023                                         cb_compl, cb_blocking, cb_data);
1024                 RETURN(rc);
1025         }
1026
1027         if (data->namelen) {
1028                 obj = lmv_grab_obj(obd, &data->id1);
1029                 if (obj) {
1030                         /* directory is splitted. look for right mds for this
1031                          * name */
1032                         mds = raw_name2idx(obj->hashtype, obj->objcount,
1033                                            (char *)data->name, data->namelen);
1034                         data->id1 = obj->objs[mds].id;
1035                         lmv_put_obj(obj);
1036                 }
1037         }
1038         CDEBUG(D_OTHER, "ENQUEUE '%s' on "DLID4"\n", LL_IT2STR(it),
1039                OLID4(&data->id1));
1040         
1041         rc = md_enqueue(lmv->tgts[id_group(&data->id1)].ltd_exp, 
1042                         lock_type, it, lock_mode, data, lockh, lmm, 
1043                         lmmsize, cb_compl, cb_blocking, cb_data);
1044         RETURN(rc);
1045 }
1046
1047 int lmv_getattr_lock(struct obd_export *exp, struct lustre_id *id,
1048                      char *filename, int namelen, unsigned long valid,
1049                      unsigned int ea_size, struct ptlrpc_request **request)
1050 {
1051         int rc, mds = id_group(id), loop = 0;
1052         struct obd_device *obd = exp->exp_obd;
1053         struct lmv_obd *lmv = &obd->u.lmv;
1054         struct lustre_id rid = *id;
1055         struct mds_body *body;
1056         struct lmv_obj *obj;
1057         int old_valid;
1058         ENTRY;
1059         
1060         rc = lmv_check_connect(obd);
1061         if (rc)
1062                 RETURN(rc);
1063 repeat:
1064         LASSERT(++loop <= 2);
1065         obj = lmv_grab_obj(obd, id);
1066         if (obj) {
1067                 /* directory is splitted. look for right mds for this name */
1068                 mds = raw_name2idx(obj->hashtype, obj->objcount, 
1069                                    filename, namelen - 1);
1070                 rid = obj->objs[mds].id;
1071                 lmv_put_obj(obj);
1072         }
1073         
1074         CDEBUG(D_OTHER, "getattr_lock for %*s on "DLID4" -> "DLID4"\n",
1075                namelen, filename, OLID4(id), OLID4(&rid));
1076
1077         old_valid = valid;
1078
1079         /*
1080          * here should be applied OBD_MD_FID to ->valid, because otherwise,
1081          * mds_getattr_lock() will not fetch fid component of lustre_id and
1082          * thus, next call to md_getattr_lock() will be performed to wrong mds.
1083          */
1084         if (!(old_valid & OBD_MD_FID))
1085                 valid |= OBD_MD_FID;
1086         
1087         rc = md_getattr_lock(lmv->tgts[id_group(&rid)].ltd_exp, 
1088                              &rid, filename, namelen, valid,
1089                              ea_size, request);
1090         if (rc == 0) {
1091                 /*
1092                  * this could be cross-node reference. in this case all we have
1093                  * right now is lustre_id triple. we'd like to find other
1094                  * attributes.
1095                  */
1096                 body = lustre_msg_buf((*request)->rq_repmsg, 0, sizeof(*body));
1097                 LASSERT(body != NULL);
1098                 if (body->valid & OBD_MD_MDS) {
1099                         struct ptlrpc_request *req = NULL;
1100                         
1101                         rid = body->id1;
1102                         CDEBUG(D_OTHER, "request attrs for "DLID4"\n", OLID4(&rid));
1103
1104                         /* 
1105                          * turning OBD_MD_FID fetching off, as we already have
1106                          * full lustre_id and do need to fetch fid component
1107                          * again. This will help to make thing slightly faster.
1108                          */
1109                         if (!(old_valid & OBD_MD_FID))
1110                                 valid &= ~OBD_MD_FID;
1111                         
1112                         rc = md_getattr_lock(lmv->tgts[id_group(&rid)].ltd_exp, 
1113                                              &rid, NULL, 1, valid, ea_size, &req);
1114                         ptlrpc_req_finished(*request);
1115                         *request = req;
1116                 }
1117         } else if (rc == -ERESTART) {
1118                 /* directory got splitted. time to update local object and
1119                  * repeat the request with proper MDS */
1120                 rc = lmv_get_mea_and_update_object(exp, &rid);
1121                 if (rc == 0) {
1122                         ptlrpc_req_finished(*request);
1123                         goto repeat;
1124                 }
1125         }
1126         RETURN(rc);
1127 }
1128
1129 /*
1130  * llite passes id of an target inode in data->id1 and id of directory in
1131  * data->id2
1132  */
1133 int lmv_link(struct obd_export *exp, struct mdc_op_data *data,
1134              struct ptlrpc_request **request)
1135 {
1136         struct obd_device *obd = exp->exp_obd;
1137         struct lmv_obd *lmv = &obd->u.lmv;
1138         struct lmv_obj *obj;
1139         int rc;
1140         ENTRY;
1141         
1142         rc = lmv_check_connect(obd);
1143         if (rc)
1144                 RETURN(rc);
1145
1146         if (data->namelen != 0) {
1147                 /* usual link request */
1148                 obj = lmv_grab_obj(obd, &data->id1);
1149                 if (obj) {
1150                         rc = raw_name2idx(obj->hashtype, obj->objcount, 
1151                                           data->name, data->namelen);
1152                         data->id1 = obj->objs[rc].id;
1153                         lmv_put_obj(obj);
1154                 }
1155                 
1156                 CDEBUG(D_OTHER,"link "DLID4":%*s to "DLID4"\n",
1157                        OLID4(&data->id2), data->namelen, data->name,
1158                        OLID4(&data->id1));
1159         } else {
1160                 /* request from MDS to acquire i_links for inode by id1 */
1161                 CDEBUG(D_OTHER, "inc i_nlinks for "DLID4"\n",
1162                        OLID4(&data->id1));
1163         }
1164                         
1165         rc = md_link(lmv->tgts[id_group(&data->id1)].ltd_exp, 
1166                      data, request);
1167         RETURN(rc);
1168 }
1169
1170 int lmv_rename(struct obd_export *exp, struct mdc_op_data *data,
1171                const char *old, int oldlen, const char *new, int newlen,
1172                struct ptlrpc_request **request)
1173 {
1174         struct obd_device *obd = exp->exp_obd;
1175         struct lmv_obd *lmv = &obd->u.lmv;
1176         struct lmv_obj *obj;
1177         int rc, mds;
1178         ENTRY;
1179
1180         CDEBUG(D_OTHER, "rename %*s in "DLID4" to %*s in "DLID4"\n",
1181                oldlen, old, OLID4(&data->id1), newlen, new, OLID4(&data->id2));
1182
1183         rc = lmv_check_connect(obd);
1184         if (rc)
1185                 RETURN(rc);
1186
1187         if (oldlen == 0) {
1188                 /*
1189                  * MDS with old dir entry is asking another MDS to create name
1190                  * there.
1191                  */
1192                 CDEBUG(D_OTHER,
1193                        "create %*s(%d/%d) in "DLID4" pointing "
1194                        "to "DLID4"\n", newlen, new, oldlen, newlen,
1195                        OLID4(&data->id2), OLID4(&data->id1));
1196
1197                 mds = id_group(&data->id2);
1198
1199                 /* 
1200                  * target directory can be splitted, sowe should forward request
1201                  * to the right MDS.
1202                  */
1203                 obj = lmv_grab_obj(obd, &data->id2);
1204                 if (obj) {
1205                         mds = raw_name2idx(obj->hashtype, obj->objcount, 
1206                                            (char *)new, newlen);
1207                         data->id2 = obj->objs[mds].id;
1208                         CDEBUG(D_OTHER, "forward to MDS #%u ("DLID4")\n", mds,
1209                                OLID4(&data->id2));
1210                         lmv_put_obj(obj);
1211                 }
1212                 goto request;
1213         }
1214
1215         obj = lmv_grab_obj(obd, &data->id1);
1216         if (obj) {
1217                 /*
1218                  * directory is already splitted, so we have to forward request
1219                  * to the right MDS.
1220                  */
1221                 mds = raw_name2idx(obj->hashtype, obj->objcount, 
1222                                    (char *)old, oldlen);
1223                 data->id1 = obj->objs[mds].id;
1224                 CDEBUG(D_OTHER, "forward to MDS #%u ("DLID4")\n", mds,
1225                        OLID4(&data->id1));
1226                 lmv_put_obj(obj);
1227         }
1228
1229         obj = lmv_grab_obj(obd, &data->id2);
1230         if (obj) {
1231                 /*
1232                  * directory is already splitted, so we have to forward request
1233                  * to the right MDS.
1234                  */
1235                 mds = raw_name2idx(obj->hashtype, obj->objcount, 
1236                                    (char *)new, newlen);
1237                 
1238                 data->id2 = obj->objs[mds].id;
1239                 CDEBUG(D_OTHER, "forward to MDS #%u ("DLID4")\n", mds,
1240                        OLID4(&data->id2));
1241                 lmv_put_obj(obj);
1242         }
1243         
1244         mds = id_group(&data->id1);
1245
1246 request:
1247         if (id_group(&data->id1) != id_group(&data->id2)) {
1248                 CDEBUG(D_OTHER,"cross-node rename "DLID4"/%*s to "DLID4"/%*s\n",
1249                        OLID4(&data->id1), oldlen, old, OLID4(&data->id2),
1250                        newlen, new);
1251         }
1252
1253         rc = md_rename(lmv->tgts[mds].ltd_exp, data, old, oldlen,
1254                        new, newlen, request); 
1255         RETURN(rc);
1256 }
1257
1258 int lmv_setattr(struct obd_export *exp, struct mdc_op_data *data,
1259                 struct iattr *iattr, void *ea, int ealen, void *ea2,
1260                 int ea2len, struct ptlrpc_request **request)
1261 {
1262         struct obd_device *obd = exp->exp_obd;
1263         struct lmv_obd *lmv = &obd->u.lmv;
1264         struct ptlrpc_request *req;
1265         struct mds_body *body;
1266         struct lmv_obj *obj;
1267         int rc = 0, i;
1268         ENTRY;
1269
1270         rc = lmv_check_connect(obd);
1271         if (rc)
1272                 RETURN(rc);
1273
1274         obj = lmv_grab_obj(obd, &data->id1);
1275         
1276         CDEBUG(D_OTHER, "SETATTR for "DLID4", valid 0x%x%s\n",
1277                OLID4(&data->id1), iattr->ia_valid, obj ? ", splitted" : "");
1278         
1279         if (obj) {
1280                 for (i = 0; i < obj->objcount; i++) {
1281                         data->id1 = obj->objs[i].id;
1282                         
1283                         rc = md_setattr(lmv->tgts[id_group(&data->id1)].ltd_exp, 
1284                                         data, iattr, ea, ealen, ea2, ea2len, &req);
1285
1286                         if (id_equal_fid(&obj->id, &obj->objs[i].id)) {
1287                                 /*
1288                                  * this is master object and this request should
1289                                  * be returned back to llite.
1290                                  */
1291                                 *request = req;
1292                         } else {
1293                                 ptlrpc_req_finished(req);
1294                         }
1295
1296                         if (rc)
1297                                 break;
1298                 }
1299                 lmv_put_obj(obj);
1300         } else {
1301                 LASSERT(id_group(&data->id1) < lmv->desc.ld_tgt_count);
1302                 rc = md_setattr(lmv->tgts[id_group(&data->id1)].ltd_exp,
1303                                 data, iattr, ea, ealen, ea2, ea2len, request); 
1304                 if (rc == 0) {
1305                         body = lustre_msg_buf((*request)->rq_repmsg, 0,
1306                                               sizeof(*body));
1307                         LASSERT(body != NULL);
1308                         LASSERT(id_group(&body->id1) == id_group(&data->id1));
1309                 }
1310         }
1311         RETURN(rc);
1312 }
1313
1314 int lmv_sync(struct obd_export *exp, struct lustre_id *id,
1315              struct ptlrpc_request **request)
1316 {
1317         struct obd_device *obd = exp->exp_obd;
1318         struct lmv_obd *lmv = &obd->u.lmv;
1319         int rc;
1320         ENTRY;
1321
1322         rc = lmv_check_connect(obd);
1323         if (rc)
1324                 RETURN(rc);
1325
1326         rc = md_sync(lmv->tgts[id_group(id)].ltd_exp, 
1327                      id, request);
1328         RETURN(rc);
1329 }
1330
1331 int lmv_dirobj_blocking_ast(struct ldlm_lock *lock, 
1332                             struct ldlm_lock_desc *desc,
1333                             void *data, int flag)
1334 {
1335         struct lustre_handle lockh;
1336         struct lmv_obj *obj;
1337         int rc;
1338         ENTRY;
1339
1340         switch (flag) {
1341         case LDLM_CB_BLOCKING:
1342                 ldlm_lock2handle(lock, &lockh);
1343                 rc = ldlm_cli_cancel(&lockh);
1344                 if (rc < 0) {
1345                         CDEBUG(D_INODE, "ldlm_cli_cancel: %d\n", rc);
1346                         RETURN(rc);
1347                 }
1348                 break;
1349         case LDLM_CB_CANCELING:
1350                 /* time to drop cached attrs for dirobj */
1351                 obj = lock->l_ast_data;
1352                 if (obj) {
1353                         CDEBUG(D_OTHER, "cancel %s on "LPU64"/"LPU64
1354                                ", master "DLID4"\n",
1355                                lock->l_resource->lr_name.name[3] == 1 ?
1356                                "LOOKUP" : "UPDATE",
1357                                lock->l_resource->lr_name.name[0],
1358                                lock->l_resource->lr_name.name[1], 
1359                                OLID4(&obj->id));
1360                         lmv_put_obj(obj);
1361                 }
1362                 break;
1363         default:
1364                 LBUG();
1365         }
1366         RETURN(0);
1367 }
1368
1369 void lmv_remove_dots(struct page *page)
1370 {
1371         char *kaddr = page_address(page);
1372         unsigned limit = PAGE_CACHE_SIZE;
1373         unsigned offs, rec_len;
1374         struct ext2_dir_entry_2 *p;
1375
1376         for (offs = 0; offs <= limit - EXT2_DIR_REC_LEN(1); offs += rec_len) {
1377                 p = (struct ext2_dir_entry_2 *)(kaddr + offs);
1378                 rec_len = le16_to_cpu(p->rec_len);
1379
1380                 if ((p->name_len == 1 && p->name[0] == '.') ||
1381                     (p->name_len == 2 && p->name[0] == '.' && p->name[1] == '.'))
1382                         p->inode = 0;
1383         }
1384 }
1385
1386 int lmv_readpage(struct obd_export *exp, struct lustre_id *id,
1387                  __u64 offset, struct page *page,
1388                  struct ptlrpc_request **request)
1389 {
1390         struct obd_device *obd = exp->exp_obd;
1391         struct lmv_obd *lmv = &obd->u.lmv;
1392         struct lustre_id rid = *id;
1393         struct lmv_obj *obj;
1394         int rc, i;
1395         ENTRY;
1396
1397 #warning "we need well-desgined readdir() implementation"
1398         rc = lmv_check_connect(obd);
1399         if (rc)
1400                 RETURN(rc);
1401
1402         LASSERT(id_group(id) < lmv->desc.ld_tgt_count);
1403         CDEBUG(D_OTHER, "READPAGE at %llu from "DLID4"\n",
1404                offset, OLID4(&rid));
1405
1406         obj = lmv_grab_obj(obd, id);
1407         if (obj) {
1408                 lmv_lock_obj(obj);
1409
1410                 /* find dirobj containing page with requested offset. */
1411                 for (i = 0; i < obj->objcount; i++) {
1412                         if (offset < obj->objs[i].size)
1413                                 break;
1414                         offset -= obj->objs[i].size;
1415                 }
1416                 rid = obj->objs[i].id;
1417                 
1418                 lmv_unlock_obj(obj);
1419                 lmv_put_obj(obj);
1420                 
1421                 CDEBUG(D_OTHER, "forward to "DLID4" with offset %lu\n",
1422                        OLID4(&rid), (unsigned long)offset);
1423         }
1424         rc = md_readpage(lmv->tgts[id_group(&rid)].ltd_exp, &rid, 
1425                          offset, page, request);
1426         
1427         if (rc == 0 && !id_equal_fid(&rid, id))
1428                 /* this page isn't from master object. To avoid "." and ".." 
1429                  * duplication in directory, we have to remove them from all
1430                  * slave objects */
1431                 lmv_remove_dots(page);
1432         
1433         RETURN(rc);
1434 }
1435
1436 int lmv_unlink_slaves(struct obd_export *exp, struct mdc_op_data *data,
1437                       struct ptlrpc_request **req)
1438 {
1439         struct obd_device *obd = exp->exp_obd;
1440         struct lmv_obd *lmv = &obd->u.lmv;
1441         struct mea *mea = data->mea1;
1442         struct mdc_op_data data2;
1443         int i, rc = 0, mds;
1444         ENTRY;
1445
1446         LASSERT(mea != NULL);
1447         for (i = 0; i < mea->mea_count; i++) {
1448                 memset(&data2, 0, sizeof(data2));
1449                 data2.id1 = mea->mea_ids[i];
1450                 data2.create_mode = MDS_MODE_DONT_LOCK | S_IFDIR;
1451                 
1452                 mds = id_group(&data2.id1);
1453
1454                 if (lmv->tgts[mds].ltd_exp == NULL)
1455                         continue;
1456
1457                 rc = md_unlink(lmv->tgts[mds].ltd_exp, &data2, req);
1458                 CDEBUG(D_OTHER, "unlink slave "DLID4" -> %d\n",
1459                        OLID4(&mea->mea_ids[i]), rc);
1460                 if (*req) {
1461                         ptlrpc_req_finished(*req);
1462                         *req = NULL;
1463                 }
1464                 if (rc)
1465                         break;
1466         }
1467         RETURN(rc);
1468 }
1469
1470 int lmv_delete_inode(struct obd_export *exp, struct lustre_id *id)
1471 {
1472         ENTRY;
1473         lmv_delete_obj(exp, id);
1474         RETURN(0);
1475 }
1476
1477 int lmv_unlink(struct obd_export *exp, struct mdc_op_data *data,
1478                struct ptlrpc_request **request)
1479 {
1480         struct obd_device *obd = exp->exp_obd;
1481         struct lmv_obd *lmv = &obd->u.lmv;
1482         int rc, i = 0;
1483         ENTRY;
1484         
1485         rc = lmv_check_connect(obd);
1486         if (rc)
1487                 RETURN(rc);
1488
1489         if (data->namelen == 0 && data->mea1 != NULL) {
1490                 /* mds asks to remove slave objects */
1491                 rc = lmv_unlink_slaves(exp, data, request);
1492                 RETURN(rc);
1493         }
1494
1495         if (data->namelen != 0) {
1496                 struct lmv_obj *obj;
1497                 
1498                 obj = lmv_grab_obj(obd, &data->id1);
1499                 if (obj) {
1500                         i = raw_name2idx(obj->hashtype, obj->objcount,
1501                                          data->name, data->namelen);
1502                         data->id1 = obj->objs[i].id;
1503                         lmv_put_obj(obj);
1504                 }
1505                 CDEBUG(D_OTHER, "unlink '%*s' in "DLID4" -> %u\n",
1506                        data->namelen, data->name, OLID4(&data->id1),
1507                        i);
1508         } else {
1509                 CDEBUG(D_OTHER, "drop i_nlink on "DLID4"\n",
1510                        OLID4(&data->id1));
1511         }
1512         rc = md_unlink(lmv->tgts[id_group(&data->id1)].ltd_exp, 
1513                        data, request); 
1514         RETURN(rc);
1515 }
1516
1517 struct obd_device *lmv_get_real_obd(struct obd_export *exp,
1518                                     char *name, int len)
1519 {
1520         struct obd_device *obd = exp->exp_obd;
1521         struct lmv_obd *lmv = &obd->u.lmv;
1522         int rc;
1523         ENTRY;
1524
1525         rc = lmv_check_connect(obd);
1526         if (rc)
1527                 RETURN(ERR_PTR(rc));
1528         obd = lmv->tgts[0].ltd_exp->exp_obd;
1529         EXIT;
1530         
1531         return obd;
1532 }
1533
1534 int lmv_init_ea_size(struct obd_export *exp, int easize,
1535                      int cookiesize)
1536 {
1537         struct obd_device *obd = exp->exp_obd;
1538         struct lmv_obd *lmv = &obd->u.lmv;
1539         int i, rc = 0, change = 0;
1540         ENTRY;
1541
1542         if (lmv->max_easize < easize) {
1543                 lmv->max_easize = easize;
1544                 change = 1;
1545         }
1546         if (lmv->max_cookiesize < cookiesize) {
1547                 lmv->max_cookiesize = cookiesize;
1548                 change = 1;
1549         }
1550         if (change == 0)
1551                 RETURN(0);
1552         
1553         if (lmv->connected == 0)
1554                 RETURN(0);
1555
1556         for (i = 0; i < lmv->desc.ld_tgt_count; i++) {
1557                 if (lmv->tgts[i].ltd_exp == NULL) {
1558                         CWARN("%s: NULL export for %d\n", obd->obd_name, i);
1559                         continue;
1560                 }
1561
1562                 rc = obd_init_ea_size(lmv->tgts[i].ltd_exp, easize, cookiesize);
1563                 if (rc) {
1564                         CERROR("obd_init_ea_size() failed on MDT target %d, "
1565                                "error %d.\n", i, rc);
1566                         break;
1567                 }
1568         }
1569         RETURN(rc);
1570 }
1571
1572 int lmv_obd_create_single(struct obd_export *exp, struct obdo *oa,
1573                           struct lov_stripe_md **ea, struct obd_trans_info *oti)
1574 {
1575         struct obd_device *obd = exp->exp_obd;
1576         struct lmv_obd *lmv = &obd->u.lmv;
1577         struct lov_stripe_md obj_md;
1578         struct lov_stripe_md *obj_mdp = &obj_md;
1579         int rc = 0;
1580         ENTRY;
1581
1582         LASSERT(ea == NULL);
1583         LASSERT(oa->o_mds < lmv->desc.ld_tgt_count);
1584
1585         rc = obd_create(lmv->tgts[oa->o_mds].ltd_exp, oa, &obj_mdp, oti);
1586
1587         RETURN(rc);
1588 }
1589
1590 int lmv_getready(struct obd_export *exp)
1591 {
1592         struct obd_device *obd = exp->exp_obd;
1593         int rc = 0;
1594         
1595         ENTRY;
1596         rc = lmv_check_connect(obd);
1597         RETURN(rc);
1598 }
1599
1600 /*
1601  * to be called from MDS only. @oa should have correct store cookie and o_fid
1602  * values for "master" object, as it will be used.
1603  */
1604 int lmv_obd_create(struct obd_export *exp, struct obdo *oa,
1605                    struct lov_stripe_md **ea, struct obd_trans_info *oti)
1606 {
1607         struct obd_device *obd = exp->exp_obd;
1608         struct lmv_obd *lmv = &obd->u.lmv;
1609         struct lustre_id mid;
1610         int i, c, rc = 0;
1611         struct mea *mea;
1612         ENTRY;
1613
1614         rc = lmv_check_connect(obd);
1615         if (rc)
1616                 RETURN(rc);
1617
1618         LASSERT(oa != NULL);
1619         
1620         if (ea == NULL) {
1621                 rc = lmv_obd_create_single(exp, oa, NULL, oti);
1622                 if (rc)
1623                         CERROR("Can't create object, rc = %d\n", rc);
1624                 RETURN(rc);
1625         }
1626
1627         if (*ea == NULL) {
1628                 rc = obd_alloc_diskmd(exp, (struct lov_mds_md **)ea);
1629                 if (rc < 0) {
1630                         CERROR("obd_alloc_diskmd() failed, error %d\n",
1631                                rc);
1632                         RETURN(rc);
1633                 } else
1634                         rc = 0;
1635                 
1636                 if (*ea == NULL)
1637                         RETURN(-ENOMEM);
1638         }
1639
1640         /* 
1641          * here we should take care about splitted dir, so store cookie and fid
1642          * for "master" object should already be allocated and passed in @oa.
1643          */
1644         LASSERT(oa->o_id != 0);
1645         LASSERT(oa->o_fid != 0);
1646
1647         /* save "master" object id */
1648         obdo2id(&mid, oa);
1649
1650         mea = (struct mea *)*ea;
1651         mea->mea_master = -1;
1652         mea->mea_magic = MEA_MAGIC_ALL_CHARS;
1653
1654         if (!mea->mea_count || mea->mea_count > lmv->desc.ld_tgt_count)
1655                 mea->mea_count = lmv->desc.ld_tgt_count;
1656
1657         for (i = 0, c = 0; c < mea->mea_count && i < lmv->desc.ld_tgt_count; i++) {
1658                 struct lov_stripe_md obj_md;
1659                 struct lov_stripe_md *obj_mdp = &obj_md;
1660                
1661                 if (lmv->tgts[i].ltd_exp == NULL) {
1662                         /* this is "master" MDS */
1663                         mea->mea_master = i;
1664                         mea->mea_ids[c] = mid;
1665                         c++;
1666                         continue;
1667                 }
1668
1669                 /*
1670                  * "master" MDS should always be part of stripped dir,
1671                  * so scan for it.
1672                  */
1673                 if (mea->mea_master == -1 && c == mea->mea_count - 1)
1674                         continue;
1675
1676                 oa->o_valid = OBD_MD_FLGENER | OBD_MD_FLTYPE | OBD_MD_FLMODE |
1677                         OBD_MD_FLUID | OBD_MD_FLGID | OBD_MD_FLID;
1678
1679                 rc = obd_create(lmv->tgts[c].ltd_exp, oa, &obj_mdp, oti);
1680                 if (rc) {
1681                         CERROR("obd_create() failed on MDT target %d, "
1682                                "error %d\n", c, rc);
1683                         RETURN(rc);
1684                 }
1685
1686                 CDEBUG(D_OTHER, "dirobj at mds %d: "LPU64"/%u\n",
1687                        i, oa->o_id, oa->o_generation);
1688
1689
1690                 /*
1691                  * here, when object is created (or it is master and was passed
1692                  * from caller) on desired MDS we save its fid to local mea_ids.
1693                  */
1694                 LASSERT(oa->o_fid);
1695
1696                 /* 
1697                  * store cookie should be defined here for both cases (master
1698                  * object and not master), because master is already created.
1699                  */
1700                 LASSERT(oa->o_id);
1701
1702                 /* fill mea by store cookie and fid */
1703                 obdo2id(&mea->mea_ids[c], oa);
1704                 c++;
1705         }
1706         LASSERT(c == mea->mea_count);
1707
1708         CDEBUG(D_OTHER, "%d dirobjects created\n",
1709                (int)mea->mea_count);
1710         
1711         RETURN(rc);
1712 }
1713
1714 static int lmv_llog_init(struct obd_device *obd, struct obd_llogs *llogs, 
1715                          struct obd_device *tgt, int count,
1716                          struct llog_catid *logid)
1717 {
1718         struct llog_ctxt *ctxt;
1719         int rc;
1720         ENTRY;
1721
1722         rc = obd_llog_setup(obd, llogs, LLOG_CONFIG_REPL_CTXT, tgt, 0, NULL,
1723                             &llog_client_ops);
1724         if (rc == 0) {
1725                 ctxt = llog_get_context(llogs, LLOG_CONFIG_REPL_CTXT);
1726                 ctxt->loc_imp = tgt->u.cli.cl_import;
1727         }
1728
1729         RETURN(rc);
1730 }
1731
1732 static int lmv_llog_finish(struct obd_device *obd,
1733                            struct obd_llogs *llogs, int count)
1734 {
1735         int rc;
1736         ENTRY;
1737
1738         rc = obd_llog_cleanup(llog_get_context(llogs, LLOG_CONFIG_REPL_CTXT));
1739         RETURN(rc);
1740 }
1741
1742 static int lmv_get_info(struct obd_export *exp, __u32 keylen,
1743                         void *key, __u32 *vallen, void *val)
1744 {
1745         struct obd_device *obd;
1746         struct lmv_obd *lmv;
1747         int rc = 0;
1748         ENTRY;
1749
1750         obd = class_exp2obd(exp);
1751         if (obd == NULL) {
1752                 CDEBUG(D_IOCTL, "invalid client cookie "LPX64"\n",
1753                        exp->exp_handle.h_cookie);
1754                 RETURN(-EINVAL);
1755         }
1756
1757         lmv = &obd->u.lmv;
1758         if (keylen == 6 && memcmp(key, "mdsize", 6) == 0) {
1759                 __u32 *mdsize = val;
1760                 *vallen = sizeof(__u32);
1761                 *mdsize = sizeof(struct lustre_id) * lmv->desc.ld_tgt_count
1762                         + sizeof(struct mea);
1763                 RETURN(0);
1764         } else if (keylen == 6 && memcmp(key, "mdsnum", 6) == 0) {
1765                 struct obd_uuid *cluuid = &lmv->cluuid;
1766                 struct lmv_tgt_desc *tgts;
1767                 __u32 *mdsnum = val;
1768                 int i;
1769
1770                 for (i = 0, tgts = lmv->tgts; i < lmv->desc.ld_tgt_count; i++, tgts++) {
1771                         if (obd_uuid_equals(&tgts->uuid, cluuid)) {
1772                                 *vallen = sizeof(__u32);
1773                                 *mdsnum = i;
1774                                 RETURN(0);
1775                         }
1776                 }
1777                 LASSERT(0);
1778         } else if (keylen == 6 && memcmp(key, "rootid", 6) == 0) {
1779                 /* getting rootid from first MDS. */
1780                 rc = obd_get_info(lmv->tgts[0].ltd_exp, keylen, key,
1781                                   vallen, val);
1782                 RETURN(rc);
1783         } else if (keylen >= strlen("lmvdesc") && strcmp(key, "lmvdesc") == 0) {
1784                 struct lmv_desc *desc_ret = val;
1785                 *desc_ret = lmv->desc;
1786                 RETURN(0);
1787         }
1788
1789         CDEBUG(D_IOCTL, "invalid key\n");
1790         RETURN(-EINVAL);
1791 }
1792
1793 int lmv_set_info(struct obd_export *exp, obd_count keylen,
1794                  void *key, obd_count vallen, void *val)
1795 {
1796         struct obd_device *obd;
1797         struct lmv_obd *lmv;
1798         ENTRY;
1799
1800         obd = class_exp2obd(exp);
1801         if (obd == NULL) {
1802                 CDEBUG(D_IOCTL, "invalid client cookie "LPX64"\n",
1803                        exp->exp_handle.h_cookie);
1804                 RETURN(-EINVAL);
1805         }
1806         lmv = &obd->u.lmv;
1807
1808         if (keylen >= strlen("inter_mds") && strcmp(key, "inter_mds") == 0) {
1809                 lmv->server_timeout = 1;
1810                 lmv_set_timeouts(obd);
1811                 RETURN(0);
1812         }
1813         
1814         RETURN(-EINVAL);
1815 }
1816
1817 int lmv_packmd(struct obd_export *exp, struct lov_mds_md **lmmp,
1818                struct lov_stripe_md *lsm)
1819 {
1820         struct obd_device *obd = class_exp2obd(exp);
1821         struct lmv_obd *lmv = &obd->u.lmv;
1822         int mea_size;
1823         ENTRY;
1824
1825         mea_size = sizeof(struct lustre_id) * 
1826                 lmv->desc.ld_tgt_count + sizeof(struct mea);
1827         if (!lmmp)
1828                 RETURN(mea_size);
1829
1830         if (*lmmp && !lsm) {
1831                 OBD_FREE(*lmmp, mea_size);
1832                 *lmmp = NULL;
1833                 RETURN(0);
1834         }
1835
1836         if (*lmmp == NULL) {
1837                 OBD_ALLOC(*lmmp, mea_size);
1838                 if (*lmmp == NULL)
1839                         RETURN(-ENOMEM);
1840         }
1841
1842         if (!lsm)
1843                 RETURN(mea_size);
1844
1845 #warning "MEA packing/convertation must be here! -bzzz"
1846         memcpy(*lmmp, lsm, mea_size);
1847         RETURN(mea_size);
1848 }
1849
1850 int lmv_unpackmd(struct obd_export *exp, struct lov_stripe_md **mem_tgt,
1851                  struct lov_mds_md *disk_src, int mdsize)
1852 {
1853         struct obd_device *obd = class_exp2obd(exp);
1854         struct lmv_obd *lmv = &obd->u.lmv;
1855         struct mea **tmea = (struct mea **) mem_tgt;
1856         struct mea *mea = (void *) disk_src;
1857         int mea_size;
1858         ENTRY;
1859
1860         mea_size = sizeof(struct lustre_id) * 
1861                 lmv->desc.ld_tgt_count + sizeof(struct mea);
1862         if (mem_tgt == NULL)
1863                 return mea_size;
1864
1865         if (*mem_tgt != NULL && disk_src == NULL) {
1866                 OBD_FREE(*tmea, mea_size);
1867                 RETURN(0);
1868         }
1869
1870         LASSERT(mea_size == mdsize);
1871
1872         OBD_ALLOC(*tmea, mea_size);
1873         if (*tmea == NULL)
1874                 RETURN(-ENOMEM);
1875
1876         if (!disk_src)
1877                 RETURN(mea_size);
1878
1879 #warning "MEA unpacking/convertation must be here! -bzzz"
1880         memcpy(*tmea, mea, mdsize);
1881         RETURN(mea_size);
1882 }
1883
1884 int lmv_brw(int rw, struct obd_export *exp, struct obdo *oa,
1885             struct lov_stripe_md *ea, obd_count oa_bufs,
1886             struct brw_page *pgarr, struct obd_trans_info *oti)
1887 {
1888         struct obd_device *obd = exp->exp_obd;
1889         struct lmv_obd *lmv = &obd->u.lmv;
1890         struct mea *mea = (struct mea *) ea;
1891         int err;
1892       
1893         LASSERT(oa != NULL);
1894         LASSERT(ea != NULL);
1895         LASSERT(pgarr != NULL);
1896         LASSERT(oa->o_mds < lmv->desc.ld_tgt_count);
1897
1898         oa->o_gr = id_gen(&mea->mea_ids[oa->o_mds]);
1899         oa->o_id = id_ino(&mea->mea_ids[oa->o_mds]);
1900         oa->o_valid = OBD_MD_FLID | OBD_MD_FLGROUP;
1901         
1902         err = obd_brw(rw, lmv->tgts[oa->o_mds].ltd_exp,
1903                       oa, NULL, oa_bufs, pgarr, oti);
1904         RETURN(err);
1905 }
1906
1907 struct obd_ops lmv_obd_ops = {
1908         .o_owner                = THIS_MODULE,
1909         .o_attach               = lmv_attach,
1910         .o_detach               = lmv_detach,
1911         .o_setup                = lmv_setup,
1912         .o_cleanup              = lmv_cleanup,
1913         .o_connect              = lmv_connect,
1914         .o_disconnect           = lmv_disconnect,
1915         .o_statfs               = lmv_statfs,
1916         .o_llog_init            = lmv_llog_init,
1917         .o_llog_finish          = lmv_llog_finish,
1918         .o_get_info             = lmv_get_info,
1919         .o_set_info             = lmv_set_info,
1920         .o_create               = lmv_obd_create,
1921         .o_packmd               = lmv_packmd,
1922         .o_unpackmd             = lmv_unpackmd,
1923         .o_brw                  = lmv_brw,
1924         .o_init_ea_size         = lmv_init_ea_size,
1925         .o_notify               = lmv_notify,
1926         .o_iocontrol            = lmv_iocontrol,
1927         .o_getready             = lmv_getready,
1928 };
1929
1930 struct md_ops lmv_md_ops = {
1931         .m_getstatus           = lmv_getstatus,
1932         .m_getattr             = lmv_getattr,
1933         .m_change_cbdata       = lmv_change_cbdata,
1934         .m_change_cbdata_name  = lmv_change_cbdata_name,
1935         .m_close               = lmv_close,
1936         .m_create              = lmv_create,
1937         .m_done_writing        = lmv_done_writing,
1938         .m_enqueue             = lmv_enqueue,
1939         .m_getattr_lock        = lmv_getattr_lock,
1940         .m_intent_lock         = lmv_intent_lock,
1941         .m_link                = lmv_link,
1942         .m_rename              = lmv_rename,
1943         .m_setattr             = lmv_setattr,
1944         .m_sync                = lmv_sync,
1945         .m_readpage            = lmv_readpage,
1946         .m_unlink              = lmv_unlink,
1947         .m_get_real_obd        = lmv_get_real_obd,
1948         .m_valid_attrs         = lmv_valid_attrs,
1949         .m_delete_inode        = lmv_delete_inode,
1950 };
1951
1952 int __init lmv_init(void)
1953 {
1954         struct lprocfs_static_vars lvars;
1955         int rc;
1956
1957         obj_cache = kmem_cache_create("lmv_objects",
1958                                       sizeof(struct lmv_obj),
1959                                       0, 0, NULL, NULL);
1960         if (!obj_cache) {
1961                 CERROR("error allocating lmv objects cache\n");
1962                 return -ENOMEM;
1963         }
1964
1965         lprocfs_init_vars(lmv, &lvars);
1966         rc = class_register_type(&lmv_obd_ops, &lmv_md_ops,
1967                                  lvars.module_vars,
1968                                  OBD_LMV_DEVICENAME);
1969         if (rc)
1970                 kmem_cache_destroy(obj_cache);
1971         
1972         return rc;
1973 }
1974
1975 #ifdef __KERNEL__
1976 static void lmv_exit(void)
1977 {
1978         class_unregister_type(OBD_LMV_DEVICENAME);
1979
1980         LASSERTF(kmem_cache_destroy(obj_cache) == 0,
1981                  "can't free lmv objects cache, %d object(s)"
1982                  "still in use\n", atomic_read(&obj_cache_count));
1983 }
1984
1985 MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
1986 MODULE_DESCRIPTION("Lustre Logical Metadata Volume OBD driver");
1987 MODULE_LICENSE("GPL");
1988
1989 module_init(lmv_init);
1990 module_exit(lmv_exit);
1991 #endif