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