1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37#define DEBUG_SUBSYSTEM S_LMV
38#include <linux/slab.h>
39#include <linux/module.h>
40#include <linux/init.h>
41#include <linux/pagemap.h>
42#include <linux/mm.h>
43#include <asm/div64.h>
44#include <linux/seq_file.h>
45#include <linux/namei.h>
46#include <linux/uaccess.h>
47
48#include "../include/lustre/lustre_idl.h"
49#include "../include/obd_support.h"
50#include "../include/lustre_lib.h"
51#include "../include/lustre_net.h"
52#include "../include/obd_class.h"
53#include "../include/lprocfs_status.h"
54#include "../include/lustre_lite.h"
55#include "../include/lustre_fid.h"
56#include "lmv_internal.h"
57
58static void lmv_activate_target(struct lmv_obd *lmv,
59 struct lmv_tgt_desc *tgt,
60 int activate)
61{
62 if (tgt->ltd_active == activate)
63 return;
64
65 tgt->ltd_active = activate;
66 lmv->desc.ld_active_tgt_count += (activate ? 1 : -1);
67}
68
69
70
71
72
73
74
75
76static int lmv_set_mdc_active(struct lmv_obd *lmv, struct obd_uuid *uuid,
77 int activate)
78{
79 struct lmv_tgt_desc *uninitialized_var(tgt);
80 struct obd_device *obd;
81 int i;
82 int rc = 0;
83
84 CDEBUG(D_INFO, "Searching in lmv %p for uuid %s (activate=%d)\n",
85 lmv, uuid->uuid, activate);
86
87 spin_lock(&lmv->lmv_lock);
88 for (i = 0; i < lmv->desc.ld_tgt_count; i++) {
89 tgt = lmv->tgts[i];
90 if (tgt == NULL || tgt->ltd_exp == NULL)
91 continue;
92
93 CDEBUG(D_INFO, "Target idx %d is %s conn %#llx\n", i,
94 tgt->ltd_uuid.uuid, tgt->ltd_exp->exp_handle.h_cookie);
95
96 if (obd_uuid_equals(uuid, &tgt->ltd_uuid))
97 break;
98 }
99
100 if (i == lmv->desc.ld_tgt_count) {
101 rc = -EINVAL;
102 goto out_lmv_lock;
103 }
104
105 obd = class_exp2obd(tgt->ltd_exp);
106 if (obd == NULL) {
107 rc = -ENOTCONN;
108 goto out_lmv_lock;
109 }
110
111 CDEBUG(D_INFO, "Found OBD %s=%s device %d (%p) type %s at LMV idx %d\n",
112 obd->obd_name, obd->obd_uuid.uuid, obd->obd_minor, obd,
113 obd->obd_type->typ_name, i);
114 LASSERT(strcmp(obd->obd_type->typ_name, LUSTRE_MDC_NAME) == 0);
115
116 if (tgt->ltd_active == activate) {
117 CDEBUG(D_INFO, "OBD %p already %sactive!\n", obd,
118 activate ? "" : "in");
119 goto out_lmv_lock;
120 }
121
122 CDEBUG(D_INFO, "Marking OBD %p %sactive\n", obd,
123 activate ? "" : "in");
124 lmv_activate_target(lmv, tgt, activate);
125
126 out_lmv_lock:
127 spin_unlock(&lmv->lmv_lock);
128 return rc;
129}
130
131static struct obd_uuid *lmv_get_uuid(struct obd_export *exp)
132{
133 struct lmv_obd *lmv = &exp->exp_obd->u.lmv;
134
135 return obd_get_uuid(lmv->tgts[0]->ltd_exp);
136}
137
138static int lmv_notify(struct obd_device *obd, struct obd_device *watched,
139 enum obd_notify_event ev, void *data)
140{
141 struct obd_connect_data *conn_data;
142 struct lmv_obd *lmv = &obd->u.lmv;
143 struct obd_uuid *uuid;
144 int rc = 0;
145
146 if (strcmp(watched->obd_type->typ_name, LUSTRE_MDC_NAME)) {
147 CERROR("unexpected notification of %s %s!\n",
148 watched->obd_type->typ_name,
149 watched->obd_name);
150 return -EINVAL;
151 }
152
153 uuid = &watched->u.cli.cl_target_uuid;
154 if (ev == OBD_NOTIFY_ACTIVE || ev == OBD_NOTIFY_INACTIVE) {
155
156
157
158
159 rc = lmv_set_mdc_active(lmv, uuid,
160 ev == OBD_NOTIFY_ACTIVE);
161 if (rc) {
162 CERROR("%sactivation of %s failed: %d\n",
163 ev == OBD_NOTIFY_ACTIVE ? "" : "de",
164 uuid->uuid, rc);
165 return rc;
166 }
167 } else if (ev == OBD_NOTIFY_OCD) {
168 conn_data = &watched->u.cli.cl_import->imp_connect_data;
169
170
171
172
173
174 obd->obd_self_export->exp_connect_data = *conn_data;
175 }
176#if 0
177 else if (ev == OBD_NOTIFY_DISCON) {
178
179
180
181 fld_client_flush(&lmv->lmv_fld);
182 }
183#endif
184
185
186
187 if (obd->obd_observer)
188 rc = obd_notify(obd->obd_observer, watched, ev, data);
189
190 return rc;
191}
192
193
194
195
196
197static int lmv_connect(const struct lu_env *env,
198 struct obd_export **exp, struct obd_device *obd,
199 struct obd_uuid *cluuid, struct obd_connect_data *data,
200 void *localdata)
201{
202 struct lmv_obd *lmv = &obd->u.lmv;
203 struct lustre_handle conn = { 0 };
204 int rc = 0;
205
206
207
208
209
210 lmv->refcount++;
211 if (lmv->refcount > 1) {
212 *exp = NULL;
213 return 0;
214 }
215
216 rc = class_connect(&conn, obd, cluuid);
217 if (rc) {
218 CERROR("class_connection() returned %d\n", rc);
219 return rc;
220 }
221
222 *exp = class_conn2export(&conn);
223 class_export_get(*exp);
224
225 lmv->exp = *exp;
226 lmv->connected = 0;
227 lmv->cluuid = *cluuid;
228
229 if (data)
230 lmv->conn_data = *data;
231
232 lmv->lmv_tgts_kobj = kobject_create_and_add("target_obds",
233 &obd->obd_kobj);
234
235
236
237
238
239
240 if (data->ocd_connect_flags & OBD_CONNECT_REAL)
241 rc = lmv_check_connect(obd);
242
243 if (rc && lmv->lmv_tgts_kobj)
244 kobject_put(lmv->lmv_tgts_kobj);
245
246 return rc;
247}
248
249static void lmv_set_timeouts(struct obd_device *obd)
250{
251 struct lmv_tgt_desc *tgt;
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; i < lmv->desc.ld_tgt_count; i++) {
263 tgt = lmv->tgts[i];
264 if (tgt == NULL || tgt->ltd_exp == NULL || tgt->ltd_active == 0)
265 continue;
266
267 obd_set_info_async(NULL, tgt->ltd_exp, sizeof(KEY_INTERMDS),
268 KEY_INTERMDS, 0, NULL, NULL);
269 }
270}
271
272static int lmv_init_ea_size(struct obd_export *exp, int easize,
273 int def_easize, int cookiesize, int def_cookiesize)
274{
275 struct obd_device *obd = exp->exp_obd;
276 struct lmv_obd *lmv = &obd->u.lmv;
277 int i;
278 int rc = 0;
279 int change = 0;
280
281 if (lmv->max_easize < easize) {
282 lmv->max_easize = easize;
283 change = 1;
284 }
285 if (lmv->max_def_easize < def_easize) {
286 lmv->max_def_easize = def_easize;
287 change = 1;
288 }
289 if (lmv->max_cookiesize < cookiesize) {
290 lmv->max_cookiesize = cookiesize;
291 change = 1;
292 }
293 if (lmv->max_def_cookiesize < def_cookiesize) {
294 lmv->max_def_cookiesize = def_cookiesize;
295 change = 1;
296 }
297 if (change == 0)
298 return 0;
299
300 if (lmv->connected == 0)
301 return 0;
302
303 for (i = 0; i < lmv->desc.ld_tgt_count; i++) {
304 if (lmv->tgts[i] == NULL ||
305 lmv->tgts[i]->ltd_exp == NULL ||
306 lmv->tgts[i]->ltd_active == 0) {
307 CWARN("%s: NULL export for %d\n", obd->obd_name, i);
308 continue;
309 }
310
311 rc = md_init_ea_size(lmv->tgts[i]->ltd_exp, easize, def_easize,
312 cookiesize, def_cookiesize);
313 if (rc) {
314 CERROR("%s: obd_init_ea_size() failed on MDT target %d: rc = %d.\n",
315 obd->obd_name, i, rc);
316 break;
317 }
318 }
319 return rc;
320}
321
322#define MAX_STRING_SIZE 128
323
324static int lmv_connect_mdc(struct obd_device *obd, struct lmv_tgt_desc *tgt)
325{
326 struct lmv_obd *lmv = &obd->u.lmv;
327 struct obd_uuid *cluuid = &lmv->cluuid;
328 struct obd_uuid lmv_mdc_uuid = { "LMV_MDC_UUID" };
329 struct obd_device *mdc_obd;
330 struct obd_export *mdc_exp;
331 struct lu_fld_target target;
332 int rc;
333
334 mdc_obd = class_find_client_obd(&tgt->ltd_uuid, LUSTRE_MDC_NAME,
335 &obd->obd_uuid);
336 if (!mdc_obd) {
337 CERROR("target %s not attached\n", tgt->ltd_uuid.uuid);
338 return -EINVAL;
339 }
340
341 CDEBUG(D_CONFIG, "connect to %s(%s) - %s, %s FOR %s\n",
342 mdc_obd->obd_name, mdc_obd->obd_uuid.uuid,
343 tgt->ltd_uuid.uuid, obd->obd_uuid.uuid,
344 cluuid->uuid);
345
346 if (!mdc_obd->obd_set_up) {
347 CERROR("target %s is not set up\n", tgt->ltd_uuid.uuid);
348 return -EINVAL;
349 }
350
351 rc = obd_connect(NULL, &mdc_exp, mdc_obd, &lmv_mdc_uuid,
352 &lmv->conn_data, NULL);
353 if (rc) {
354 CERROR("target %s connect error %d\n", tgt->ltd_uuid.uuid, rc);
355 return rc;
356 }
357
358
359
360
361 rc = obd_fid_init(mdc_obd, mdc_exp, LUSTRE_SEQ_METADATA);
362 if (rc)
363 return rc;
364
365 target.ft_srv = NULL;
366 target.ft_exp = mdc_exp;
367 target.ft_idx = tgt->ltd_idx;
368
369 fld_client_add_target(&lmv->lmv_fld, &target);
370
371 rc = obd_register_observer(mdc_obd, obd);
372 if (rc) {
373 obd_disconnect(mdc_exp);
374 CERROR("target %s register_observer error %d\n",
375 tgt->ltd_uuid.uuid, rc);
376 return rc;
377 }
378
379 if (obd->obd_observer) {
380
381
382
383 rc = obd_notify(obd->obd_observer, mdc_exp->exp_obd,
384 OBD_NOTIFY_ACTIVE,
385 (void *)(tgt - lmv->tgts[0]));
386 if (rc) {
387 obd_disconnect(mdc_exp);
388 return rc;
389 }
390 }
391
392 tgt->ltd_active = 1;
393 tgt->ltd_exp = mdc_exp;
394 lmv->desc.ld_active_tgt_count++;
395
396 md_init_ea_size(tgt->ltd_exp, lmv->max_easize, lmv->max_def_easize,
397 lmv->max_cookiesize, lmv->max_def_cookiesize);
398
399 CDEBUG(D_CONFIG, "Connected to %s(%s) successfully (%d)\n",
400 mdc_obd->obd_name, mdc_obd->obd_uuid.uuid,
401 atomic_read(&obd->obd_refcount));
402
403 if (lmv->lmv_tgts_kobj)
404
405 rc = sysfs_create_link(lmv->lmv_tgts_kobj, &mdc_obd->obd_kobj,
406 mdc_obd->obd_name);
407 return 0;
408}
409
410static void lmv_del_target(struct lmv_obd *lmv, int index)
411{
412 if (lmv->tgts[index] == NULL)
413 return;
414
415 kfree(lmv->tgts[index]);
416 lmv->tgts[index] = NULL;
417 return;
418}
419
420static int lmv_add_target(struct obd_device *obd, struct obd_uuid *uuidp,
421 __u32 index, int gen)
422{
423 struct lmv_obd *lmv = &obd->u.lmv;
424 struct lmv_tgt_desc *tgt;
425 int rc = 0;
426
427 CDEBUG(D_CONFIG, "Target uuid: %s. index %d\n", uuidp->uuid, index);
428
429 lmv_init_lock(lmv);
430
431 if (lmv->desc.ld_tgt_count == 0) {
432 struct obd_device *mdc_obd;
433
434 mdc_obd = class_find_client_obd(uuidp, LUSTRE_MDC_NAME,
435 &obd->obd_uuid);
436 if (!mdc_obd) {
437 lmv_init_unlock(lmv);
438 CERROR("%s: Target %s not attached: rc = %d\n",
439 obd->obd_name, uuidp->uuid, -EINVAL);
440 return -EINVAL;
441 }
442 }
443
444 if ((index < lmv->tgts_size) && (lmv->tgts[index] != NULL)) {
445 tgt = lmv->tgts[index];
446 CERROR("%s: UUID %s already assigned at LOV target index %d: rc = %d\n",
447 obd->obd_name,
448 obd_uuid2str(&tgt->ltd_uuid), index, -EEXIST);
449 lmv_init_unlock(lmv);
450 return -EEXIST;
451 }
452
453 if (index >= lmv->tgts_size) {
454
455 struct lmv_tgt_desc **newtgts, **old = NULL;
456 __u32 newsize = 1;
457 __u32 oldsize = 0;
458
459 while (newsize < index + 1)
460 newsize <<= 1;
461 newtgts = kcalloc(newsize, sizeof(*newtgts), GFP_NOFS);
462 if (newtgts == NULL) {
463 lmv_init_unlock(lmv);
464 return -ENOMEM;
465 }
466
467 if (lmv->tgts_size) {
468 memcpy(newtgts, lmv->tgts,
469 sizeof(*newtgts) * lmv->tgts_size);
470 old = lmv->tgts;
471 oldsize = lmv->tgts_size;
472 }
473
474 lmv->tgts = newtgts;
475 lmv->tgts_size = newsize;
476 smp_rmb();
477 kfree(old);
478
479 CDEBUG(D_CONFIG, "tgts: %p size: %d\n", lmv->tgts,
480 lmv->tgts_size);
481 }
482
483 tgt = kzalloc(sizeof(*tgt), GFP_NOFS);
484 if (!tgt) {
485 lmv_init_unlock(lmv);
486 return -ENOMEM;
487 }
488
489 mutex_init(&tgt->ltd_fid_mutex);
490 tgt->ltd_idx = index;
491 tgt->ltd_uuid = *uuidp;
492 tgt->ltd_active = 0;
493 lmv->tgts[index] = tgt;
494 if (index >= lmv->desc.ld_tgt_count)
495 lmv->desc.ld_tgt_count = index + 1;
496
497 if (lmv->connected) {
498 rc = lmv_connect_mdc(obd, tgt);
499 if (rc) {
500 spin_lock(&lmv->lmv_lock);
501 lmv->desc.ld_tgt_count--;
502 memset(tgt, 0, sizeof(*tgt));
503 spin_unlock(&lmv->lmv_lock);
504 } else {
505 int easize = sizeof(struct lmv_stripe_md) +
506 lmv->desc.ld_tgt_count * sizeof(struct lu_fid);
507 lmv_init_ea_size(obd->obd_self_export, easize, 0, 0, 0);
508 }
509 }
510
511 lmv_init_unlock(lmv);
512 return rc;
513}
514
515int lmv_check_connect(struct obd_device *obd)
516{
517 struct lmv_obd *lmv = &obd->u.lmv;
518 struct lmv_tgt_desc *tgt;
519 int i;
520 int rc;
521 int easize;
522
523 if (lmv->connected)
524 return 0;
525
526 lmv_init_lock(lmv);
527 if (lmv->connected) {
528 lmv_init_unlock(lmv);
529 return 0;
530 }
531
532 if (lmv->desc.ld_tgt_count == 0) {
533 lmv_init_unlock(lmv);
534 CERROR("%s: no targets configured.\n", obd->obd_name);
535 return -EINVAL;
536 }
537
538 CDEBUG(D_CONFIG, "Time to connect %s to %s\n",
539 lmv->cluuid.uuid, obd->obd_name);
540
541 LASSERT(lmv->tgts != NULL);
542
543 for (i = 0; i < lmv->desc.ld_tgt_count; i++) {
544 tgt = lmv->tgts[i];
545 if (tgt == NULL)
546 continue;
547 rc = lmv_connect_mdc(obd, tgt);
548 if (rc)
549 goto out_disc;
550 }
551
552 lmv_set_timeouts(obd);
553 class_export_put(lmv->exp);
554 lmv->connected = 1;
555 easize = lmv_get_easize(lmv);
556 lmv_init_ea_size(obd->obd_self_export, easize, 0, 0, 0);
557 lmv_init_unlock(lmv);
558 return 0;
559
560 out_disc:
561 while (i-- > 0) {
562 int rc2;
563 tgt = lmv->tgts[i];
564 if (tgt == NULL)
565 continue;
566 tgt->ltd_active = 0;
567 if (tgt->ltd_exp) {
568 --lmv->desc.ld_active_tgt_count;
569 rc2 = obd_disconnect(tgt->ltd_exp);
570 if (rc2) {
571 CERROR("LMV target %s disconnect on MDC idx %d: error %d\n",
572 tgt->ltd_uuid.uuid, i, rc2);
573 }
574 }
575 }
576 class_disconnect(lmv->exp);
577 lmv_init_unlock(lmv);
578 return rc;
579}
580
581static int lmv_disconnect_mdc(struct obd_device *obd, struct lmv_tgt_desc *tgt)
582{
583 struct lmv_obd *lmv = &obd->u.lmv;
584 struct obd_device *mdc_obd;
585 int rc;
586
587 LASSERT(tgt != NULL);
588 LASSERT(obd != NULL);
589
590 mdc_obd = class_exp2obd(tgt->ltd_exp);
591
592 if (mdc_obd) {
593 mdc_obd->obd_force = obd->obd_force;
594 mdc_obd->obd_fail = obd->obd_fail;
595 mdc_obd->obd_no_recov = obd->obd_no_recov;
596 }
597
598 if (lmv->lmv_tgts_kobj)
599 sysfs_remove_link(lmv->lmv_tgts_kobj,
600 mdc_obd->obd_name);
601
602 rc = obd_fid_fini(tgt->ltd_exp->exp_obd);
603 if (rc)
604 CERROR("Can't finalize fids factory\n");
605
606 CDEBUG(D_INFO, "Disconnected from %s(%s) successfully\n",
607 tgt->ltd_exp->exp_obd->obd_name,
608 tgt->ltd_exp->exp_obd->obd_uuid.uuid);
609
610 obd_register_observer(tgt->ltd_exp->exp_obd, NULL);
611 rc = obd_disconnect(tgt->ltd_exp);
612 if (rc) {
613 if (tgt->ltd_active) {
614 CERROR("Target %s disconnect error %d\n",
615 tgt->ltd_uuid.uuid, rc);
616 }
617 }
618
619 lmv_activate_target(lmv, tgt, 0);
620 tgt->ltd_exp = NULL;
621 return 0;
622}
623
624static int lmv_disconnect(struct obd_export *exp)
625{
626 struct obd_device *obd = class_exp2obd(exp);
627 struct lmv_obd *lmv = &obd->u.lmv;
628 int rc;
629 int i;
630
631 if (!lmv->tgts)
632 goto out_local;
633
634
635
636
637 lmv->refcount--;
638 if (lmv->refcount != 0)
639 goto out_local;
640
641 for (i = 0; i < lmv->desc.ld_tgt_count; i++) {
642 if (lmv->tgts[i] == NULL || lmv->tgts[i]->ltd_exp == NULL)
643 continue;
644
645 lmv_disconnect_mdc(obd, lmv->tgts[i]);
646 }
647
648 if (lmv->lmv_tgts_kobj)
649 kobject_put(lmv->lmv_tgts_kobj);
650
651out_local:
652
653
654
655
656 if (!lmv->connected)
657 class_export_put(exp);
658 rc = class_disconnect(exp);
659 if (lmv->refcount == 0)
660 lmv->connected = 0;
661 return rc;
662}
663
664static int lmv_fid2path(struct obd_export *exp, int len, void *karg, void *uarg)
665{
666 struct obd_device *obddev = class_exp2obd(exp);
667 struct lmv_obd *lmv = &obddev->u.lmv;
668 struct getinfo_fid2path *gf;
669 struct lmv_tgt_desc *tgt;
670 struct getinfo_fid2path *remote_gf = NULL;
671 int remote_gf_size = 0;
672 int rc;
673
674 gf = (struct getinfo_fid2path *)karg;
675 tgt = lmv_find_target(lmv, &gf->gf_fid);
676 if (IS_ERR(tgt))
677 return PTR_ERR(tgt);
678
679repeat_fid2path:
680 rc = obd_iocontrol(OBD_IOC_FID2PATH, tgt->ltd_exp, len, gf, uarg);
681 if (rc != 0 && rc != -EREMOTE)
682 goto out_fid2path;
683
684
685
686 if (remote_gf != NULL) {
687 struct getinfo_fid2path *ori_gf;
688 char *ptr;
689
690 ori_gf = (struct getinfo_fid2path *)karg;
691 if (strlen(ori_gf->gf_path) +
692 strlen(gf->gf_path) > ori_gf->gf_pathlen) {
693 rc = -EOVERFLOW;
694 goto out_fid2path;
695 }
696
697 ptr = ori_gf->gf_path;
698
699 memmove(ptr + strlen(gf->gf_path) + 1, ptr,
700 strlen(ori_gf->gf_path));
701
702 strncpy(ptr, gf->gf_path, strlen(gf->gf_path));
703 ptr += strlen(gf->gf_path);
704 *ptr = '/';
705 }
706
707 CDEBUG(D_INFO, "%s: get path %s "DFID" rec: %llu ln: %u\n",
708 tgt->ltd_exp->exp_obd->obd_name,
709 gf->gf_path, PFID(&gf->gf_fid), gf->gf_recno,
710 gf->gf_linkno);
711
712 if (rc == 0)
713 goto out_fid2path;
714
715
716 if (remote_gf == NULL) {
717 remote_gf_size = sizeof(*remote_gf) + PATH_MAX;
718 remote_gf = kzalloc(remote_gf_size, GFP_NOFS);
719 if (!remote_gf) {
720 rc = -ENOMEM;
721 goto out_fid2path;
722 }
723 remote_gf->gf_pathlen = PATH_MAX;
724 }
725
726 if (!fid_is_sane(&gf->gf_fid)) {
727 CERROR("%s: invalid FID "DFID": rc = %d\n",
728 tgt->ltd_exp->exp_obd->obd_name,
729 PFID(&gf->gf_fid), -EINVAL);
730 rc = -EINVAL;
731 goto out_fid2path;
732 }
733
734 tgt = lmv_find_target(lmv, &gf->gf_fid);
735 if (IS_ERR(tgt)) {
736 rc = -EINVAL;
737 goto out_fid2path;
738 }
739
740 remote_gf->gf_fid = gf->gf_fid;
741 remote_gf->gf_recno = -1;
742 remote_gf->gf_linkno = -1;
743 memset(remote_gf->gf_path, 0, remote_gf->gf_pathlen);
744 gf = remote_gf;
745 goto repeat_fid2path;
746
747out_fid2path:
748 kfree(remote_gf);
749 return rc;
750}
751
752static int lmv_hsm_req_count(struct lmv_obd *lmv,
753 const struct hsm_user_request *hur,
754 const struct lmv_tgt_desc *tgt_mds)
755{
756 int i, nr = 0;
757 struct lmv_tgt_desc *curr_tgt;
758
759
760 for (i = 0; i < hur->hur_request.hr_itemcount; i++) {
761 curr_tgt = lmv_find_target(lmv, &hur->hur_user_item[i].hui_fid);
762 if (obd_uuid_equals(&curr_tgt->ltd_uuid, &tgt_mds->ltd_uuid))
763 nr++;
764 }
765 return nr;
766}
767
768static void lmv_hsm_req_build(struct lmv_obd *lmv,
769 struct hsm_user_request *hur_in,
770 const struct lmv_tgt_desc *tgt_mds,
771 struct hsm_user_request *hur_out)
772{
773 int i, nr_out;
774 struct lmv_tgt_desc *curr_tgt;
775
776
777 hur_out->hur_request = hur_in->hur_request;
778 nr_out = 0;
779 for (i = 0; i < hur_in->hur_request.hr_itemcount; i++) {
780 curr_tgt = lmv_find_target(lmv,
781 &hur_in->hur_user_item[i].hui_fid);
782 if (obd_uuid_equals(&curr_tgt->ltd_uuid, &tgt_mds->ltd_uuid)) {
783 hur_out->hur_user_item[nr_out] =
784 hur_in->hur_user_item[i];
785 nr_out++;
786 }
787 }
788 hur_out->hur_request.hr_itemcount = nr_out;
789 memcpy(hur_data(hur_out), hur_data(hur_in),
790 hur_in->hur_request.hr_data_len);
791}
792
793static int lmv_hsm_ct_unregister(struct lmv_obd *lmv, unsigned int cmd, int len,
794 struct lustre_kernelcomm *lk, void *uarg)
795{
796 int i, rc = 0;
797
798
799 for (i = 0; i < lmv->desc.ld_tgt_count; i++) {
800
801
802 obd_iocontrol(cmd, lmv->tgts[i]->ltd_exp, len, lk, uarg);
803 }
804
805
806
807
808
809 rc = libcfs_kkuc_group_rem(lk->lk_uid, lk->lk_group);
810 return rc;
811}
812
813static int lmv_hsm_ct_register(struct lmv_obd *lmv, unsigned int cmd, int len,
814 struct lustre_kernelcomm *lk, void *uarg)
815{
816 struct file *filp;
817 int i, j, err;
818 int rc = 0;
819 bool any_set = false;
820
821
822
823
824 for (i = 0; i < lmv->desc.ld_tgt_count; i++) {
825 err = obd_iocontrol(cmd, lmv->tgts[i]->ltd_exp,
826 len, lk, uarg);
827 if (err) {
828 if (lmv->tgts[i]->ltd_active) {
829
830 CERROR("error: iocontrol MDC %s on MDTidx %d cmd %x: err = %d\n",
831 lmv->tgts[i]->ltd_uuid.uuid,
832 i, cmd, err);
833 rc = err;
834 lk->lk_flags |= LK_FLG_STOP;
835
836 for (j = 0; j < i; j++)
837 obd_iocontrol(cmd,
838 lmv->tgts[j]->ltd_exp,
839 len, lk, uarg);
840 return rc;
841 }
842
843
844
845 } else {
846 any_set = true;
847 }
848 }
849
850 if (!any_set)
851
852 return -ENOTCONN;
853
854
855 filp = fget(lk->lk_wfd);
856 if (filp == NULL) {
857 return -EBADF;
858 }
859 rc = libcfs_kkuc_group_add(filp, lk->lk_uid, lk->lk_group, lk->lk_data);
860 if (rc != 0 && filp != NULL)
861 fput(filp);
862 return rc;
863}
864
865
866
867
868static int lmv_iocontrol(unsigned int cmd, struct obd_export *exp,
869 int len, void *karg, void *uarg)
870{
871 struct obd_device *obddev = class_exp2obd(exp);
872 struct lmv_obd *lmv = &obddev->u.lmv;
873 int i = 0;
874 int rc = 0;
875 int set = 0;
876 int count = lmv->desc.ld_tgt_count;
877
878 if (count == 0)
879 return -ENOTTY;
880
881 switch (cmd) {
882 case IOC_OBD_STATFS: {
883 struct obd_ioctl_data *data = karg;
884 struct obd_device *mdc_obd;
885 struct obd_statfs stat_buf = {0};
886 __u32 index;
887
888 memcpy(&index, data->ioc_inlbuf2, sizeof(__u32));
889 if (index >= count)
890 return -ENODEV;
891
892 if (lmv->tgts[index] == NULL ||
893 lmv->tgts[index]->ltd_active == 0)
894 return -ENODATA;
895
896 mdc_obd = class_exp2obd(lmv->tgts[index]->ltd_exp);
897 if (!mdc_obd)
898 return -EINVAL;
899
900
901 if (copy_to_user(data->ioc_pbuf2, obd2cli_tgt(mdc_obd),
902 min((int) data->ioc_plen2,
903 (int) sizeof(struct obd_uuid))))
904 return -EFAULT;
905
906 rc = obd_statfs(NULL, lmv->tgts[index]->ltd_exp, &stat_buf,
907 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
908 0);
909 if (rc)
910 return rc;
911 if (copy_to_user(data->ioc_pbuf1, &stat_buf,
912 min((int) data->ioc_plen1,
913 (int) sizeof(stat_buf))))
914 return -EFAULT;
915 break;
916 }
917 case OBD_IOC_QUOTACTL: {
918 struct if_quotactl *qctl = karg;
919 struct lmv_tgt_desc *tgt = NULL;
920 struct obd_quotactl *oqctl;
921
922 if (qctl->qc_valid == QC_MDTIDX) {
923 if (qctl->qc_idx < 0 || count <= qctl->qc_idx)
924 return -EINVAL;
925
926 tgt = lmv->tgts[qctl->qc_idx];
927 if (tgt == NULL || tgt->ltd_exp == NULL)
928 return -EINVAL;
929 } else if (qctl->qc_valid == QC_UUID) {
930 for (i = 0; i < count; i++) {
931 tgt = lmv->tgts[i];
932 if (tgt == NULL)
933 continue;
934 if (!obd_uuid_equals(&tgt->ltd_uuid,
935 &qctl->obd_uuid))
936 continue;
937
938 if (tgt->ltd_exp == NULL)
939 return -EINVAL;
940
941 break;
942 }
943 } else {
944 return -EINVAL;
945 }
946
947 if (i >= count)
948 return -EAGAIN;
949
950 LASSERT(tgt && tgt->ltd_exp);
951 oqctl = kzalloc(sizeof(*oqctl), GFP_NOFS);
952 if (!oqctl)
953 return -ENOMEM;
954
955 QCTL_COPY(oqctl, qctl);
956 rc = obd_quotactl(tgt->ltd_exp, oqctl);
957 if (rc == 0) {
958 QCTL_COPY(qctl, oqctl);
959 qctl->qc_valid = QC_MDTIDX;
960 qctl->obd_uuid = tgt->ltd_uuid;
961 }
962 kfree(oqctl);
963 break;
964 }
965 case OBD_IOC_CHANGELOG_SEND:
966 case OBD_IOC_CHANGELOG_CLEAR: {
967 struct ioc_changelog *icc = karg;
968
969 if (icc->icc_mdtindex >= count)
970 return -ENODEV;
971
972 if (lmv->tgts[icc->icc_mdtindex] == NULL ||
973 lmv->tgts[icc->icc_mdtindex]->ltd_exp == NULL ||
974 lmv->tgts[icc->icc_mdtindex]->ltd_active == 0)
975 return -ENODEV;
976 rc = obd_iocontrol(cmd, lmv->tgts[icc->icc_mdtindex]->ltd_exp,
977 sizeof(*icc), icc, NULL);
978 break;
979 }
980 case LL_IOC_GET_CONNECT_FLAGS: {
981 if (lmv->tgts[0] == NULL)
982 return -ENODATA;
983 rc = obd_iocontrol(cmd, lmv->tgts[0]->ltd_exp, len, karg, uarg);
984 break;
985 }
986 case OBD_IOC_FID2PATH: {
987 rc = lmv_fid2path(exp, len, karg, uarg);
988 break;
989 }
990 case LL_IOC_HSM_STATE_GET:
991 case LL_IOC_HSM_STATE_SET:
992 case LL_IOC_HSM_ACTION: {
993 struct md_op_data *op_data = karg;
994 struct lmv_tgt_desc *tgt;
995
996 tgt = lmv_find_target(lmv, &op_data->op_fid1);
997 if (IS_ERR(tgt))
998 return PTR_ERR(tgt);
999
1000 if (tgt->ltd_exp == NULL)
1001 return -EINVAL;
1002
1003 rc = obd_iocontrol(cmd, tgt->ltd_exp, len, karg, uarg);
1004 break;
1005 }
1006 case LL_IOC_HSM_PROGRESS: {
1007 const struct hsm_progress_kernel *hpk = karg;
1008 struct lmv_tgt_desc *tgt;
1009
1010 tgt = lmv_find_target(lmv, &hpk->hpk_fid);
1011 if (IS_ERR(tgt))
1012 return PTR_ERR(tgt);
1013 rc = obd_iocontrol(cmd, tgt->ltd_exp, len, karg, uarg);
1014 break;
1015 }
1016 case LL_IOC_HSM_REQUEST: {
1017 struct hsm_user_request *hur = karg;
1018 struct lmv_tgt_desc *tgt;
1019 unsigned int reqcount = hur->hur_request.hr_itemcount;
1020
1021 if (reqcount == 0)
1022 return 0;
1023
1024
1025
1026
1027 if (reqcount == 1 || count == 1) {
1028 tgt = lmv_find_target(lmv,
1029 &hur->hur_user_item[0].hui_fid);
1030 if (IS_ERR(tgt))
1031 return PTR_ERR(tgt);
1032 rc = obd_iocontrol(cmd, tgt->ltd_exp, len, karg, uarg);
1033 } else {
1034
1035 for (i = 0; i < count; i++) {
1036 unsigned int nr, reqlen;
1037 int rc1;
1038 struct hsm_user_request *req;
1039
1040 nr = lmv_hsm_req_count(lmv, hur, lmv->tgts[i]);
1041 if (nr == 0)
1042 continue;
1043
1044
1045 reqlen = offsetof(typeof(*hur),
1046 hur_user_item[nr])
1047 + hur->hur_request.hr_data_len;
1048 req = libcfs_kvzalloc(reqlen, GFP_NOFS);
1049 if (req == NULL)
1050 return -ENOMEM;
1051
1052 lmv_hsm_req_build(lmv, hur, lmv->tgts[i], req);
1053
1054 rc1 = obd_iocontrol(cmd, lmv->tgts[i]->ltd_exp,
1055 reqlen, req, uarg);
1056 if (rc1 != 0 && rc == 0)
1057 rc = rc1;
1058 kvfree(req);
1059 }
1060 }
1061 break;
1062 }
1063 case LL_IOC_LOV_SWAP_LAYOUTS: {
1064 struct md_op_data *op_data = karg;
1065 struct lmv_tgt_desc *tgt1, *tgt2;
1066
1067 tgt1 = lmv_find_target(lmv, &op_data->op_fid1);
1068 if (IS_ERR(tgt1))
1069 return PTR_ERR(tgt1);
1070
1071 tgt2 = lmv_find_target(lmv, &op_data->op_fid2);
1072 if (IS_ERR(tgt2))
1073 return PTR_ERR(tgt2);
1074
1075 if ((tgt1->ltd_exp == NULL) || (tgt2->ltd_exp == NULL))
1076 return -EINVAL;
1077
1078
1079 if (tgt1->ltd_idx != tgt2->ltd_idx)
1080 return -EPERM;
1081
1082 rc = obd_iocontrol(cmd, tgt1->ltd_exp, len, karg, uarg);
1083 break;
1084 }
1085 case LL_IOC_HSM_CT_START: {
1086 struct lustre_kernelcomm *lk = karg;
1087 if (lk->lk_flags & LK_FLG_STOP)
1088 rc = lmv_hsm_ct_unregister(lmv, cmd, len, lk, uarg);
1089 else
1090 rc = lmv_hsm_ct_register(lmv, cmd, len, lk, uarg);
1091 break;
1092 }
1093 default:
1094 for (i = 0; i < count; i++) {
1095 struct obd_device *mdc_obd;
1096 int err;
1097
1098 if (lmv->tgts[i] == NULL ||
1099 lmv->tgts[i]->ltd_exp == NULL)
1100 continue;
1101
1102
1103 mdc_obd = class_exp2obd(lmv->tgts[i]->ltd_exp);
1104 mdc_obd->obd_force = obddev->obd_force;
1105 err = obd_iocontrol(cmd, lmv->tgts[i]->ltd_exp, len,
1106 karg, uarg);
1107 if (err == -ENODATA && cmd == OBD_IOC_POLL_QUOTACHECK) {
1108 return err;
1109 } else if (err) {
1110 if (lmv->tgts[i]->ltd_active) {
1111 CERROR("error: iocontrol MDC %s on MDTidx %d cmd %x: err = %d\n",
1112 lmv->tgts[i]->ltd_uuid.uuid,
1113 i, cmd, err);
1114 if (!rc)
1115 rc = err;
1116 }
1117 } else
1118 set = 1;
1119 }
1120 if (!set && !rc)
1121 rc = -EIO;
1122 }
1123 return rc;
1124}
1125
1126#if 0
1127static int lmv_all_chars_policy(int count, const char *name,
1128 int len)
1129{
1130 unsigned int c = 0;
1131
1132 while (len > 0)
1133 c += name[--len];
1134 c = c % count;
1135 return c;
1136}
1137
1138static int lmv_nid_policy(struct lmv_obd *lmv)
1139{
1140 struct obd_import *imp;
1141 __u32 id;
1142
1143
1144
1145
1146 imp = class_exp2cliimp(lmv->tgts[0].ltd_exp);
1147 id = imp->imp_connection->c_self ^ (imp->imp_connection->c_self >> 32);
1148 return id % lmv->desc.ld_tgt_count;
1149}
1150
1151static int lmv_choose_mds(struct lmv_obd *lmv, struct md_op_data *op_data,
1152 enum placement_policy placement)
1153{
1154 switch (placement) {
1155 case PLACEMENT_CHAR_POLICY:
1156 return lmv_all_chars_policy(lmv->desc.ld_tgt_count,
1157 op_data->op_name,
1158 op_data->op_namelen);
1159 case PLACEMENT_NID_POLICY:
1160 return lmv_nid_policy(lmv);
1161
1162 default:
1163 break;
1164 }
1165
1166 CERROR("Unsupported placement policy %x\n", placement);
1167 return -EINVAL;
1168}
1169#endif
1170
1171
1172
1173
1174static int lmv_placement_policy(struct obd_device *obd,
1175 struct md_op_data *op_data, u32 *mds)
1176{
1177 struct lmv_obd *lmv = &obd->u.lmv;
1178
1179 LASSERT(mds != NULL);
1180
1181 if (lmv->desc.ld_tgt_count == 1) {
1182 *mds = 0;
1183 return 0;
1184 }
1185
1186
1187
1188
1189
1190 if (op_data->op_cli_flags & CLI_SET_MEA) {
1191 struct lmv_user_md *lum;
1192
1193 lum = (struct lmv_user_md *)op_data->op_data;
1194 if (lum->lum_type == LMV_STRIPE_TYPE &&
1195 lum->lum_stripe_offset != -1) {
1196 if (lum->lum_stripe_offset >= lmv->desc.ld_tgt_count) {
1197 CERROR("%s: Stripe_offset %d > MDT count %d: rc = %d\n",
1198 obd->obd_name,
1199 lum->lum_stripe_offset,
1200 lmv->desc.ld_tgt_count, -ERANGE);
1201 return -ERANGE;
1202 }
1203 *mds = lum->lum_stripe_offset;
1204 return 0;
1205 }
1206 }
1207
1208
1209
1210 *mds = op_data->op_mds;
1211 return 0;
1212}
1213
1214int __lmv_fid_alloc(struct lmv_obd *lmv, struct lu_fid *fid, u32 mds)
1215{
1216 struct lmv_tgt_desc *tgt;
1217 int rc;
1218
1219 tgt = lmv_get_target(lmv, mds);
1220 if (IS_ERR(tgt))
1221 return PTR_ERR(tgt);
1222
1223
1224
1225
1226
1227 mutex_lock(&tgt->ltd_fid_mutex);
1228
1229 if (tgt->ltd_active == 0 || tgt->ltd_exp == NULL) {
1230 rc = -ENODEV;
1231 goto out;
1232 }
1233
1234
1235
1236
1237 rc = obd_fid_alloc(tgt->ltd_exp, fid, NULL);
1238 if (rc > 0) {
1239 LASSERT(fid_is_sane(fid));
1240 rc = 0;
1241 }
1242
1243out:
1244 mutex_unlock(&tgt->ltd_fid_mutex);
1245 return rc;
1246}
1247
1248int lmv_fid_alloc(struct obd_export *exp, struct lu_fid *fid,
1249 struct md_op_data *op_data)
1250{
1251 struct obd_device *obd = class_exp2obd(exp);
1252 struct lmv_obd *lmv = &obd->u.lmv;
1253 u32 mds = 0;
1254 int rc;
1255
1256 LASSERT(op_data != NULL);
1257 LASSERT(fid != NULL);
1258
1259 rc = lmv_placement_policy(obd, op_data, &mds);
1260 if (rc) {
1261 CERROR("Can't get target for allocating fid, rc %d\n",
1262 rc);
1263 return rc;
1264 }
1265
1266 rc = __lmv_fid_alloc(lmv, fid, mds);
1267 if (rc) {
1268 CERROR("Can't alloc new fid, rc %d\n", rc);
1269 return rc;
1270 }
1271
1272 return rc;
1273}
1274
1275static int lmv_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
1276{
1277 struct lmv_obd *lmv = &obd->u.lmv;
1278 struct lprocfs_static_vars lvars = { NULL };
1279 struct lmv_desc *desc;
1280 int rc;
1281
1282 if (LUSTRE_CFG_BUFLEN(lcfg, 1) < 1) {
1283 CERROR("LMV setup requires a descriptor\n");
1284 return -EINVAL;
1285 }
1286
1287 desc = (struct lmv_desc *)lustre_cfg_buf(lcfg, 1);
1288 if (sizeof(*desc) > LUSTRE_CFG_BUFLEN(lcfg, 1)) {
1289 CERROR("Lmv descriptor size wrong: %d > %d\n",
1290 (int)sizeof(*desc), LUSTRE_CFG_BUFLEN(lcfg, 1));
1291 return -EINVAL;
1292 }
1293
1294 lmv->tgts = kcalloc(32, sizeof(*lmv->tgts), GFP_NOFS);
1295 if (lmv->tgts == NULL)
1296 return -ENOMEM;
1297 lmv->tgts_size = 32;
1298
1299 obd_str2uuid(&lmv->desc.ld_uuid, desc->ld_uuid.uuid);
1300 lmv->desc.ld_tgt_count = 0;
1301 lmv->desc.ld_active_tgt_count = 0;
1302 lmv->max_cookiesize = 0;
1303 lmv->max_def_easize = 0;
1304 lmv->max_easize = 0;
1305 lmv->lmv_placement = PLACEMENT_CHAR_POLICY;
1306
1307 spin_lock_init(&lmv->lmv_lock);
1308 mutex_init(&lmv->init_mutex);
1309
1310 lprocfs_lmv_init_vars(&lvars);
1311
1312 lprocfs_obd_setup(obd, lvars.obd_vars, lvars.sysfs_vars);
1313 rc = ldebugfs_seq_create(obd->obd_debugfs_entry, "target_obd",
1314 0444, &lmv_proc_target_fops, obd);
1315 if (rc)
1316 CWARN("%s: error adding LMV target_obd file: rc = %d\n",
1317 obd->obd_name, rc);
1318 rc = fld_client_init(&lmv->lmv_fld, obd->obd_name,
1319 LUSTRE_CLI_FLD_HASH_DHT);
1320 if (rc) {
1321 CERROR("Can't init FLD, err %d\n", rc);
1322 goto out;
1323 }
1324
1325 return 0;
1326
1327out:
1328 return rc;
1329}
1330
1331static int lmv_cleanup(struct obd_device *obd)
1332{
1333 struct lmv_obd *lmv = &obd->u.lmv;
1334
1335 fld_client_fini(&lmv->lmv_fld);
1336 if (lmv->tgts != NULL) {
1337 int i;
1338 for (i = 0; i < lmv->desc.ld_tgt_count; i++) {
1339 if (lmv->tgts[i] == NULL)
1340 continue;
1341 lmv_del_target(lmv, i);
1342 }
1343 kfree(lmv->tgts);
1344 lmv->tgts_size = 0;
1345 }
1346 return 0;
1347}
1348
1349static int lmv_process_config(struct obd_device *obd, u32 len, void *buf)
1350{
1351 struct lustre_cfg *lcfg = buf;
1352 struct obd_uuid obd_uuid;
1353 int gen;
1354 __u32 index;
1355 int rc;
1356
1357 switch (lcfg->lcfg_command) {
1358 case LCFG_ADD_MDC:
1359
1360
1361 if (LUSTRE_CFG_BUFLEN(lcfg, 1) > sizeof(obd_uuid.uuid)) {
1362 rc = -EINVAL;
1363 goto out;
1364 }
1365
1366 obd_str2uuid(&obd_uuid, lustre_cfg_buf(lcfg, 1));
1367
1368 if (sscanf(lustre_cfg_buf(lcfg, 2), "%d", &index) != 1) {
1369 rc = -EINVAL;
1370 goto out;
1371 }
1372 if (sscanf(lustre_cfg_buf(lcfg, 3), "%d", &gen) != 1) {
1373 rc = -EINVAL;
1374 goto out;
1375 }
1376 rc = lmv_add_target(obd, &obd_uuid, index, gen);
1377 goto out;
1378 default:
1379 CERROR("Unknown command: %d\n", lcfg->lcfg_command);
1380 rc = -EINVAL;
1381 goto out;
1382 }
1383out:
1384 return rc;
1385}
1386
1387static int lmv_statfs(const struct lu_env *env, struct obd_export *exp,
1388 struct obd_statfs *osfs, __u64 max_age, __u32 flags)
1389{
1390 struct obd_device *obd = class_exp2obd(exp);
1391 struct lmv_obd *lmv = &obd->u.lmv;
1392 struct obd_statfs *temp;
1393 int rc = 0;
1394 int i;
1395
1396 rc = lmv_check_connect(obd);
1397 if (rc)
1398 return rc;
1399
1400 temp = kzalloc(sizeof(*temp), GFP_NOFS);
1401 if (!temp)
1402 return -ENOMEM;
1403
1404 for (i = 0; i < lmv->desc.ld_tgt_count; i++) {
1405 if (lmv->tgts[i] == NULL || lmv->tgts[i]->ltd_exp == NULL)
1406 continue;
1407
1408 rc = obd_statfs(env, lmv->tgts[i]->ltd_exp, temp,
1409 max_age, flags);
1410 if (rc) {
1411 CERROR("can't stat MDS #%d (%s), error %d\n", i,
1412 lmv->tgts[i]->ltd_exp->exp_obd->obd_name,
1413 rc);
1414 goto out_free_temp;
1415 }
1416
1417 if (i == 0) {
1418 *osfs = *temp;
1419
1420
1421
1422
1423
1424
1425 if (flags & OBD_STATFS_FOR_MDT0)
1426 goto out_free_temp;
1427 } else {
1428 osfs->os_bavail += temp->os_bavail;
1429 osfs->os_blocks += temp->os_blocks;
1430 osfs->os_ffree += temp->os_ffree;
1431 osfs->os_files += temp->os_files;
1432 }
1433 }
1434
1435out_free_temp:
1436 kfree(temp);
1437 return rc;
1438}
1439
1440static int lmv_getstatus(struct obd_export *exp,
1441 struct lu_fid *fid,
1442 struct obd_capa **pc)
1443{
1444 struct obd_device *obd = exp->exp_obd;
1445 struct lmv_obd *lmv = &obd->u.lmv;
1446 int rc;
1447
1448 rc = lmv_check_connect(obd);
1449 if (rc)
1450 return rc;
1451
1452 rc = md_getstatus(lmv->tgts[0]->ltd_exp, fid, pc);
1453 return rc;
1454}
1455
1456static int lmv_getxattr(struct obd_export *exp, const struct lu_fid *fid,
1457 struct obd_capa *oc, u64 valid, const char *name,
1458 const char *input, int input_size, int output_size,
1459 int flags, struct ptlrpc_request **request)
1460{
1461 struct obd_device *obd = exp->exp_obd;
1462 struct lmv_obd *lmv = &obd->u.lmv;
1463 struct lmv_tgt_desc *tgt;
1464 int rc;
1465
1466 rc = lmv_check_connect(obd);
1467 if (rc)
1468 return rc;
1469
1470 tgt = lmv_find_target(lmv, fid);
1471 if (IS_ERR(tgt))
1472 return PTR_ERR(tgt);
1473
1474 rc = md_getxattr(tgt->ltd_exp, fid, oc, valid, name, input,
1475 input_size, output_size, flags, request);
1476
1477 return rc;
1478}
1479
1480static int lmv_setxattr(struct obd_export *exp, const struct lu_fid *fid,
1481 struct obd_capa *oc, u64 valid, const char *name,
1482 const char *input, int input_size, int output_size,
1483 int flags, __u32 suppgid,
1484 struct ptlrpc_request **request)
1485{
1486 struct obd_device *obd = exp->exp_obd;
1487 struct lmv_obd *lmv = &obd->u.lmv;
1488 struct lmv_tgt_desc *tgt;
1489 int rc;
1490
1491 rc = lmv_check_connect(obd);
1492 if (rc)
1493 return rc;
1494
1495 tgt = lmv_find_target(lmv, fid);
1496 if (IS_ERR(tgt))
1497 return PTR_ERR(tgt);
1498
1499 rc = md_setxattr(tgt->ltd_exp, fid, oc, valid, name, input,
1500 input_size, output_size, flags, suppgid,
1501 request);
1502
1503 return rc;
1504}
1505
1506static int lmv_getattr(struct obd_export *exp, struct md_op_data *op_data,
1507 struct ptlrpc_request **request)
1508{
1509 struct obd_device *obd = exp->exp_obd;
1510 struct lmv_obd *lmv = &obd->u.lmv;
1511 struct lmv_tgt_desc *tgt;
1512 int rc;
1513
1514 rc = lmv_check_connect(obd);
1515 if (rc)
1516 return rc;
1517
1518 tgt = lmv_find_target(lmv, &op_data->op_fid1);
1519 if (IS_ERR(tgt))
1520 return PTR_ERR(tgt);
1521
1522 if (op_data->op_flags & MF_GET_MDT_IDX) {
1523 op_data->op_mds = tgt->ltd_idx;
1524 return 0;
1525 }
1526
1527 rc = md_getattr(tgt->ltd_exp, op_data, request);
1528
1529 return rc;
1530}
1531
1532static int lmv_null_inode(struct obd_export *exp, const struct lu_fid *fid)
1533{
1534 struct obd_device *obd = exp->exp_obd;
1535 struct lmv_obd *lmv = &obd->u.lmv;
1536 int i;
1537 int rc;
1538
1539 rc = lmv_check_connect(obd);
1540 if (rc)
1541 return rc;
1542
1543 CDEBUG(D_INODE, "CBDATA for "DFID"\n", PFID(fid));
1544
1545
1546
1547
1548
1549
1550 for (i = 0; i < lmv->desc.ld_tgt_count; i++) {
1551 if (lmv->tgts[i] == NULL || lmv->tgts[i]->ltd_exp == NULL)
1552 continue;
1553 md_null_inode(lmv->tgts[i]->ltd_exp, fid);
1554 }
1555
1556 return 0;
1557}
1558
1559static int lmv_find_cbdata(struct obd_export *exp, const struct lu_fid *fid,
1560 ldlm_iterator_t it, void *data)
1561{
1562 struct obd_device *obd = exp->exp_obd;
1563 struct lmv_obd *lmv = &obd->u.lmv;
1564 int i;
1565 int rc;
1566
1567 rc = lmv_check_connect(obd);
1568 if (rc)
1569 return rc;
1570
1571 CDEBUG(D_INODE, "CBDATA for "DFID"\n", PFID(fid));
1572
1573
1574
1575
1576
1577
1578 for (i = 0; i < lmv->desc.ld_tgt_count; i++) {
1579 if (lmv->tgts[i] == NULL || lmv->tgts[i]->ltd_exp == NULL)
1580 continue;
1581 rc = md_find_cbdata(lmv->tgts[i]->ltd_exp, fid, it, data);
1582 if (rc)
1583 return rc;
1584 }
1585
1586 return rc;
1587}
1588
1589
1590static int lmv_close(struct obd_export *exp, struct md_op_data *op_data,
1591 struct md_open_data *mod, struct ptlrpc_request **request)
1592{
1593 struct obd_device *obd = exp->exp_obd;
1594 struct lmv_obd *lmv = &obd->u.lmv;
1595 struct lmv_tgt_desc *tgt;
1596 int rc;
1597
1598 rc = lmv_check_connect(obd);
1599 if (rc)
1600 return rc;
1601
1602 tgt = lmv_find_target(lmv, &op_data->op_fid1);
1603 if (IS_ERR(tgt))
1604 return PTR_ERR(tgt);
1605
1606 CDEBUG(D_INODE, "CLOSE "DFID"\n", PFID(&op_data->op_fid1));
1607 rc = md_close(tgt->ltd_exp, op_data, mod, request);
1608 return rc;
1609}
1610
1611struct lmv_tgt_desc
1612*lmv_locate_mds(struct lmv_obd *lmv, struct md_op_data *op_data,
1613 struct lu_fid *fid)
1614{
1615 struct lmv_tgt_desc *tgt;
1616
1617 tgt = lmv_find_target(lmv, fid);
1618 if (IS_ERR(tgt))
1619 return tgt;
1620
1621 op_data->op_mds = tgt->ltd_idx;
1622
1623 return tgt;
1624}
1625
1626static int lmv_create(struct obd_export *exp, struct md_op_data *op_data,
1627 const void *data, int datalen, int mode, __u32 uid,
1628 __u32 gid, cfs_cap_t cap_effective, __u64 rdev,
1629 struct ptlrpc_request **request)
1630{
1631 struct obd_device *obd = exp->exp_obd;
1632 struct lmv_obd *lmv = &obd->u.lmv;
1633 struct lmv_tgt_desc *tgt;
1634 int rc;
1635
1636 rc = lmv_check_connect(obd);
1637 if (rc)
1638 return rc;
1639
1640 if (!lmv->desc.ld_active_tgt_count)
1641 return -EIO;
1642
1643 tgt = lmv_locate_mds(lmv, op_data, &op_data->op_fid1);
1644 if (IS_ERR(tgt))
1645 return PTR_ERR(tgt);
1646
1647 rc = lmv_fid_alloc(exp, &op_data->op_fid2, op_data);
1648 if (rc)
1649 return rc;
1650
1651 CDEBUG(D_INODE, "CREATE '%*s' on "DFID" -> mds #%x\n",
1652 op_data->op_namelen, op_data->op_name, PFID(&op_data->op_fid1),
1653 op_data->op_mds);
1654
1655 op_data->op_flags |= MF_MDC_CANCEL_FID1;
1656 rc = md_create(tgt->ltd_exp, op_data, data, datalen, mode, uid, gid,
1657 cap_effective, rdev, request);
1658
1659 if (rc == 0) {
1660 if (*request == NULL)
1661 return rc;
1662 CDEBUG(D_INODE, "Created - "DFID"\n", PFID(&op_data->op_fid2));
1663 }
1664 return rc;
1665}
1666
1667static int lmv_done_writing(struct obd_export *exp,
1668 struct md_op_data *op_data,
1669 struct md_open_data *mod)
1670{
1671 struct obd_device *obd = exp->exp_obd;
1672 struct lmv_obd *lmv = &obd->u.lmv;
1673 struct lmv_tgt_desc *tgt;
1674 int rc;
1675
1676 rc = lmv_check_connect(obd);
1677 if (rc)
1678 return rc;
1679
1680 tgt = lmv_find_target(lmv, &op_data->op_fid1);
1681 if (IS_ERR(tgt))
1682 return PTR_ERR(tgt);
1683
1684 rc = md_done_writing(tgt->ltd_exp, op_data, mod);
1685 return rc;
1686}
1687
1688static int
1689lmv_enqueue_remote(struct obd_export *exp, struct ldlm_enqueue_info *einfo,
1690 struct lookup_intent *it, struct md_op_data *op_data,
1691 struct lustre_handle *lockh, void *lmm, int lmmsize,
1692 __u64 extra_lock_flags)
1693{
1694 struct ptlrpc_request *req = it->d.lustre.it_data;
1695 struct obd_device *obd = exp->exp_obd;
1696 struct lmv_obd *lmv = &obd->u.lmv;
1697 struct lustre_handle plock;
1698 struct lmv_tgt_desc *tgt;
1699 struct md_op_data *rdata;
1700 struct lu_fid fid1;
1701 struct mdt_body *body;
1702 int rc = 0;
1703 int pmode;
1704
1705 body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY);
1706 LASSERT(body != NULL);
1707
1708 if (!(body->valid & OBD_MD_MDS))
1709 return 0;
1710
1711 CDEBUG(D_INODE, "REMOTE_ENQUEUE '%s' on "DFID" -> "DFID"\n",
1712 LL_IT2STR(it), PFID(&op_data->op_fid1), PFID(&body->fid1));
1713
1714
1715
1716
1717 pmode = it->d.lustre.it_lock_mode;
1718 LASSERT(pmode != 0);
1719 memcpy(&plock, lockh, sizeof(plock));
1720 it->d.lustre.it_lock_mode = 0;
1721 it->d.lustre.it_data = NULL;
1722 fid1 = body->fid1;
1723
1724 ptlrpc_req_finished(req);
1725
1726 tgt = lmv_find_target(lmv, &fid1);
1727 if (IS_ERR(tgt)) {
1728 rc = PTR_ERR(tgt);
1729 goto out;
1730 }
1731
1732 rdata = kzalloc(sizeof(*rdata), GFP_NOFS);
1733 if (!rdata) {
1734 rc = -ENOMEM;
1735 goto out;
1736 }
1737
1738 rdata->op_fid1 = fid1;
1739 rdata->op_bias = MDS_CROSS_REF;
1740
1741 rc = md_enqueue(tgt->ltd_exp, einfo, it, rdata, lockh,
1742 lmm, lmmsize, NULL, extra_lock_flags);
1743 kfree(rdata);
1744out:
1745 ldlm_lock_decref(&plock, pmode);
1746 return rc;
1747}
1748
1749static int
1750lmv_enqueue(struct obd_export *exp, struct ldlm_enqueue_info *einfo,
1751 struct lookup_intent *it, struct md_op_data *op_data,
1752 struct lustre_handle *lockh, void *lmm, int lmmsize,
1753 struct ptlrpc_request **req, __u64 extra_lock_flags)
1754{
1755 struct obd_device *obd = exp->exp_obd;
1756 struct lmv_obd *lmv = &obd->u.lmv;
1757 struct lmv_tgt_desc *tgt;
1758 int rc;
1759
1760 rc = lmv_check_connect(obd);
1761 if (rc)
1762 return rc;
1763
1764 CDEBUG(D_INODE, "ENQUEUE '%s' on "DFID"\n",
1765 LL_IT2STR(it), PFID(&op_data->op_fid1));
1766
1767 tgt = lmv_locate_mds(lmv, op_data, &op_data->op_fid1);
1768 if (IS_ERR(tgt))
1769 return PTR_ERR(tgt);
1770
1771 CDEBUG(D_INODE, "ENQUEUE '%s' on "DFID" -> mds #%d\n",
1772 LL_IT2STR(it), PFID(&op_data->op_fid1), tgt->ltd_idx);
1773
1774 rc = md_enqueue(tgt->ltd_exp, einfo, it, op_data, lockh,
1775 lmm, lmmsize, req, extra_lock_flags);
1776
1777 if (rc == 0 && it && it->it_op == IT_OPEN) {
1778 rc = lmv_enqueue_remote(exp, einfo, it, op_data, lockh,
1779 lmm, lmmsize, extra_lock_flags);
1780 }
1781 return rc;
1782}
1783
1784static int
1785lmv_getattr_name(struct obd_export *exp, struct md_op_data *op_data,
1786 struct ptlrpc_request **request)
1787{
1788 struct ptlrpc_request *req = NULL;
1789 struct obd_device *obd = exp->exp_obd;
1790 struct lmv_obd *lmv = &obd->u.lmv;
1791 struct lmv_tgt_desc *tgt;
1792 struct mdt_body *body;
1793 int rc;
1794
1795 rc = lmv_check_connect(obd);
1796 if (rc)
1797 return rc;
1798
1799 tgt = lmv_locate_mds(lmv, op_data, &op_data->op_fid1);
1800 if (IS_ERR(tgt))
1801 return PTR_ERR(tgt);
1802
1803 CDEBUG(D_INODE, "GETATTR_NAME for %*s on "DFID" -> mds #%d\n",
1804 op_data->op_namelen, op_data->op_name, PFID(&op_data->op_fid1),
1805 tgt->ltd_idx);
1806
1807 rc = md_getattr_name(tgt->ltd_exp, op_data, request);
1808 if (rc != 0)
1809 return rc;
1810
1811 body = req_capsule_server_get(&(*request)->rq_pill,
1812 &RMF_MDT_BODY);
1813 LASSERT(body != NULL);
1814
1815 if (body->valid & OBD_MD_MDS) {
1816 struct lu_fid rid = body->fid1;
1817 CDEBUG(D_INODE, "Request attrs for "DFID"\n",
1818 PFID(&rid));
1819
1820 tgt = lmv_find_target(lmv, &rid);
1821 if (IS_ERR(tgt)) {
1822 ptlrpc_req_finished(*request);
1823 return PTR_ERR(tgt);
1824 }
1825
1826 op_data->op_fid1 = rid;
1827 op_data->op_valid |= OBD_MD_FLCROSSREF;
1828 op_data->op_namelen = 0;
1829 op_data->op_name = NULL;
1830 rc = md_getattr_name(tgt->ltd_exp, op_data, &req);
1831 ptlrpc_req_finished(*request);
1832 *request = req;
1833 }
1834
1835 return rc;
1836}
1837
1838#define md_op_data_fid(op_data, fl) \
1839 (fl == MF_MDC_CANCEL_FID1 ? &op_data->op_fid1 : \
1840 fl == MF_MDC_CANCEL_FID2 ? &op_data->op_fid2 : \
1841 fl == MF_MDC_CANCEL_FID3 ? &op_data->op_fid3 : \
1842 fl == MF_MDC_CANCEL_FID4 ? &op_data->op_fid4 : \
1843 NULL)
1844
1845static int lmv_early_cancel(struct obd_export *exp, struct md_op_data *op_data,
1846 int op_tgt, ldlm_mode_t mode, int bits, int flag)
1847{
1848 struct lu_fid *fid = md_op_data_fid(op_data, flag);
1849 struct obd_device *obd = exp->exp_obd;
1850 struct lmv_obd *lmv = &obd->u.lmv;
1851 struct lmv_tgt_desc *tgt;
1852 ldlm_policy_data_t policy = {{0}};
1853 int rc = 0;
1854
1855 if (!fid_is_sane(fid))
1856 return 0;
1857
1858 tgt = lmv_find_target(lmv, fid);
1859 if (IS_ERR(tgt))
1860 return PTR_ERR(tgt);
1861
1862 if (tgt->ltd_idx != op_tgt) {
1863 CDEBUG(D_INODE, "EARLY_CANCEL on "DFID"\n", PFID(fid));
1864 policy.l_inodebits.bits = bits;
1865 rc = md_cancel_unused(tgt->ltd_exp, fid, &policy,
1866 mode, LCF_ASYNC, NULL);
1867 } else {
1868 CDEBUG(D_INODE,
1869 "EARLY_CANCEL skip operation target %d on "DFID"\n",
1870 op_tgt, PFID(fid));
1871 op_data->op_flags |= flag;
1872 rc = 0;
1873 }
1874
1875 return rc;
1876}
1877
1878
1879
1880
1881
1882static int lmv_link(struct obd_export *exp, struct md_op_data *op_data,
1883 struct ptlrpc_request **request)
1884{
1885 struct obd_device *obd = exp->exp_obd;
1886 struct lmv_obd *lmv = &obd->u.lmv;
1887 struct lmv_tgt_desc *tgt;
1888 int rc;
1889
1890 rc = lmv_check_connect(obd);
1891 if (rc)
1892 return rc;
1893
1894 LASSERT(op_data->op_namelen != 0);
1895
1896 CDEBUG(D_INODE, "LINK "DFID":%*s to "DFID"\n",
1897 PFID(&op_data->op_fid2), op_data->op_namelen,
1898 op_data->op_name, PFID(&op_data->op_fid1));
1899
1900 op_data->op_fsuid = from_kuid(&init_user_ns, current_fsuid());
1901 op_data->op_fsgid = from_kgid(&init_user_ns, current_fsgid());
1902 op_data->op_cap = cfs_curproc_cap_pack();
1903 tgt = lmv_locate_mds(lmv, op_data, &op_data->op_fid2);
1904 if (IS_ERR(tgt))
1905 return PTR_ERR(tgt);
1906
1907
1908
1909
1910 op_data->op_flags |= MF_MDC_CANCEL_FID2;
1911 rc = lmv_early_cancel(exp, op_data, tgt->ltd_idx, LCK_EX,
1912 MDS_INODELOCK_UPDATE, MF_MDC_CANCEL_FID1);
1913 if (rc != 0)
1914 return rc;
1915
1916 rc = md_link(tgt->ltd_exp, op_data, request);
1917
1918 return rc;
1919}
1920
1921static int lmv_rename(struct obd_export *exp, struct md_op_data *op_data,
1922 const char *old, int oldlen, const char *new, int newlen,
1923 struct ptlrpc_request **request)
1924{
1925 struct obd_device *obd = exp->exp_obd;
1926 struct lmv_obd *lmv = &obd->u.lmv;
1927 struct lmv_tgt_desc *src_tgt;
1928 struct lmv_tgt_desc *tgt_tgt;
1929 int rc;
1930
1931 LASSERT(oldlen != 0);
1932
1933 CDEBUG(D_INODE, "RENAME %*s in "DFID" to %*s in "DFID"\n",
1934 oldlen, old, PFID(&op_data->op_fid1),
1935 newlen, new, PFID(&op_data->op_fid2));
1936
1937 rc = lmv_check_connect(obd);
1938 if (rc)
1939 return rc;
1940
1941 op_data->op_fsuid = from_kuid(&init_user_ns, current_fsuid());
1942 op_data->op_fsgid = from_kgid(&init_user_ns, current_fsgid());
1943 op_data->op_cap = cfs_curproc_cap_pack();
1944 src_tgt = lmv_locate_mds(lmv, op_data, &op_data->op_fid1);
1945 if (IS_ERR(src_tgt))
1946 return PTR_ERR(src_tgt);
1947
1948 tgt_tgt = lmv_locate_mds(lmv, op_data, &op_data->op_fid2);
1949 if (IS_ERR(tgt_tgt))
1950 return PTR_ERR(tgt_tgt);
1951
1952
1953
1954
1955 op_data->op_flags |= MF_MDC_CANCEL_FID1 | MF_MDC_CANCEL_FID3;
1956
1957
1958
1959
1960
1961 rc = lmv_early_cancel(exp, op_data, src_tgt->ltd_idx,
1962 LCK_EX, MDS_INODELOCK_UPDATE,
1963 MF_MDC_CANCEL_FID2);
1964
1965
1966
1967
1968 if (rc == 0) {
1969 rc = lmv_early_cancel(exp, op_data, src_tgt->ltd_idx,
1970 LCK_EX, MDS_INODELOCK_LOOKUP,
1971 MF_MDC_CANCEL_FID4);
1972 }
1973
1974
1975
1976
1977 if (rc == 0)
1978 rc = lmv_early_cancel(exp, op_data, src_tgt->ltd_idx,
1979 LCK_EX, MDS_INODELOCK_FULL,
1980 MF_MDC_CANCEL_FID4);
1981
1982 if (rc == 0)
1983 rc = md_rename(src_tgt->ltd_exp, op_data, old, oldlen,
1984 new, newlen, request);
1985 return rc;
1986}
1987
1988static int lmv_setattr(struct obd_export *exp, struct md_op_data *op_data,
1989 void *ea, int ealen, void *ea2, int ea2len,
1990 struct ptlrpc_request **request,
1991 struct md_open_data **mod)
1992{
1993 struct obd_device *obd = exp->exp_obd;
1994 struct lmv_obd *lmv = &obd->u.lmv;
1995 struct lmv_tgt_desc *tgt;
1996 int rc;
1997
1998 rc = lmv_check_connect(obd);
1999 if (rc)
2000 return rc;
2001
2002 CDEBUG(D_INODE, "SETATTR for "DFID", valid 0x%x\n",
2003 PFID(&op_data->op_fid1), op_data->op_attr.ia_valid);
2004
2005 op_data->op_flags |= MF_MDC_CANCEL_FID1;
2006 tgt = lmv_find_target(lmv, &op_data->op_fid1);
2007 if (IS_ERR(tgt))
2008 return PTR_ERR(tgt);
2009
2010 rc = md_setattr(tgt->ltd_exp, op_data, ea, ealen, ea2,
2011 ea2len, request, mod);
2012
2013 return rc;
2014}
2015
2016static int lmv_sync(struct obd_export *exp, const struct lu_fid *fid,
2017 struct obd_capa *oc, struct ptlrpc_request **request)
2018{
2019 struct obd_device *obd = exp->exp_obd;
2020 struct lmv_obd *lmv = &obd->u.lmv;
2021 struct lmv_tgt_desc *tgt;
2022 int rc;
2023
2024 rc = lmv_check_connect(obd);
2025 if (rc)
2026 return rc;
2027
2028 tgt = lmv_find_target(lmv, fid);
2029 if (IS_ERR(tgt))
2030 return PTR_ERR(tgt);
2031
2032 rc = md_sync(tgt->ltd_exp, fid, oc, request);
2033 return rc;
2034}
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086#if PAGE_CACHE_SIZE > LU_PAGE_SIZE
2087static void lmv_adjust_dirpages(struct page **pages, int ncfspgs, int nlupgs)
2088{
2089 int i;
2090
2091 for (i = 0; i < ncfspgs; i++) {
2092 struct lu_dirpage *dp = kmap(pages[i]);
2093 struct lu_dirpage *first = dp;
2094 struct lu_dirent *end_dirent = NULL;
2095 struct lu_dirent *ent;
2096 __u64 hash_end = dp->ldp_hash_end;
2097 __u32 flags = dp->ldp_flags;
2098
2099 while (--nlupgs > 0) {
2100 ent = lu_dirent_start(dp);
2101 for (end_dirent = ent; ent != NULL;
2102 end_dirent = ent, ent = lu_dirent_next(ent));
2103
2104
2105 dp = (struct lu_dirpage *)((char *)dp + LU_PAGE_SIZE);
2106
2107
2108 if (!((unsigned long)dp & ~CFS_PAGE_MASK))
2109 break;
2110
2111
2112 hash_end = dp->ldp_hash_end;
2113 flags = dp->ldp_flags;
2114
2115
2116 if (!end_dirent)
2117 break;
2118
2119
2120
2121 LASSERT(le16_to_cpu(end_dirent->lde_reclen) == 0);
2122 end_dirent->lde_reclen =
2123 cpu_to_le16((char *)(dp->ldp_entries) -
2124 (char *)end_dirent);
2125 }
2126
2127 first->ldp_hash_end = hash_end;
2128 first->ldp_flags &= ~cpu_to_le32(LDF_COLLIDE);
2129 first->ldp_flags |= flags & cpu_to_le32(LDF_COLLIDE);
2130
2131 kunmap(pages[i]);
2132 }
2133 LASSERTF(nlupgs == 0, "left = %d", nlupgs);
2134}
2135#else
2136#define lmv_adjust_dirpages(pages, ncfspgs, nlupgs) do {} while (0)
2137#endif
2138
2139static int lmv_readpage(struct obd_export *exp, struct md_op_data *op_data,
2140 struct page **pages, struct ptlrpc_request **request)
2141{
2142 struct obd_device *obd = exp->exp_obd;
2143 struct lmv_obd *lmv = &obd->u.lmv;
2144 __u64 offset = op_data->op_offset;
2145 int rc;
2146 int ncfspgs;
2147 int nlupgs;
2148 struct lmv_tgt_desc *tgt;
2149
2150 rc = lmv_check_connect(obd);
2151 if (rc)
2152 return rc;
2153
2154 CDEBUG(D_INODE, "READPAGE at %#llx from "DFID"\n",
2155 offset, PFID(&op_data->op_fid1));
2156
2157 tgt = lmv_find_target(lmv, &op_data->op_fid1);
2158 if (IS_ERR(tgt))
2159 return PTR_ERR(tgt);
2160
2161 rc = md_readpage(tgt->ltd_exp, op_data, pages, request);
2162 if (rc != 0)
2163 return rc;
2164
2165 ncfspgs = ((*request)->rq_bulk->bd_nob_transferred + PAGE_CACHE_SIZE - 1)
2166 >> PAGE_CACHE_SHIFT;
2167 nlupgs = (*request)->rq_bulk->bd_nob_transferred >> LU_PAGE_SHIFT;
2168 LASSERT(!((*request)->rq_bulk->bd_nob_transferred & ~LU_PAGE_MASK));
2169 LASSERT(ncfspgs > 0 && ncfspgs <= op_data->op_npages);
2170
2171 CDEBUG(D_INODE, "read %d(%d)/%d pages\n", ncfspgs, nlupgs,
2172 op_data->op_npages);
2173
2174 lmv_adjust_dirpages(pages, ncfspgs, nlupgs);
2175
2176 return rc;
2177}
2178
2179static int lmv_unlink(struct obd_export *exp, struct md_op_data *op_data,
2180 struct ptlrpc_request **request)
2181{
2182 struct obd_device *obd = exp->exp_obd;
2183 struct lmv_obd *lmv = &obd->u.lmv;
2184 struct lmv_tgt_desc *tgt = NULL;
2185 struct mdt_body *body;
2186 int rc;
2187
2188 rc = lmv_check_connect(obd);
2189 if (rc)
2190 return rc;
2191retry:
2192
2193 if (likely(!fid_is_zero(&op_data->op_fid2)))
2194 tgt = lmv_locate_mds(lmv, op_data, &op_data->op_fid2);
2195 else
2196 tgt = lmv_locate_mds(lmv, op_data, &op_data->op_fid1);
2197 if (IS_ERR(tgt))
2198 return PTR_ERR(tgt);
2199
2200 op_data->op_fsuid = from_kuid(&init_user_ns, current_fsuid());
2201 op_data->op_fsgid = from_kgid(&init_user_ns, current_fsgid());
2202 op_data->op_cap = cfs_curproc_cap_pack();
2203
2204
2205
2206
2207
2208
2209
2210
2211 op_data->op_flags |= MF_MDC_CANCEL_FID1 | MF_MDC_CANCEL_FID3;
2212
2213
2214
2215
2216 rc = lmv_early_cancel(exp, op_data, tgt->ltd_idx, LCK_EX,
2217 MDS_INODELOCK_FULL, MF_MDC_CANCEL_FID3);
2218
2219 if (rc != 0)
2220 return rc;
2221
2222 CDEBUG(D_INODE, "unlink with fid="DFID"/"DFID" -> mds #%d\n",
2223 PFID(&op_data->op_fid1), PFID(&op_data->op_fid2), tgt->ltd_idx);
2224
2225 rc = md_unlink(tgt->ltd_exp, op_data, request);
2226 if (rc != 0 && rc != -EREMOTE)
2227 return rc;
2228
2229 body = req_capsule_server_get(&(*request)->rq_pill, &RMF_MDT_BODY);
2230 if (body == NULL)
2231 return -EPROTO;
2232
2233
2234 if (likely(!(body->valid & OBD_MD_MDS)))
2235 return 0;
2236
2237 CDEBUG(D_INODE, "%s: try unlink to another MDT for "DFID"\n",
2238 exp->exp_obd->obd_name, PFID(&body->fid1));
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259 op_data->op_fid2 = body->fid1;
2260 ptlrpc_req_finished(*request);
2261 *request = NULL;
2262
2263 goto retry;
2264}
2265
2266static int lmv_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage)
2267{
2268 struct lmv_obd *lmv = &obd->u.lmv;
2269
2270 switch (stage) {
2271 case OBD_CLEANUP_EARLY:
2272
2273
2274 break;
2275 case OBD_CLEANUP_EXPORTS:
2276 fld_client_debugfs_fini(&lmv->lmv_fld);
2277 lprocfs_obd_cleanup(obd);
2278 break;
2279 default:
2280 break;
2281 }
2282 return 0;
2283}
2284
2285static int lmv_get_info(const struct lu_env *env, struct obd_export *exp,
2286 __u32 keylen, void *key, __u32 *vallen, void *val,
2287 struct lov_stripe_md *lsm)
2288{
2289 struct obd_device *obd;
2290 struct lmv_obd *lmv;
2291 int rc = 0;
2292
2293 obd = class_exp2obd(exp);
2294 if (obd == NULL) {
2295 CDEBUG(D_IOCTL, "Invalid client cookie %#llx\n",
2296 exp->exp_handle.h_cookie);
2297 return -EINVAL;
2298 }
2299
2300 lmv = &obd->u.lmv;
2301 if (keylen >= strlen("remote_flag") && !strcmp(key, "remote_flag")) {
2302 struct lmv_tgt_desc *tgt;
2303 int i;
2304
2305 rc = lmv_check_connect(obd);
2306 if (rc)
2307 return rc;
2308
2309 LASSERT(*vallen == sizeof(__u32));
2310 for (i = 0; i < lmv->desc.ld_tgt_count; i++) {
2311 tgt = lmv->tgts[i];
2312
2313
2314
2315 if (tgt == NULL || tgt->ltd_exp == NULL)
2316 continue;
2317
2318 if (!obd_get_info(env, tgt->ltd_exp, keylen, key,
2319 vallen, val, NULL))
2320 return 0;
2321 }
2322 return -EINVAL;
2323 } else if (KEY_IS(KEY_MAX_EASIZE) ||
2324 KEY_IS(KEY_DEFAULT_EASIZE) ||
2325 KEY_IS(KEY_MAX_COOKIESIZE) ||
2326 KEY_IS(KEY_DEFAULT_COOKIESIZE) ||
2327 KEY_IS(KEY_CONN_DATA)) {
2328 rc = lmv_check_connect(obd);
2329 if (rc)
2330 return rc;
2331
2332
2333
2334
2335
2336 rc = obd_get_info(env, lmv->tgts[0]->ltd_exp, keylen, key,
2337 vallen, val, NULL);
2338 if (!rc && KEY_IS(KEY_CONN_DATA))
2339 exp->exp_connect_data = *(struct obd_connect_data *)val;
2340 return rc;
2341 } else if (KEY_IS(KEY_TGT_COUNT)) {
2342 *((int *)val) = lmv->desc.ld_tgt_count;
2343 return 0;
2344 }
2345
2346 CDEBUG(D_IOCTL, "Invalid key\n");
2347 return -EINVAL;
2348}
2349
2350static int lmv_set_info_async(const struct lu_env *env, struct obd_export *exp,
2351 u32 keylen, void *key, u32 vallen,
2352 void *val, struct ptlrpc_request_set *set)
2353{
2354 struct lmv_tgt_desc *tgt;
2355 struct obd_device *obd;
2356 struct lmv_obd *lmv;
2357 int rc = 0;
2358
2359 obd = class_exp2obd(exp);
2360 if (obd == NULL) {
2361 CDEBUG(D_IOCTL, "Invalid client cookie %#llx\n",
2362 exp->exp_handle.h_cookie);
2363 return -EINVAL;
2364 }
2365 lmv = &obd->u.lmv;
2366
2367 if (KEY_IS(KEY_READ_ONLY) || KEY_IS(KEY_FLUSH_CTX)) {
2368 int i, err = 0;
2369
2370 for (i = 0; i < lmv->desc.ld_tgt_count; i++) {
2371 tgt = lmv->tgts[i];
2372
2373 if (tgt == NULL || tgt->ltd_exp == NULL)
2374 continue;
2375
2376 err = obd_set_info_async(env, tgt->ltd_exp,
2377 keylen, key, vallen, val, set);
2378 if (err && rc == 0)
2379 rc = err;
2380 }
2381
2382 return rc;
2383 }
2384
2385 return -EINVAL;
2386}
2387
2388static int lmv_packmd(struct obd_export *exp, struct lov_mds_md **lmmp,
2389 struct lov_stripe_md *lsm)
2390{
2391 struct obd_device *obd = class_exp2obd(exp);
2392 struct lmv_obd *lmv = &obd->u.lmv;
2393 struct lmv_stripe_md *meap;
2394 struct lmv_stripe_md *lsmp;
2395 int mea_size;
2396 int i;
2397
2398 mea_size = lmv_get_easize(lmv);
2399 if (!lmmp)
2400 return mea_size;
2401
2402 if (*lmmp && !lsm) {
2403 kvfree(*lmmp);
2404 *lmmp = NULL;
2405 return 0;
2406 }
2407
2408 if (*lmmp == NULL) {
2409 *lmmp = libcfs_kvzalloc(mea_size, GFP_NOFS);
2410 if (*lmmp == NULL)
2411 return -ENOMEM;
2412 }
2413
2414 if (!lsm)
2415 return mea_size;
2416
2417 lsmp = (struct lmv_stripe_md *)lsm;
2418 meap = (struct lmv_stripe_md *)*lmmp;
2419
2420 if (lsmp->mea_magic != MEA_MAGIC_LAST_CHAR &&
2421 lsmp->mea_magic != MEA_MAGIC_ALL_CHARS)
2422 return -EINVAL;
2423
2424 meap->mea_magic = cpu_to_le32(lsmp->mea_magic);
2425 meap->mea_count = cpu_to_le32(lsmp->mea_count);
2426 meap->mea_master = cpu_to_le32(lsmp->mea_master);
2427
2428 for (i = 0; i < lmv->desc.ld_tgt_count; i++) {
2429 meap->mea_ids[i] = lsmp->mea_ids[i];
2430 fid_cpu_to_le(&meap->mea_ids[i], &lsmp->mea_ids[i]);
2431 }
2432
2433 return mea_size;
2434}
2435
2436static int lmv_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsmp,
2437 struct lov_mds_md *lmm, int lmm_size)
2438{
2439 struct obd_device *obd = class_exp2obd(exp);
2440 struct lmv_stripe_md **tmea = (struct lmv_stripe_md **)lsmp;
2441 struct lmv_stripe_md *mea = (struct lmv_stripe_md *)lmm;
2442 struct lmv_obd *lmv = &obd->u.lmv;
2443 int mea_size;
2444 int i;
2445 __u32 magic;
2446
2447 mea_size = lmv_get_easize(lmv);
2448 if (lsmp == NULL)
2449 return mea_size;
2450
2451 if (*lsmp != NULL && lmm == NULL) {
2452 kvfree(*tmea);
2453 *lsmp = NULL;
2454 return 0;
2455 }
2456
2457 LASSERT(mea_size == lmm_size);
2458
2459 *tmea = libcfs_kvzalloc(mea_size, GFP_NOFS);
2460 if (*tmea == NULL)
2461 return -ENOMEM;
2462
2463 if (!lmm)
2464 return mea_size;
2465
2466 if (mea->mea_magic == MEA_MAGIC_LAST_CHAR ||
2467 mea->mea_magic == MEA_MAGIC_ALL_CHARS ||
2468 mea->mea_magic == MEA_MAGIC_HASH_SEGMENT) {
2469 magic = le32_to_cpu(mea->mea_magic);
2470 } else {
2471
2472
2473
2474 CERROR("Old not supportable EA is found\n");
2475 LBUG();
2476 }
2477
2478 (*tmea)->mea_magic = magic;
2479 (*tmea)->mea_count = le32_to_cpu(mea->mea_count);
2480 (*tmea)->mea_master = le32_to_cpu(mea->mea_master);
2481
2482 for (i = 0; i < (*tmea)->mea_count; i++) {
2483 (*tmea)->mea_ids[i] = mea->mea_ids[i];
2484 fid_le_to_cpu(&(*tmea)->mea_ids[i], &(*tmea)->mea_ids[i]);
2485 }
2486 return mea_size;
2487}
2488
2489static int lmv_cancel_unused(struct obd_export *exp, const struct lu_fid *fid,
2490 ldlm_policy_data_t *policy, ldlm_mode_t mode,
2491 ldlm_cancel_flags_t flags, void *opaque)
2492{
2493 struct obd_device *obd = exp->exp_obd;
2494 struct lmv_obd *lmv = &obd->u.lmv;
2495 int rc = 0;
2496 int err;
2497 int i;
2498
2499 LASSERT(fid != NULL);
2500
2501 for (i = 0; i < lmv->desc.ld_tgt_count; i++) {
2502 if (lmv->tgts[i] == NULL || lmv->tgts[i]->ltd_exp == NULL ||
2503 lmv->tgts[i]->ltd_active == 0)
2504 continue;
2505
2506 err = md_cancel_unused(lmv->tgts[i]->ltd_exp, fid,
2507 policy, mode, flags, opaque);
2508 if (!rc)
2509 rc = err;
2510 }
2511 return rc;
2512}
2513
2514static int lmv_set_lock_data(struct obd_export *exp, __u64 *lockh, void *data,
2515 __u64 *bits)
2516{
2517 struct lmv_obd *lmv = &exp->exp_obd->u.lmv;
2518 int rc;
2519
2520 rc = md_set_lock_data(lmv->tgts[0]->ltd_exp, lockh, data, bits);
2521 return rc;
2522}
2523
2524static ldlm_mode_t lmv_lock_match(struct obd_export *exp, __u64 flags,
2525 const struct lu_fid *fid, ldlm_type_t type,
2526 ldlm_policy_data_t *policy, ldlm_mode_t mode,
2527 struct lustre_handle *lockh)
2528{
2529 struct obd_device *obd = exp->exp_obd;
2530 struct lmv_obd *lmv = &obd->u.lmv;
2531 ldlm_mode_t rc;
2532 int i;
2533
2534 CDEBUG(D_INODE, "Lock match for "DFID"\n", PFID(fid));
2535
2536
2537
2538
2539
2540
2541
2542 for (i = 0; i < lmv->desc.ld_tgt_count; i++) {
2543 if (lmv->tgts[i] == NULL ||
2544 lmv->tgts[i]->ltd_exp == NULL ||
2545 lmv->tgts[i]->ltd_active == 0)
2546 continue;
2547
2548 rc = md_lock_match(lmv->tgts[i]->ltd_exp, flags, fid,
2549 type, policy, mode, lockh);
2550 if (rc)
2551 return rc;
2552 }
2553
2554 return 0;
2555}
2556
2557static int lmv_get_lustre_md(struct obd_export *exp,
2558 struct ptlrpc_request *req,
2559 struct obd_export *dt_exp,
2560 struct obd_export *md_exp,
2561 struct lustre_md *md)
2562{
2563 struct lmv_obd *lmv = &exp->exp_obd->u.lmv;
2564
2565 return md_get_lustre_md(lmv->tgts[0]->ltd_exp, req, dt_exp, md_exp, md);
2566}
2567
2568static int lmv_free_lustre_md(struct obd_export *exp, struct lustre_md *md)
2569{
2570 struct obd_device *obd = exp->exp_obd;
2571 struct lmv_obd *lmv = &obd->u.lmv;
2572
2573 if (md->mea)
2574 obd_free_memmd(exp, (void *)&md->mea);
2575 return md_free_lustre_md(lmv->tgts[0]->ltd_exp, md);
2576}
2577
2578static int lmv_set_open_replay_data(struct obd_export *exp,
2579 struct obd_client_handle *och,
2580 struct lookup_intent *it)
2581{
2582 struct obd_device *obd = exp->exp_obd;
2583 struct lmv_obd *lmv = &obd->u.lmv;
2584 struct lmv_tgt_desc *tgt;
2585
2586 tgt = lmv_find_target(lmv, &och->och_fid);
2587 if (IS_ERR(tgt))
2588 return PTR_ERR(tgt);
2589
2590 return md_set_open_replay_data(tgt->ltd_exp, och, it);
2591}
2592
2593static int lmv_clear_open_replay_data(struct obd_export *exp,
2594 struct obd_client_handle *och)
2595{
2596 struct obd_device *obd = exp->exp_obd;
2597 struct lmv_obd *lmv = &obd->u.lmv;
2598 struct lmv_tgt_desc *tgt;
2599
2600 tgt = lmv_find_target(lmv, &och->och_fid);
2601 if (IS_ERR(tgt))
2602 return PTR_ERR(tgt);
2603
2604 return md_clear_open_replay_data(tgt->ltd_exp, och);
2605}
2606
2607static int lmv_get_remote_perm(struct obd_export *exp,
2608 const struct lu_fid *fid,
2609 struct obd_capa *oc, __u32 suppgid,
2610 struct ptlrpc_request **request)
2611{
2612 struct obd_device *obd = exp->exp_obd;
2613 struct lmv_obd *lmv = &obd->u.lmv;
2614 struct lmv_tgt_desc *tgt;
2615 int rc;
2616
2617 rc = lmv_check_connect(obd);
2618 if (rc)
2619 return rc;
2620
2621 tgt = lmv_find_target(lmv, fid);
2622 if (IS_ERR(tgt))
2623 return PTR_ERR(tgt);
2624
2625 rc = md_get_remote_perm(tgt->ltd_exp, fid, oc, suppgid, request);
2626 return rc;
2627}
2628
2629static int lmv_renew_capa(struct obd_export *exp, struct obd_capa *oc,
2630 renew_capa_cb_t cb)
2631{
2632 struct obd_device *obd = exp->exp_obd;
2633 struct lmv_obd *lmv = &obd->u.lmv;
2634 struct lmv_tgt_desc *tgt;
2635 int rc;
2636
2637 rc = lmv_check_connect(obd);
2638 if (rc)
2639 return rc;
2640
2641 tgt = lmv_find_target(lmv, &oc->c_capa.lc_fid);
2642 if (IS_ERR(tgt))
2643 return PTR_ERR(tgt);
2644
2645 rc = md_renew_capa(tgt->ltd_exp, oc, cb);
2646 return rc;
2647}
2648
2649static int lmv_unpack_capa(struct obd_export *exp, struct ptlrpc_request *req,
2650 const struct req_msg_field *field,
2651 struct obd_capa **oc)
2652{
2653 struct lmv_obd *lmv = &exp->exp_obd->u.lmv;
2654
2655 return md_unpack_capa(lmv->tgts[0]->ltd_exp, req, field, oc);
2656}
2657
2658static int lmv_intent_getattr_async(struct obd_export *exp,
2659 struct md_enqueue_info *minfo,
2660 struct ldlm_enqueue_info *einfo)
2661{
2662 struct md_op_data *op_data = &minfo->mi_data;
2663 struct obd_device *obd = exp->exp_obd;
2664 struct lmv_obd *lmv = &obd->u.lmv;
2665 struct lmv_tgt_desc *tgt = NULL;
2666 int rc;
2667
2668 rc = lmv_check_connect(obd);
2669 if (rc)
2670 return rc;
2671
2672 tgt = lmv_find_target(lmv, &op_data->op_fid1);
2673 if (IS_ERR(tgt))
2674 return PTR_ERR(tgt);
2675
2676 rc = md_intent_getattr_async(tgt->ltd_exp, minfo, einfo);
2677 return rc;
2678}
2679
2680static int lmv_revalidate_lock(struct obd_export *exp, struct lookup_intent *it,
2681 struct lu_fid *fid, __u64 *bits)
2682{
2683 struct obd_device *obd = exp->exp_obd;
2684 struct lmv_obd *lmv = &obd->u.lmv;
2685 struct lmv_tgt_desc *tgt;
2686 int rc;
2687
2688 rc = lmv_check_connect(obd);
2689 if (rc)
2690 return rc;
2691
2692 tgt = lmv_find_target(lmv, fid);
2693 if (IS_ERR(tgt))
2694 return PTR_ERR(tgt);
2695
2696 rc = md_revalidate_lock(tgt->ltd_exp, it, fid, bits);
2697 return rc;
2698}
2699
2700
2701
2702
2703
2704
2705static int lmv_quotactl(struct obd_device *unused, struct obd_export *exp,
2706 struct obd_quotactl *oqctl)
2707{
2708 struct obd_device *obd = class_exp2obd(exp);
2709 struct lmv_obd *lmv = &obd->u.lmv;
2710 struct lmv_tgt_desc *tgt = lmv->tgts[0];
2711 int rc = 0, i;
2712 __u64 curspace, curinodes;
2713
2714 if (!lmv->desc.ld_tgt_count || !tgt->ltd_active) {
2715 CERROR("master lmv inactive\n");
2716 return -EIO;
2717 }
2718
2719 if (oqctl->qc_cmd != Q_GETOQUOTA) {
2720 rc = obd_quotactl(tgt->ltd_exp, oqctl);
2721 return rc;
2722 }
2723
2724 curspace = curinodes = 0;
2725 for (i = 0; i < lmv->desc.ld_tgt_count; i++) {
2726 int err;
2727 tgt = lmv->tgts[i];
2728
2729 if (tgt == NULL || tgt->ltd_exp == NULL || tgt->ltd_active == 0)
2730 continue;
2731 if (!tgt->ltd_active) {
2732 CDEBUG(D_HA, "mdt %d is inactive.\n", i);
2733 continue;
2734 }
2735
2736 err = obd_quotactl(tgt->ltd_exp, oqctl);
2737 if (err) {
2738 CERROR("getquota on mdt %d failed. %d\n", i, err);
2739 if (!rc)
2740 rc = err;
2741 } else {
2742 curspace += oqctl->qc_dqblk.dqb_curspace;
2743 curinodes += oqctl->qc_dqblk.dqb_curinodes;
2744 }
2745 }
2746 oqctl->qc_dqblk.dqb_curspace = curspace;
2747 oqctl->qc_dqblk.dqb_curinodes = curinodes;
2748
2749 return rc;
2750}
2751
2752static int lmv_quotacheck(struct obd_device *unused, struct obd_export *exp,
2753 struct obd_quotactl *oqctl)
2754{
2755 struct obd_device *obd = class_exp2obd(exp);
2756 struct lmv_obd *lmv = &obd->u.lmv;
2757 struct lmv_tgt_desc *tgt;
2758 int i, rc = 0;
2759
2760 for (i = 0; i < lmv->desc.ld_tgt_count; i++) {
2761 int err;
2762 tgt = lmv->tgts[i];
2763 if (tgt == NULL || tgt->ltd_exp == NULL || !tgt->ltd_active) {
2764 CERROR("lmv idx %d inactive\n", i);
2765 return -EIO;
2766 }
2767
2768 err = obd_quotacheck(tgt->ltd_exp, oqctl);
2769 if (err && !rc)
2770 rc = err;
2771 }
2772
2773 return rc;
2774}
2775
2776static struct obd_ops lmv_obd_ops = {
2777 .o_owner = THIS_MODULE,
2778 .o_setup = lmv_setup,
2779 .o_cleanup = lmv_cleanup,
2780 .o_precleanup = lmv_precleanup,
2781 .o_process_config = lmv_process_config,
2782 .o_connect = lmv_connect,
2783 .o_disconnect = lmv_disconnect,
2784 .o_statfs = lmv_statfs,
2785 .o_get_info = lmv_get_info,
2786 .o_set_info_async = lmv_set_info_async,
2787 .o_packmd = lmv_packmd,
2788 .o_unpackmd = lmv_unpackmd,
2789 .o_notify = lmv_notify,
2790 .o_get_uuid = lmv_get_uuid,
2791 .o_iocontrol = lmv_iocontrol,
2792 .o_quotacheck = lmv_quotacheck,
2793 .o_quotactl = lmv_quotactl
2794};
2795
2796static struct md_ops lmv_md_ops = {
2797 .m_getstatus = lmv_getstatus,
2798 .m_null_inode = lmv_null_inode,
2799 .m_find_cbdata = lmv_find_cbdata,
2800 .m_close = lmv_close,
2801 .m_create = lmv_create,
2802 .m_done_writing = lmv_done_writing,
2803 .m_enqueue = lmv_enqueue,
2804 .m_getattr = lmv_getattr,
2805 .m_getxattr = lmv_getxattr,
2806 .m_getattr_name = lmv_getattr_name,
2807 .m_intent_lock = lmv_intent_lock,
2808 .m_link = lmv_link,
2809 .m_rename = lmv_rename,
2810 .m_setattr = lmv_setattr,
2811 .m_setxattr = lmv_setxattr,
2812 .m_sync = lmv_sync,
2813 .m_readpage = lmv_readpage,
2814 .m_unlink = lmv_unlink,
2815 .m_init_ea_size = lmv_init_ea_size,
2816 .m_cancel_unused = lmv_cancel_unused,
2817 .m_set_lock_data = lmv_set_lock_data,
2818 .m_lock_match = lmv_lock_match,
2819 .m_get_lustre_md = lmv_get_lustre_md,
2820 .m_free_lustre_md = lmv_free_lustre_md,
2821 .m_set_open_replay_data = lmv_set_open_replay_data,
2822 .m_clear_open_replay_data = lmv_clear_open_replay_data,
2823 .m_renew_capa = lmv_renew_capa,
2824 .m_unpack_capa = lmv_unpack_capa,
2825 .m_get_remote_perm = lmv_get_remote_perm,
2826 .m_intent_getattr_async = lmv_intent_getattr_async,
2827 .m_revalidate_lock = lmv_revalidate_lock
2828};
2829
2830static int __init lmv_init(void)
2831{
2832 struct lprocfs_static_vars lvars;
2833 int rc;
2834
2835 lprocfs_lmv_init_vars(&lvars);
2836
2837 rc = class_register_type(&lmv_obd_ops, &lmv_md_ops,
2838 LUSTRE_LMV_NAME, NULL);
2839 return rc;
2840}
2841
2842static void lmv_exit(void)
2843{
2844 class_unregister_type(LUSTRE_LMV_NAME);
2845}
2846
2847MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>");
2848MODULE_DESCRIPTION("Lustre Logical Metadata Volume OBD driver");
2849MODULE_LICENSE("GPL");
2850
2851module_init(lmv_init);
2852module_exit(lmv_exit);
2853