Whamcloud - gitweb
- cleanups about getattr_name. By now getattr_lock is used everywhere.
[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 static void lmv_activate_target(struct lmv_obd *lmv,
53                                 struct lmv_tgt_desc *tgt,
54                                 int activate)
55 {
56         if (tgt->active == activate)
57                 return;
58         
59         tgt->active = activate;
60         lmv->desc.ld_active_tgt_count += (activate ? 1 : -1);
61 }
62
63 /* Error codes:
64  *
65  *  -EINVAL  : UUID can't be found in the LMV's target list
66  *  -ENOTCONN: The UUID is found, but the target connection is bad (!)
67  *  -EBADF   : The UUID is found, but the OBD of the wrong type (!)
68  */
69 static int lmv_set_mdc_active(struct lmv_obd *lmv, struct obd_uuid *uuid,
70                               int activate)
71 {
72         struct obd_device *obd;
73         struct lmv_tgt_desc *tgt;
74         int i, rc = 0;
75         ENTRY;
76
77         CDEBUG(D_INFO, "Searching in lmv %p for uuid %s (activate=%d)\n",
78                lmv, uuid->uuid, activate);
79
80         spin_lock(&lmv->lmv_lock);
81         for (i = 0, tgt = lmv->tgts; i < lmv->desc.ld_tgt_count; i++, tgt++) {
82                 if (tgt->ltd_exp == NULL)
83                         continue;
84
85                 CDEBUG(D_INFO, "lmv idx %d is %s conn "LPX64"\n",
86                        i, tgt->uuid.uuid, tgt->ltd_exp->exp_handle.h_cookie);
87
88                 if (strncmp(uuid->uuid, tgt->uuid.uuid, sizeof uuid->uuid) == 0)
89                         break;
90         }
91
92         if (i == lmv->desc.ld_tgt_count)
93                 GOTO(out_lmv_lock, rc = -EINVAL);
94
95         obd = class_exp2obd(tgt->ltd_exp);
96         if (obd == NULL)
97                 GOTO(out_lmv_lock, rc = -ENOTCONN);
98
99         CDEBUG(D_INFO, "Found OBD %s=%s device %d (%p) type %s at LMV idx %d\n",
100                obd->obd_name, obd->obd_uuid.uuid, obd->obd_minor, obd,
101                obd->obd_type->typ_name, i);
102         LASSERT(strcmp(obd->obd_type->typ_name, LUSTRE_MDC_NAME) == 0);
103
104         if (tgt->active == activate) {
105                 CDEBUG(D_INFO, "OBD %p already %sactive!\n", obd,
106                        activate ? "" : "in");
107                 GOTO(out_lmv_lock, rc);
108         }
109
110         CDEBUG(D_INFO, "Marking OBD %p %sactive\n",
111                obd, activate ? "" : "in");
112
113         lmv_activate_target(lmv, tgt, activate);
114
115         EXIT;
116         
117  out_lmv_lock:
118         spin_unlock(&lmv->lmv_lock);
119         return rc;
120 }
121
122 static int lmv_notify(struct obd_device *obd, struct obd_device *watched,
123                       int active, void *data)
124 {
125         int rc;
126         struct obd_uuid *uuid;
127
128         if (strcmp(watched->obd_type->typ_name, LUSTRE_MDC_NAME)) {
129                 CERROR("unexpected notification of %s %s!\n",
130                        watched->obd_type->typ_name,
131                        watched->obd_name);
132                 return -EINVAL;
133         }
134         uuid = &watched->u.cli.cl_import->imp_target_uuid;
135
136         /* Set MDC as active before notifying the observer, so the observer can
137          * use the MDC normally.
138          */
139         rc = lmv_set_mdc_active(&obd->u.lmv, uuid, active);
140         if (rc) {
141                 CERROR("%sactivation of %s failed: %d\n",
142                        active ? "" : "de", uuid->uuid, rc);
143                 RETURN(rc);
144         }
145
146         if (obd->obd_observer)
147                 /* Pass the notification up the chain. */
148                 rc = obd_notify(obd->obd_observer, watched, active, data);
149
150         RETURN(rc);
151 }
152
153 int lmv_attach(struct obd_device *dev, obd_count len, void *data)
154 {
155         struct lprocfs_static_vars lvars;
156         int rc;
157         ENTRY;
158
159         lprocfs_init_vars(lmv, &lvars);
160         rc = lprocfs_obd_attach(dev, lvars.obd_vars);
161         if (rc == 0) {
162 #ifdef __KERNEL__
163                 struct proc_dir_entry *entry;
164                 
165                 entry = create_proc_entry("target_obd_status", 0444, 
166                                            dev->obd_proc_entry);
167                 if (entry == NULL)
168                         RETURN(-ENOMEM);
169                 entry->proc_fops = &lmv_proc_target_fops; 
170                 entry->data = dev;
171 #endif
172        }
173         RETURN (rc);
174 }
175
176 int lmv_detach(struct obd_device *dev)
177 {
178         return lprocfs_obd_detach(dev);
179 }
180
181 /* this is fake connect function. Its purpose is to initialize lmv and say
182  * caller that everything is okay. Real connection will be performed later. */
183 static int lmv_connect(struct lustre_handle *conn, struct obd_device *obd,
184                        struct obd_uuid *cluuid, unsigned long flags)
185 {
186 #ifdef __KERNEL__
187         struct proc_dir_entry *lmv_proc_dir;
188 #endif
189         struct lmv_obd *lmv = &obd->u.lmv;
190         struct obd_export *exp;
191         int rc = 0;
192         ENTRY;
193
194         rc = class_connect(conn, obd, cluuid);
195         if (rc) {
196                 CERROR("class_connection() returned %d\n", rc);
197                 RETURN(rc);
198         }
199
200         exp = class_conn2export(conn);
201         
202         /* we don't want to actually do the underlying connections more than
203          * once, so keep track. */
204         lmv->refcount++;
205         if (lmv->refcount > 1) {
206                 class_export_put(exp);
207                 RETURN(0);
208         }
209
210         lmv->exp = exp;
211         lmv->connected = 0;
212         lmv->cluuid = *cluuid;
213         lmv->connect_flags = flags;
214         sema_init(&lmv->init_sem, 1);
215
216 #ifdef __KERNEL__
217         lmv_proc_dir = lprocfs_register("target_obds", obd->obd_proc_entry,
218                                         NULL, NULL);
219         if (IS_ERR(lmv_proc_dir)) {
220                 CERROR("could not register /proc/fs/lustre/%s/%s/target_obds.",
221                        obd->obd_type->typ_name, obd->obd_name);
222                 lmv_proc_dir = NULL;
223         }
224 #endif
225
226         /* 
227          * all real clients shouls perform actual connection rightaway, because
228          * it is possible, that LMV will not have opportunity to connect
229          * targets, as MDC stuff will bit called directly, for instance while
230          * reading ../mdc/../kbytesfree procfs file, etc.
231          */
232         if (flags & OBD_OPT_REAL_CLIENT)
233                 rc = lmv_check_connect(obd);
234
235 #ifdef __KERNEL__
236         if (lmv_proc_dir)
237                 lprocfs_remove(lmv_proc_dir);
238 #endif
239
240         RETURN(rc);
241 }
242
243 void lmv_set_timeouts(struct obd_device *obd)
244 {
245         struct lmv_tgt_desc *tgts;
246         struct lmv_obd *lmv;
247         int i;
248
249         lmv = &obd->u.lmv;
250         if (lmv->server_timeout == 0)
251                 return;
252
253         if (lmv->connected == 0)
254                 return;
255
256         for (i = 0, tgts = lmv->tgts; i < lmv->desc.ld_tgt_count; i++, tgts++) {
257                 if (tgts->ltd_exp == NULL)
258                         continue;
259                 
260                 obd_set_info(tgts->ltd_exp, strlen("inter_mds"),
261                              "inter_mds", 0, NULL);
262         }
263 }
264
265 #define MAX_STRING_SIZE 128
266
267 /* performs a check if passed obd is connected. If no - connect it. */
268 int lmv_check_connect(struct obd_device *obd)
269 {
270 #ifdef __KERNEL__
271         struct proc_dir_entry *lmv_proc_dir;
272 #endif
273         struct lmv_obd *lmv = &obd->u.lmv;
274         struct lmv_tgt_desc *tgts;
275         struct obd_uuid *cluuid;
276         struct obd_export *exp;
277         int rc, rc2, i;
278
279         if (lmv->connected)
280                 return 0;
281         
282         down(&lmv->init_sem);
283         if (lmv->connected) {
284                 up(&lmv->init_sem);
285                 return 0;
286         }
287
288         cluuid = &lmv->cluuid;
289         exp = lmv->exp;
290         
291         CDEBUG(D_OTHER, "time to connect %s to %s\n",
292                cluuid->uuid, obd->obd_name);
293
294         for (i = 0, tgts = lmv->tgts; i < lmv->desc.ld_tgt_count; i++, tgts++) {
295                 struct obd_device *tgt_obd;
296                 struct lustre_handle conn = {0, };
297                 struct obd_uuid lmv_mdc_uuid = { "LMV_MDC_UUID" };
298
299                 LASSERT(tgts != NULL);
300
301                 tgt_obd = class_find_client_obd(&tgts->uuid, LUSTRE_MDC_NAME, 
302                                                 &obd->obd_uuid);
303                 if (!tgt_obd) {
304                         CERROR("Target %s not attached\n", tgts->uuid.uuid);
305                         GOTO(out_disc, rc = -EINVAL);
306                 }
307
308                 /* for MDS: don't connect to yourself */
309                 if (obd_uuid_equals(&tgts->uuid, cluuid)) {
310                         CDEBUG(D_OTHER, "don't connect back to %s\n",
311                                cluuid->uuid);
312                         tgts->ltd_exp = NULL;
313                         continue;
314                 }
315
316                 CDEBUG(D_OTHER, "connect to %s(%s) - %s, %s FOR %s\n",
317                         tgt_obd->obd_name, tgt_obd->obd_uuid.uuid,
318                         tgts->uuid.uuid, obd->obd_uuid.uuid,
319                         cluuid->uuid);
320
321                 if (!tgt_obd->obd_set_up) {
322                         CERROR("Target %s not set up\n", tgts->uuid.uuid);
323                         GOTO(out_disc, rc = -EINVAL);
324                 }
325                 
326                 rc = obd_connect(&conn, tgt_obd, &lmv_mdc_uuid,
327                                  lmv->connect_flags);
328                 if (rc) {
329                         CERROR("Target %s connect error %d\n",
330                                 tgts->uuid.uuid, rc);
331                         GOTO(out_disc, rc);
332                 }
333                 tgts->ltd_exp = class_conn2export(&conn);
334
335                 obd_init_ea_size(tgts->ltd_exp, lmv->max_easize,
336                                  lmv->max_cookiesize);
337
338                 rc = obd_register_observer(tgt_obd, obd);
339                 if (rc) {
340                         CERROR("Target %s register_observer error %d\n",
341                                tgts->uuid.uuid, rc);
342                         obd_disconnect(tgts->ltd_exp, 0);
343                         GOTO(out_disc, rc);
344                 }
345
346                 lmv->desc.ld_active_tgt_count++;
347                 tgts->active = 1;
348
349                 CDEBUG(D_OTHER, "connected to %s(%s) successfully (%d)\n",
350                         tgt_obd->obd_name, tgt_obd->obd_uuid.uuid,
351                         atomic_read(&obd->obd_refcount));
352
353 #ifdef __KERNEL__
354                 lmv_proc_dir = lprocfs_srch(obd->obd_proc_entry, "target_obds");
355                 if (lmv_proc_dir) {
356                         struct obd_device *mdc_obd = class_conn2obd(&conn);
357                         struct proc_dir_entry *mdc_symlink;
358                         char name[MAX_STRING_SIZE + 1];
359
360                         LASSERT(mdc_obd != NULL);
361                         LASSERT(mdc_obd->obd_type != NULL);
362                         LASSERT(mdc_obd->obd_type->typ_name != NULL);
363                         name[MAX_STRING_SIZE] = '\0';
364                         snprintf(name, MAX_STRING_SIZE, "../../../%s/%s",
365                                  mdc_obd->obd_type->typ_name,
366                                  mdc_obd->obd_name);
367                         mdc_symlink = proc_symlink(mdc_obd->obd_name,
368                                                    lmv_proc_dir, name);
369                         if (mdc_symlink == NULL) {
370                                 CERROR("could not register LMV target "
371                                        "/proc/fs/lustre/%s/%s/target_obds/%s.",
372                                        obd->obd_type->typ_name, obd->obd_name,
373                                        mdc_obd->obd_name);
374                                 lprocfs_remove(lmv_proc_dir);
375                                 lmv_proc_dir = NULL;
376                         }
377                 }
378 #endif
379         }
380
381         lmv_set_timeouts(obd);
382         class_export_put(exp);
383         lmv->connected = 1;
384         up(&lmv->init_sem);
385         return 0;
386
387  out_disc:
388         while (i-- > 0) {
389                 struct obd_uuid uuid;
390                 --tgts;
391                 --lmv->desc.ld_active_tgt_count;
392                 tgts->active = 0;
393                 /* save for CERROR below; (we know it's terminated) */
394                 uuid = tgts->uuid;
395                 rc2 = obd_disconnect(tgts->ltd_exp, 0);
396                 if (rc2)
397                         CERROR("error: LMV target %s disconnect on MDC idx %d: "
398                                "error %d\n", uuid.uuid, i, rc2);
399         }
400         class_disconnect(exp, 0);
401         up(&lmv->init_sem);
402         RETURN (rc);
403 }
404
405 static int lmv_disconnect(struct obd_export *exp, int flags)
406 {
407         struct obd_device *obd = class_exp2obd(exp);
408         struct lmv_obd *lmv = &obd->u.lmv;
409
410 #ifdef __KERNEL__
411         struct proc_dir_entry *lmv_proc_dir;
412 #endif
413         int rc, i;
414         ENTRY;
415
416         if (!lmv->tgts)
417                 goto out_local;
418
419         /* Only disconnect the underlying layers on the final disconnect. */
420         lmv->refcount--;
421         if (lmv->refcount != 0)
422                 goto out_local;
423
424 #ifdef __KERNEL__
425         lmv_proc_dir = lprocfs_srch(obd->obd_proc_entry, "target_obds");
426 #endif
427
428         for (i = 0; i < lmv->desc.ld_tgt_count; i++) {
429                 struct obd_device *mdc_obd; 
430                 
431                 if (lmv->tgts[i].ltd_exp == NULL)
432                         continue;
433
434                 mdc_obd = class_exp2obd(lmv->tgts[i].ltd_exp);
435
436 #ifdef __KERNEL__
437                 if (lmv_proc_dir) {
438                         struct proc_dir_entry *mdc_symlink;
439
440                         mdc_symlink = lprocfs_srch(lmv_proc_dir, mdc_obd->obd_name);
441                         if (mdc_symlink) {
442                                 lprocfs_remove(mdc_symlink);
443                         } else {
444                                 CERROR("/proc/fs/lustre/%s/%s/target_obds/%s missing\n",
445                                        obd->obd_type->typ_name, obd->obd_name,
446                                        mdc_obd->obd_name);
447                         }
448                 }
449 #endif
450                 if (obd->obd_no_recov) {
451                         if (mdc_obd)
452                                 mdc_obd->obd_no_recov = 1;
453                 }
454                 CDEBUG(D_OTHER, "disconnected from %s(%s) successfully\n",
455                         lmv->tgts[i].ltd_exp->exp_obd->obd_name,
456                         lmv->tgts[i].ltd_exp->exp_obd->obd_uuid.uuid);
457
458                 obd_register_observer(lmv->tgts[i].ltd_exp->exp_obd, NULL);
459                 rc = obd_disconnect(lmv->tgts[i].ltd_exp, flags);
460                 if (rc) {
461                         if (lmv->tgts[i].active) {
462                                 CERROR("Target %s disconnect error %d\n",
463                                        lmv->tgts[i].uuid.uuid, rc);
464                         }
465                         rc = 0;
466                 }
467                 
468                 lmv_activate_target(lmv, &lmv->tgts[i], 0);
469                 lmv->tgts[i].ltd_exp = NULL;
470         }
471
472 #ifdef __KERNEL__
473         if (lmv_proc_dir) {
474                 lprocfs_remove(lmv_proc_dir);
475         } else {
476                 CERROR("/proc/fs/lustre/%s/%s/target_obds missing\n",
477                        obd->obd_type->typ_name, obd->obd_name);
478         }
479 #endif
480
481 out_local:
482         /* this is the case when no real connection is established by
483          * lmv_check_connect(). */
484         if (!lmv->connected)
485                 class_export_put(exp);
486         rc = class_disconnect(exp, 0);
487         if (lmv->refcount == 0)
488                 lmv->connected = 0;
489         RETURN(rc);
490 }
491
492 static int lmv_iocontrol(unsigned int cmd, struct obd_export *exp,
493                          int len, void *karg, void *uarg)
494 {
495         struct obd_device *obddev = class_exp2obd(exp);
496         struct lmv_obd *lmv = &obddev->u.lmv;
497         int i, rc = 0, set = 0;
498
499         ENTRY;
500
501         if (lmv->desc.ld_tgt_count == 0)
502                 RETURN(-ENOTTY);
503         
504         for (i = 0; i < lmv->desc.ld_tgt_count; i++) {
505                 int err;
506
507                 if (lmv->tgts[i].ltd_exp == NULL)
508                         continue;
509
510                 err = obd_iocontrol(cmd, lmv->tgts[i].ltd_exp, len, karg, uarg);
511                 if (err) {
512                         if (lmv->tgts[i].active) {
513                                 CERROR("error: iocontrol MDC %s on MDT"
514                                        "idx %d: err = %d\n",
515                                        lmv->tgts[i].uuid.uuid, i, err);
516                                 if (!rc)
517                                         rc = err;
518                         }
519                 } else
520                         set = 1;
521         }
522         if (!set && !rc)
523                 rc = -EIO;
524
525         RETURN(rc);
526 }
527
528 static int lmv_setup(struct obd_device *obd, obd_count len, void *buf)
529 {
530         int i, rc = 0;
531         struct lmv_desc *desc;
532         struct obd_uuid *uuids;
533         struct lmv_tgt_desc *tgts;
534         struct obd_device *tgt_obd;
535         struct lustre_cfg *lcfg = buf;
536         struct lmv_obd *lmv = &obd->u.lmv;
537         ENTRY;
538
539         if (lcfg->lcfg_inllen1 < 1) {
540                 CERROR("LMV setup requires a descriptor\n");
541                 RETURN(-EINVAL);
542         }
543
544         if (lcfg->lcfg_inllen2 < 1) {
545                 CERROR("LMV setup requires an OST UUID list\n");
546                 RETURN(-EINVAL);
547         }
548
549         desc = (struct lmv_desc *)lcfg->lcfg_inlbuf1;
550         if (sizeof(*desc) > lcfg->lcfg_inllen1) {
551                 CERROR("descriptor size wrong: %d > %d\n",
552                        (int)sizeof(*desc), lcfg->lcfg_inllen1);
553                 RETURN(-EINVAL);
554         }
555
556         uuids = (struct obd_uuid *)lcfg->lcfg_inlbuf2;
557         if (sizeof(*uuids) * desc->ld_tgt_count != lcfg->lcfg_inllen2) {
558                 CERROR("UUID array size wrong: %u * %u != %u\n",
559                        sizeof(*uuids), desc->ld_tgt_count, lcfg->lcfg_inllen2);
560                 RETURN(-EINVAL);
561         }
562
563         lmv->tgts_size = sizeof(struct lmv_tgt_desc) * desc->ld_tgt_count;
564         OBD_ALLOC(lmv->tgts, lmv->tgts_size);
565         if (lmv->tgts == NULL) {
566                 CERROR("Out of memory\n");
567                 RETURN(-ENOMEM);
568         }
569
570         lmv->desc = *desc;
571         spin_lock_init(&lmv->lmv_lock);
572         
573         for (i = 0, tgts = lmv->tgts; i < desc->ld_tgt_count; i++, tgts++)
574                 tgts->uuid = uuids[i];
575         
576         lmv->max_cookiesize = 0;
577
578         lmv->max_easize = sizeof(struct lustre_id) *
579                 desc->ld_tgt_count + sizeof(struct mea);
580         
581         rc = lmv_setup_mgr(obd);
582         if (rc) {
583                 CERROR("Can't setup LMV object manager, "
584                        "error %d.\n", rc);
585                 OBD_FREE(lmv->tgts, lmv->tgts_size);
586         }
587
588         tgt_obd = class_find_client_obd(&lmv->tgts->uuid, LUSTRE_MDC_NAME, 
589                                         &obd->obd_uuid);
590         if (!tgt_obd) {
591                 CERROR("Target %s not attached\n", lmv->tgts->uuid.uuid);
592                 RETURN(-EINVAL);
593         }
594
595         RETURN(rc);
596 }
597
598 static int lmv_cleanup(struct obd_device *obd, int flags) 
599 {
600         struct lmv_obd *lmv = &obd->u.lmv;
601         ENTRY;
602
603         lmv_cleanup_mgr(obd);
604         OBD_FREE(lmv->tgts, lmv->tgts_size);
605         
606         RETURN(0);
607 }
608
609 static int lmv_statfs(struct obd_device *obd, struct obd_statfs *osfs,
610                       unsigned long max_age)
611 {
612         struct lmv_obd *lmv = &obd->u.lmv;
613         struct obd_statfs temp;
614         int rc = 0, i;
615         ENTRY;
616         
617         rc = lmv_check_connect(obd);
618         if (rc)
619                 RETURN(rc);
620                 
621         for (i = 0; i < lmv->desc.ld_tgt_count; i++) {
622                 if (lmv->tgts[i].ltd_exp == NULL) {
623                         CWARN("%s: NULL export for %d\n", obd->obd_name, i);
624                         continue;
625                 }
626
627                 rc = obd_statfs(lmv->tgts[i].ltd_exp->exp_obd, &temp, max_age);
628                 if (rc) {
629                         CERROR("can't stat MDS #%d (%s)\n", i,
630                                lmv->tgts[i].ltd_exp->exp_obd->obd_name);
631                         RETURN(rc);
632                 }
633                 if (i == 0) {
634                         memcpy(osfs, &temp, sizeof(temp));
635                 } else {
636                         osfs->os_bavail += temp.os_bavail;
637                         osfs->os_blocks += temp.os_blocks;
638                         osfs->os_ffree += temp.os_ffree;
639                         osfs->os_files += temp.os_files;
640                 }
641         }
642         RETURN(rc);
643 }
644
645 static int lmv_getstatus(struct obd_export *exp, struct lustre_id *id)
646 {
647         struct obd_device *obd = exp->exp_obd;
648         struct lmv_obd *lmv = &obd->u.lmv;
649         int rc;
650         ENTRY;
651
652         rc = lmv_check_connect(obd);
653         if (rc)
654                 RETURN(rc);
655
656         rc = md_getstatus(lmv->tgts[0].ltd_exp, id);
657         id_group(id) = 0;
658         
659         RETURN(rc);
660 }
661
662 static int lmv_getattr(struct obd_export *exp, struct lustre_id *id,
663                        unsigned long valid, unsigned int ea_size,
664                        struct ptlrpc_request **request)
665 {
666         struct obd_device *obd = exp->exp_obd;
667         struct lmv_obd *lmv = &obd->u.lmv;
668         int rc, i = id_group(id);
669         struct lmv_obj *obj;
670         ENTRY;
671
672         rc = lmv_check_connect(obd);
673         if (rc)
674                 RETURN(rc);
675
676         LASSERT(i < lmv->desc.ld_tgt_count);
677
678         rc = md_getattr(lmv->tgts[i].ltd_exp, id, valid,
679                         ea_size, request);
680         if (rc)
681                 RETURN(rc);
682         
683         obj = lmv_grab_obj(obd, id);
684         
685         CDEBUG(D_OTHER, "GETATTR for "DLID4" %s\n",
686                OLID4(id), obj ? "(splitted)" : "");
687
688         /* if object is splitted, then we loop over all the slaves and gather
689          * size attribute. In ideal world we would have to gather also mds field
690          * from all slaves, as object is spread over the cluster and this is
691          * definitely interesting information and it is not good to loss it,
692          * but...*/
693         if (obj) {
694                 struct mds_body *body;
695
696                 if (*request == NULL) {
697                         lmv_put_obj(obj);
698                         RETURN(rc);
699                 }
700                         
701                 body = lustre_msg_buf((*request)->rq_repmsg, 0,
702                                       sizeof(*body));
703                 LASSERT(body != NULL);
704
705                 lmv_lock_obj(obj);
706         
707                 for (i = 0; i < obj->objcount; i++) {
708
709                         if (lmv->tgts[i].ltd_exp == NULL) {
710                                 CWARN("%s: NULL export for %d\n",
711                                       obd->obd_name, i);
712                                 continue;
713                         }
714
715                         /* skip master obj. */
716                         if (id_equal_fid(&obj->id, &obj->objs[i].id))
717                                 continue;
718                         
719                         body->size += obj->objs[i].size;
720                 }
721
722                 lmv_unlock_obj(obj);
723                 lmv_put_obj(obj);
724         }
725         
726         RETURN(rc);
727 }
728
729 static int lmv_change_cbdata(struct obd_export *exp,
730                              struct lustre_id *id, 
731                              ldlm_iterator_t it,
732                              void *data)
733 {
734         struct obd_device *obd = exp->exp_obd;
735         struct lmv_obd *lmv = &obd->u.lmv;
736         int rc = 0;
737         ENTRY;
738         
739         rc = lmv_check_connect(obd);
740         if (rc)
741                 RETURN(rc);
742         
743         CDEBUG(D_OTHER, "CBDATA for "DLID4"\n", OLID4(id));
744         LASSERT(id_group(id) < lmv->desc.ld_tgt_count);
745
746         rc = md_change_cbdata(lmv->tgts[id_group(id)].ltd_exp,
747                               id, it, data);
748         
749         RETURN(rc);
750 }
751
752 static int lmv_change_cbdata_name(struct obd_export *exp,
753                                   struct lustre_id *pid,
754                                   char *name, int len,
755                                   struct lustre_id *cid,
756                                   ldlm_iterator_t it,
757                                   void *data)
758 {
759         struct obd_device *obd = exp->exp_obd;
760         struct lmv_obd *lmv = &obd->u.lmv;
761         struct lustre_id rcid = *cid;
762         struct lmv_obj *obj;
763         int rc = 0, mds;
764         ENTRY;
765
766         rc = lmv_check_connect(obd);
767         if (rc)
768                 RETURN(rc);
769
770         LASSERT(id_group(pid) < lmv->desc.ld_tgt_count);
771         LASSERT(id_group(cid) < lmv->desc.ld_tgt_count);
772         
773         CDEBUG(D_OTHER, "CBDATA for "DLID4":%*s -> "DLID4"\n",
774                OLID4(pid), len, name, OLID4(cid));
775
776         /* this is default mds for directory name belongs to. */
777         mds = id_group(pid);
778         obj = lmv_grab_obj(obd, pid);
779         if (obj) {
780                 /* directory is splitted. look for right mds for this name. */
781                 mds = raw_name2idx(obj->hashtype, obj->objcount, name, len);
782                 rcid = obj->objs[mds].id;
783                 mds = id_group(&rcid);
784                 lmv_put_obj(obj);
785         }
786         rc = md_change_cbdata(lmv->tgts[mds].ltd_exp, &rcid, it, data);
787         RETURN(rc);
788 }
789
790 static int lmv_valid_attrs(struct obd_export *exp, struct lustre_id *id) 
791 {
792         struct obd_device *obd = exp->exp_obd;
793         struct lmv_obd *lmv = &obd->u.lmv;
794         int rc = 0;
795         ENTRY;
796
797         rc = lmv_check_connect(obd);
798         if (rc)
799                 RETURN(rc);
800
801         CDEBUG(D_OTHER, "validate "DLID4"\n", OLID4(id));
802         LASSERT(id_group(id) < lmv->desc.ld_tgt_count);
803         rc = md_valid_attrs(lmv->tgts[id_group(id)].ltd_exp, id);
804         RETURN(rc);
805 }
806
807 int lmv_close(struct obd_export *exp, struct obdo *obdo,
808               struct obd_client_handle *och,
809               struct ptlrpc_request **request)
810 {
811         struct obd_device *obd = exp->exp_obd;
812         struct lmv_obd *lmv = &obd->u.lmv;
813         int rc, i = obdo->o_mds;
814         ENTRY;
815         
816         rc = lmv_check_connect(obd);
817         if (rc)
818                 RETURN(rc);
819
820         LASSERT(i < lmv->desc.ld_tgt_count);
821         CDEBUG(D_OTHER, "CLOSE %lu/%lu/%lu\n", (unsigned long)obdo->o_mds,
822                (unsigned long)obdo->o_id, (unsigned long)obdo->o_generation);
823         rc = md_close(lmv->tgts[i].ltd_exp, obdo, och, request);
824         RETURN(rc);
825 }
826
827 int lmv_get_mea_and_update_object(struct obd_export *exp, 
828                                   struct lustre_id *id)
829 {
830         struct obd_device *obd = exp->exp_obd;
831         struct lmv_obd *lmv = &obd->u.lmv;
832         struct ptlrpc_request *req = NULL;
833         struct lmv_obj *obj;
834         struct lustre_md md;
835         unsigned long valid;
836         int mealen, rc;
837
838         md.mea = NULL;
839         mealen = MEA_SIZE_LMV(lmv);
840         
841         valid = OBD_MD_FLEASIZE | OBD_MD_FLDIREA;
842
843         /* time to update mea of parent id */
844         rc = md_getattr(lmv->tgts[id_group(id)].ltd_exp,
845                         id, valid, mealen, &req);
846         if (rc) {
847                 CERROR("md_getattr() failed, error %d\n", rc);
848                 GOTO(cleanup, rc);
849         }
850
851         rc = mdc_req2lustre_md(exp, req, 0, NULL, &md);
852         if (rc) {
853                 CERROR("mdc_req2lustre_md() failed, error %d\n", rc);
854                 GOTO(cleanup, rc);
855         }
856
857         if (md.mea == NULL)
858                 GOTO(cleanup, rc = -ENODATA);
859
860         obj = lmv_create_obj(exp, id, md.mea);
861         if (IS_ERR(obj))
862                 rc = PTR_ERR(obj);
863         
864         lmv_put_obj(obj);
865         obd_free_memmd(exp, (struct lov_stripe_md **)&md.mea);
866
867 cleanup:
868         if (req)
869                 ptlrpc_req_finished(req);
870         RETURN(rc);
871 }
872
873 int lmv_create(struct obd_export *exp, struct mdc_op_data *op_data,
874                const void *data, int datalen, int mode, __u32 uid,
875                __u32 gid, __u64 rdev, struct ptlrpc_request **request)
876 {
877         struct obd_device *obd = exp->exp_obd;
878         struct lmv_obd *lmv = &obd->u.lmv;
879         struct mds_body *body;
880         struct lmv_obj *obj;
881         int rc, mds, loop = 0;
882         ENTRY;
883
884         rc = lmv_check_connect(obd);
885         if (rc)
886                 RETURN(rc);
887
888         if (!lmv->desc.ld_active_tgt_count)
889                 RETURN(-EIO);
890 repeat:
891         LASSERT(++loop <= 2);
892         obj = lmv_grab_obj(obd, &op_data->id1);
893         if (obj) {
894                 mds = raw_name2idx(obj->hashtype, obj->objcount, 
895                                    op_data->name, op_data->namelen);
896                 op_data->id1 = obj->objs[mds].id;
897                 lmv_put_obj(obj);
898         }
899
900         CDEBUG(D_OTHER, "CREATE '%*s' on "DLID4"\n", op_data->namelen,
901                op_data->name, OLID4(&op_data->id1));
902         
903         rc = md_create(lmv->tgts[id_group(&op_data->id1)].ltd_exp, 
904                        op_data, data, datalen, mode, uid, gid, rdev, request);
905         if (rc == 0) {
906                 if (*request == NULL)
907                         RETURN(rc);
908
909                 body = lustre_msg_buf((*request)->rq_repmsg, 0,
910                                       sizeof(*body));
911                 LASSERT(body != NULL);
912                 
913                 CDEBUG(D_OTHER, "created. "DLID4"\n", OLID4(&op_data->id1));
914                 
915 /*                LASSERT(body->valid & OBD_MD_MDS ||
916                         body->mds == id_group(&op_data->id1));*/
917         } else if (rc == -ERESTART) {
918                 /* directory got splitted. time to update local object and
919                  * repeat the request with proper MDS */
920                 rc = lmv_get_mea_and_update_object(exp, &op_data->id1);
921                 if (rc == 0) {
922                         ptlrpc_req_finished(*request);
923                         goto repeat;
924                 }
925         }
926         RETURN(rc);
927 }
928
929 int lmv_done_writing(struct obd_export *exp, struct obdo *obdo)
930 {
931         struct obd_device *obd = exp->exp_obd;
932         struct lmv_obd *lmv = &obd->u.lmv;
933         int rc;
934         ENTRY;
935         rc = lmv_check_connect(obd);
936         if (rc)
937                 RETURN(rc);
938
939         /* FIXME: choose right MDC here */
940         CWARN("this method isn't implemented yet\n");
941         rc = md_done_writing(lmv->tgts[0].ltd_exp, obdo);
942         RETURN(rc);
943 }
944
945 int lmv_enqueue_slaves(struct obd_export *exp, int locktype,
946                        struct lookup_intent *it, int lockmode,
947                        struct mdc_op_data *data, struct lustre_handle *lockh,
948                        void *lmm, int lmmsize, ldlm_completion_callback cb_compl,
949                        ldlm_blocking_callback cb_blocking, void *cb_data)
950 {
951         struct obd_device *obd = exp->exp_obd;
952         struct lmv_obd *lmv = &obd->u.lmv;
953         struct mea *mea = data->mea1;
954         struct mdc_op_data data2;
955         int i, rc, mds;
956         ENTRY;
957
958         LASSERT(mea != NULL);
959         for (i = 0; i < mea->mea_count; i++) {
960                 memset(&data2, 0, sizeof(data2));
961                 data2.id1 = mea->mea_ids[i];
962                 mds = id_group(&data2.id1);
963                 
964                 if (lmv->tgts[mds].ltd_exp == NULL)
965                         continue;
966
967                 rc = md_enqueue(lmv->tgts[mds].ltd_exp, locktype, it, 
968                                 lockmode, &data2, lockh + i, lmm, lmmsize, 
969                                 cb_compl, cb_blocking, cb_data);
970                 
971                 CDEBUG(D_OTHER, "take lock on slave "DLID4" -> %d/%d\n",
972                        OLID4(&mea->mea_ids[i]), rc, it->d.lustre.it_status);
973                 if (rc)
974                         GOTO(cleanup, rc);
975                 if (it->d.lustre.it_data) {
976                         struct ptlrpc_request *req;
977                         req = (struct ptlrpc_request *) it->d.lustre.it_data;
978                         ptlrpc_req_finished(req);
979                 }
980                 
981                 if (it->d.lustre.it_status)
982                         GOTO(cleanup, rc = it->d.lustre.it_status);
983         }
984         RETURN(0);
985         
986 cleanup:
987         /* drop all taken locks */
988         while (--i >= 0) {
989                 if (lockh[i].cookie)
990                         ldlm_lock_decref(lockh + i, lockmode);
991                 lockh[i].cookie = 0;
992         }
993         RETURN(rc);
994 }
995
996 int lmv_enqueue(struct obd_export *exp, int lock_type,
997                 struct lookup_intent *it, int lock_mode,
998                 struct mdc_op_data *data, struct lustre_handle *lockh,
999                 void *lmm, int lmmsize, ldlm_completion_callback cb_compl,
1000                 ldlm_blocking_callback cb_blocking, void *cb_data)
1001 {
1002         struct obd_device *obd = exp->exp_obd;
1003         struct lmv_obd *lmv = &obd->u.lmv;
1004         struct lmv_obj *obj;
1005         int rc, mds;
1006         ENTRY;
1007
1008         rc = lmv_check_connect(obd);
1009         if (rc)
1010                 RETURN(rc);
1011
1012         if (data->mea1 && it->it_op == IT_UNLINK) {
1013                 rc = lmv_enqueue_slaves(exp, lock_type, it, lock_mode,
1014                                         data, lockh, lmm, lmmsize,
1015                                         cb_compl, cb_blocking, cb_data);
1016                 RETURN(rc);
1017         }
1018
1019         if (data->namelen) {
1020                 obj = lmv_grab_obj(obd, &data->id1);
1021                 if (obj) {
1022                         /* directory is splitted. look for right mds for this
1023                          * name */
1024                         mds = raw_name2idx(obj->hashtype, obj->objcount,
1025                                            (char *)data->name, data->namelen);
1026                         data->id1 = obj->objs[mds].id;
1027                         lmv_put_obj(obj);
1028                 }
1029         }
1030         CDEBUG(D_OTHER, "ENQUEUE '%s' on "DLID4"\n", LL_IT2STR(it),
1031                OLID4(&data->id1));
1032         
1033         rc = md_enqueue(lmv->tgts[id_group(&data->id1)].ltd_exp, 
1034                         lock_type, it, lock_mode, data, lockh, lmm, 
1035                         lmmsize, cb_compl, cb_blocking, cb_data);
1036         RETURN(rc);
1037 }
1038
1039 int lmv_getattr_lock(struct obd_export *exp, struct lustre_id *id,
1040                      char *filename, int namelen, unsigned long valid,
1041                      unsigned int ea_size, struct ptlrpc_request **request)
1042 {
1043         int rc, mds = id_group(id), loop = 0;
1044         struct obd_device *obd = exp->exp_obd;
1045         struct lmv_obd *lmv = &obd->u.lmv;
1046         struct lustre_id rid = *id;
1047         struct mds_body *body;
1048         struct lmv_obj *obj;
1049         int old_valid;
1050         ENTRY;
1051         
1052         rc = lmv_check_connect(obd);
1053         if (rc)
1054                 RETURN(rc);
1055 repeat:
1056         LASSERT(++loop <= 2);
1057         obj = lmv_grab_obj(obd, id);
1058         if (obj) {
1059                 /* directory is splitted. look for right mds for this name */
1060                 mds = raw_name2idx(obj->hashtype, obj->objcount, 
1061                                    filename, namelen - 1);
1062                 rid = obj->objs[mds].id;
1063                 lmv_put_obj(obj);
1064         }
1065         
1066         CDEBUG(D_OTHER, "getattr_lock for %*s on "DLID4" -> "DLID4"\n",
1067                namelen, filename, OLID4(id), OLID4(&rid));
1068
1069         old_valid = valid;
1070
1071         /*
1072          * here should be applied OBD_MD_FID to ->valid, because otherwise,
1073          * mds_getattr_lock() will not fetch fid component of lustre_id and
1074          * thus, next call to md_getattr_lock() will be performed to wrong mds.
1075          */
1076         if (!(old_valid & OBD_MD_FID))
1077                 valid |= OBD_MD_FID;
1078         
1079         rc = md_getattr_lock(lmv->tgts[id_group(&rid)].ltd_exp, 
1080                              &rid, filename, namelen, valid,
1081                              ea_size, request);
1082         if (rc == 0) {
1083                 /*
1084                  * this could be cross-node reference. in this case all we have
1085                  * right now is lustre_id triple. we'd like to find other
1086                  * attributes.
1087                  */
1088                 body = lustre_msg_buf((*request)->rq_repmsg, 0, sizeof(*body));
1089                 LASSERT(body != NULL);
1090                 if (body->valid & OBD_MD_MDS) {
1091                         struct ptlrpc_request *req = NULL;
1092                         
1093                         rid = body->id1;
1094                         CDEBUG(D_OTHER, "request attrs for "DLID4"\n", OLID4(&rid));
1095
1096                         /* 
1097                          * turning OBD_MD_FID fetching off, as we already have
1098                          * full lustre_id and do need to fetch fid component
1099                          * again. This will help to make thing slightly faster.
1100                          */
1101                         if (!(old_valid & OBD_MD_FID))
1102                                 valid &= ~OBD_MD_FID;
1103                         
1104                         rc = md_getattr_lock(lmv->tgts[id_group(&rid)].ltd_exp, 
1105                                              &rid, NULL, 1, valid, ea_size, &req);
1106                         ptlrpc_req_finished(*request);
1107                         *request = req;
1108                 }
1109         } else if (rc == -ERESTART) {
1110                 /* directory got splitted. time to update local object and
1111                  * repeat the request with proper MDS */
1112                 rc = lmv_get_mea_and_update_object(exp, &rid);
1113                 if (rc == 0) {
1114                         ptlrpc_req_finished(*request);
1115                         goto repeat;
1116                 }
1117         }
1118         RETURN(rc);
1119 }
1120
1121 /*
1122  * llite passes id of an target inode in data->id1 and id of directory in
1123  * data->id2
1124  */
1125 int lmv_link(struct obd_export *exp, struct mdc_op_data *data,
1126              struct ptlrpc_request **request)
1127 {
1128         struct obd_device *obd = exp->exp_obd;
1129         struct lmv_obd *lmv = &obd->u.lmv;
1130         struct lmv_obj *obj;
1131         int rc;
1132         ENTRY;
1133         
1134         rc = lmv_check_connect(obd);
1135         if (rc)
1136                 RETURN(rc);
1137
1138         if (data->namelen != 0) {
1139                 /* usual link request */
1140                 obj = lmv_grab_obj(obd, &data->id1);
1141                 if (obj) {
1142                         rc = raw_name2idx(obj->hashtype, obj->objcount, 
1143                                           data->name, data->namelen);
1144                         data->id1 = obj->objs[rc].id;
1145                         lmv_put_obj(obj);
1146                 }
1147                 
1148                 CDEBUG(D_OTHER,"link "DLID4":%*s to "DLID4"\n",
1149                        OLID4(&data->id2), data->namelen, data->name,
1150                        OLID4(&data->id1));
1151         } else {
1152                 /* request from MDS to acquire i_links for inode by id1 */
1153                 CDEBUG(D_OTHER, "inc i_nlinks for "DLID4"\n",
1154                        OLID4(&data->id1));
1155         }
1156                         
1157         rc = md_link(lmv->tgts[id_group(&data->id1)].ltd_exp, 
1158                      data, request);
1159         RETURN(rc);
1160 }
1161
1162 int lmv_rename(struct obd_export *exp, struct mdc_op_data *data,
1163                const char *old, int oldlen, const char *new, int newlen,
1164                struct ptlrpc_request **request)
1165 {
1166         struct obd_device *obd = exp->exp_obd;
1167         struct lmv_obd *lmv = &obd->u.lmv;
1168         struct lmv_obj *obj;
1169         int rc, mds;
1170         ENTRY;
1171
1172         CDEBUG(D_OTHER, "rename %*s in "DLID4" to %*s in "DLID4"\n",
1173                oldlen, old, OLID4(&data->id1), newlen, new, OLID4(&data->id2));
1174
1175         rc = lmv_check_connect(obd);
1176         if (rc)
1177                 RETURN(rc);
1178
1179         if (oldlen == 0) {
1180                 /*
1181                  * MDS with old dir entry is asking another MDS to create name
1182                  * there.
1183                  */
1184                 CDEBUG(D_OTHER,
1185                        "create %*s(%d/%d) in "DLID4" pointing "
1186                        "to "DLID4"\n", newlen, new, oldlen, newlen,
1187                        OLID4(&data->id2), OLID4(&data->id1));
1188
1189                 mds = id_group(&data->id2);
1190
1191                 /* 
1192                  * target directory can be splitted, sowe should forward request
1193                  * to the right MDS.
1194                  */
1195                 obj = lmv_grab_obj(obd, &data->id2);
1196                 if (obj) {
1197                         mds = raw_name2idx(obj->hashtype, obj->objcount, 
1198                                            (char *)new, newlen);
1199                         data->id2 = obj->objs[mds].id;
1200                         CDEBUG(D_OTHER, "forward to MDS #%u ("DLID4")\n", mds,
1201                                OLID4(&data->id2));
1202                         lmv_put_obj(obj);
1203                 }
1204                 goto request;
1205         }
1206
1207         obj = lmv_grab_obj(obd, &data->id1);
1208         if (obj) {
1209                 /*
1210                  * directory is already splitted, so we have to forward request
1211                  * to the right MDS.
1212                  */
1213                 mds = raw_name2idx(obj->hashtype, obj->objcount, 
1214                                    (char *)old, oldlen);
1215                 data->id1 = obj->objs[mds].id;
1216                 CDEBUG(D_OTHER, "forward to MDS #%u ("DLID4")\n", mds,
1217                        OLID4(&data->id1));
1218                 lmv_put_obj(obj);
1219         }
1220
1221         obj = lmv_grab_obj(obd, &data->id2);
1222         if (obj) {
1223                 /*
1224                  * directory is already splitted, so we have to forward request
1225                  * to the right MDS.
1226                  */
1227                 mds = raw_name2idx(obj->hashtype, obj->objcount, 
1228                                    (char *)new, newlen);
1229                 
1230                 data->id2 = obj->objs[mds].id;
1231                 CDEBUG(D_OTHER, "forward to MDS #%u ("DLID4")\n", mds,
1232                        OLID4(&data->id2));
1233                 lmv_put_obj(obj);
1234         }
1235         
1236         mds = id_group(&data->id1);
1237
1238 request:
1239         if (id_group(&data->id1) != id_group(&data->id2)) {
1240                 CDEBUG(D_OTHER,"cross-node rename "DLID4"/%*s to "DLID4"/%*s\n",
1241                        OLID4(&data->id1), oldlen, old, OLID4(&data->id2),
1242                        newlen, new);
1243         }
1244
1245         rc = md_rename(lmv->tgts[mds].ltd_exp, data, old, oldlen,
1246                        new, newlen, request); 
1247         RETURN(rc);
1248 }
1249
1250 int lmv_setattr(struct obd_export *exp, struct mdc_op_data *data,
1251                 struct iattr *iattr, void *ea, int ealen, void *ea2,
1252                 int ea2len, struct ptlrpc_request **request)
1253 {
1254         struct obd_device *obd = exp->exp_obd;
1255         struct lmv_obd *lmv = &obd->u.lmv;
1256         struct ptlrpc_request *req;
1257         struct mds_body *body;
1258         struct lmv_obj *obj;
1259         int rc = 0, i;
1260         ENTRY;
1261
1262         rc = lmv_check_connect(obd);
1263         if (rc)
1264                 RETURN(rc);
1265
1266         obj = lmv_grab_obj(obd, &data->id1);
1267         
1268         CDEBUG(D_OTHER, "SETATTR for "DLID4", valid 0x%x%s\n",
1269                OLID4(&data->id1), iattr->ia_valid, obj ? ", splitted" : "");
1270         
1271         if (obj) {
1272                 for (i = 0; i < obj->objcount; i++) {
1273                         data->id1 = obj->objs[i].id;
1274                         
1275                         rc = md_setattr(lmv->tgts[id_group(&data->id1)].ltd_exp, 
1276                                         data, iattr, ea, ealen, ea2, ea2len, &req);
1277
1278                         if (id_equal_fid(&obj->id, &obj->objs[i].id)) {
1279                                 /*
1280                                  * this is master object and this request should
1281                                  * be returned back to llite.
1282                                  */
1283                                 *request = req;
1284                         } else {
1285                                 ptlrpc_req_finished(req);
1286                         }
1287
1288                         if (rc)
1289                                 break;
1290                 }
1291                 lmv_put_obj(obj);
1292         } else {
1293                 LASSERT(id_group(&data->id1) < lmv->desc.ld_tgt_count);
1294                 rc = md_setattr(lmv->tgts[id_group(&data->id1)].ltd_exp,
1295                                 data, iattr, ea, ealen, ea2, ea2len, request); 
1296                 if (rc == 0) {
1297                         body = lustre_msg_buf((*request)->rq_repmsg, 0,
1298                                               sizeof(*body));
1299                         LASSERT(body != NULL);
1300                         LASSERT(id_group(&body->id1) == id_group(&data->id1));
1301                 }
1302         }
1303         RETURN(rc);
1304 }
1305
1306 int lmv_sync(struct obd_export *exp, struct lustre_id *id,
1307              struct ptlrpc_request **request)
1308 {
1309         struct obd_device *obd = exp->exp_obd;
1310         struct lmv_obd *lmv = &obd->u.lmv;
1311         int rc;
1312         ENTRY;
1313
1314         rc = lmv_check_connect(obd);
1315         if (rc)
1316                 RETURN(rc);
1317
1318         rc = md_sync(lmv->tgts[id_group(id)].ltd_exp, 
1319                      id, request);
1320         RETURN(rc);
1321 }
1322
1323 int lmv_dirobj_blocking_ast(struct ldlm_lock *lock, 
1324                             struct ldlm_lock_desc *desc,
1325                             void *data, int flag)
1326 {
1327         struct lustre_handle lockh;
1328         struct lmv_obj *obj;
1329         int rc;
1330         ENTRY;
1331
1332         switch (flag) {
1333         case LDLM_CB_BLOCKING:
1334                 ldlm_lock2handle(lock, &lockh);
1335                 rc = ldlm_cli_cancel(&lockh);
1336                 if (rc < 0) {
1337                         CDEBUG(D_INODE, "ldlm_cli_cancel: %d\n", rc);
1338                         RETURN(rc);
1339                 }
1340                 break;
1341         case LDLM_CB_CANCELING:
1342                 /* time to drop cached attrs for dirobj */
1343                 obj = lock->l_ast_data;
1344                 if (obj) {
1345                         CDEBUG(D_OTHER, "cancel %s on "LPU64"/"LPU64
1346                                ", master "DLID4"\n",
1347                                lock->l_resource->lr_name.name[3] == 1 ?
1348                                "LOOKUP" : "UPDATE",
1349                                lock->l_resource->lr_name.name[0],
1350                                lock->l_resource->lr_name.name[1], 
1351                                OLID4(&obj->id));
1352                         lmv_put_obj(obj);
1353                 }
1354                 break;
1355         default:
1356                 LBUG();
1357         }
1358         RETURN(0);
1359 }
1360
1361 void lmv_remove_dots(struct page *page)
1362 {
1363         char *kaddr = page_address(page);
1364         unsigned limit = PAGE_CACHE_SIZE;
1365         unsigned offs, rec_len;
1366         struct ext2_dir_entry_2 *p;
1367
1368         for (offs = 0; offs <= limit - EXT2_DIR_REC_LEN(1); offs += rec_len) {
1369                 p = (struct ext2_dir_entry_2 *)(kaddr + offs);
1370                 rec_len = le16_to_cpu(p->rec_len);
1371
1372                 if ((p->name_len == 1 && p->name[0] == '.') ||
1373                     (p->name_len == 2 && p->name[0] == '.' && p->name[1] == '.'))
1374                         p->inode = 0;
1375         }
1376 }
1377
1378 int lmv_readpage(struct obd_export *exp, struct lustre_id *id,
1379                  __u64 offset, struct page *page,
1380                  struct ptlrpc_request **request)
1381 {
1382         struct obd_device *obd = exp->exp_obd;
1383         struct lmv_obd *lmv = &obd->u.lmv;
1384         struct lustre_id rid = *id;
1385         struct lmv_obj *obj;
1386         int rc, i;
1387         ENTRY;
1388
1389 #warning "we need well-desgined readdir() implementation"
1390         rc = lmv_check_connect(obd);
1391         if (rc)
1392                 RETURN(rc);
1393
1394         LASSERT(id_group(id) < lmv->desc.ld_tgt_count);
1395         CDEBUG(D_OTHER, "READPAGE at %llu from "DLID4"\n",
1396                offset, OLID4(&rid));
1397
1398         obj = lmv_grab_obj(obd, id);
1399         if (obj) {
1400                 lmv_lock_obj(obj);
1401
1402                 /* find dirobj containing page with requested offset. */
1403                 for (i = 0; i < obj->objcount; i++) {
1404                         if (offset < obj->objs[i].size)
1405                                 break;
1406                         offset -= obj->objs[i].size;
1407                 }
1408                 rid = obj->objs[i].id;
1409                 
1410                 lmv_unlock_obj(obj);
1411                 lmv_put_obj(obj);
1412                 
1413                 CDEBUG(D_OTHER, "forward to "DLID4" with offset %lu\n",
1414                        OLID4(&rid), (unsigned long)offset);
1415         }
1416         rc = md_readpage(lmv->tgts[id_group(&rid)].ltd_exp, &rid, 
1417                          offset, page, request);
1418         
1419         if (rc == 0 && !id_equal_fid(&rid, id))
1420                 /* this page isn't from master object. To avoid "." and ".." 
1421                  * duplication in directory, we have to remove them from all
1422                  * slave objects */
1423                 lmv_remove_dots(page);
1424         
1425         RETURN(rc);
1426 }
1427
1428 int lmv_unlink_slaves(struct obd_export *exp, struct mdc_op_data *data,
1429                       struct ptlrpc_request **req)
1430 {
1431         struct obd_device *obd = exp->exp_obd;
1432         struct lmv_obd *lmv = &obd->u.lmv;
1433         struct mea *mea = data->mea1;
1434         struct mdc_op_data data2;
1435         int i, rc = 0, mds;
1436         ENTRY;
1437
1438         LASSERT(mea != NULL);
1439         for (i = 0; i < mea->mea_count; i++) {
1440                 memset(&data2, 0, sizeof(data2));
1441                 data2.id1 = mea->mea_ids[i];
1442                 data2.create_mode = MDS_MODE_DONT_LOCK | S_IFDIR;
1443                 
1444                 mds = id_group(&data2.id1);
1445
1446                 if (lmv->tgts[mds].ltd_exp == NULL)
1447                         continue;
1448
1449                 rc = md_unlink(lmv->tgts[mds].ltd_exp, &data2, req);
1450                 CDEBUG(D_OTHER, "unlink slave "DLID4" -> %d\n",
1451                        OLID4(&mea->mea_ids[i]), rc);
1452                 if (*req) {
1453                         ptlrpc_req_finished(*req);
1454                         *req = NULL;
1455                 }
1456                 if (rc)
1457                         break;
1458         }
1459         RETURN(rc);
1460 }
1461
1462 int lmv_delete_object(struct obd_export *exp, struct lustre_id *id)
1463 {
1464         ENTRY;
1465
1466         if (!lmv_delete_obj(exp, id)) {
1467                 CDEBUG(D_OTHER, "object "DLID4" is not found.\n",
1468                        OLID4(id));
1469         }
1470         
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_delete_object        = lmv_delete_object,
1943 };
1944
1945 int __init lmv_init(void)
1946 {
1947         struct lprocfs_static_vars lvars;
1948         int rc;
1949
1950         lprocfs_init_vars(lmv, &lvars);
1951         rc = class_register_type(&lmv_obd_ops, &lmv_md_ops,
1952                                  lvars.module_vars, OBD_LMV_DEVICENAME);
1953         RETURN(rc);
1954 }
1955
1956 #ifdef __KERNEL__
1957 static void lmv_exit(void)
1958 {
1959         class_unregister_type(OBD_LMV_DEVICENAME);
1960 }
1961
1962 MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
1963 MODULE_DESCRIPTION("Lustre Logical Metadata Volume OBD driver");
1964 MODULE_LICENSE("GPL");
1965
1966 module_init(lmv_init);
1967 module_exit(lmv_exit);
1968 #endif