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
38
39
40
41
42
43
44#define DEBUG_SUBSYSTEM S_CLASS
45
46#include "../include/obd.h"
47#include "../include/dt_object.h"
48#include <linux/list.h>
49
50#include "../include/lustre_fid.h"
51
52
53LU_KEY_INIT(dt_global, struct dt_thread_info);
54LU_KEY_FINI(dt_global, struct dt_thread_info);
55
56struct lu_context_key dt_key = {
57 .lct_tags = LCT_MD_THREAD | LCT_DT_THREAD | LCT_MG_THREAD | LCT_LOCAL,
58 .lct_init = dt_global_key_init,
59 .lct_fini = dt_global_key_fini
60};
61EXPORT_SYMBOL(dt_key);
62
63
64
65
66void dt_txn_callback_add(struct dt_device *dev, struct dt_txn_callback *cb)
67{
68 list_add(&cb->dtc_linkage, &dev->dd_txn_callbacks);
69}
70EXPORT_SYMBOL(dt_txn_callback_add);
71
72void dt_txn_callback_del(struct dt_device *dev, struct dt_txn_callback *cb)
73{
74 list_del_init(&cb->dtc_linkage);
75}
76EXPORT_SYMBOL(dt_txn_callback_del);
77
78int dt_txn_hook_start(const struct lu_env *env,
79 struct dt_device *dev, struct thandle *th)
80{
81 int rc = 0;
82 struct dt_txn_callback *cb;
83
84 if (th->th_local)
85 return 0;
86
87 list_for_each_entry(cb, &dev->dd_txn_callbacks, dtc_linkage) {
88 if (cb->dtc_txn_start == NULL ||
89 !(cb->dtc_tag & env->le_ctx.lc_tags))
90 continue;
91 rc = cb->dtc_txn_start(env, th, cb->dtc_cookie);
92 if (rc < 0)
93 break;
94 }
95 return rc;
96}
97EXPORT_SYMBOL(dt_txn_hook_start);
98
99int dt_txn_hook_stop(const struct lu_env *env, struct thandle *txn)
100{
101 struct dt_device *dev = txn->th_dev;
102 struct dt_txn_callback *cb;
103 int rc = 0;
104
105 if (txn->th_local)
106 return 0;
107
108 list_for_each_entry(cb, &dev->dd_txn_callbacks, dtc_linkage) {
109 if (cb->dtc_txn_stop == NULL ||
110 !(cb->dtc_tag & env->le_ctx.lc_tags))
111 continue;
112 rc = cb->dtc_txn_stop(env, txn, cb->dtc_cookie);
113 if (rc < 0)
114 break;
115 }
116 return rc;
117}
118EXPORT_SYMBOL(dt_txn_hook_stop);
119
120void dt_txn_hook_commit(struct thandle *txn)
121{
122 struct dt_txn_callback *cb;
123
124 if (txn->th_local)
125 return;
126
127 list_for_each_entry(cb, &txn->th_dev->dd_txn_callbacks,
128 dtc_linkage) {
129 if (cb->dtc_txn_commit)
130 cb->dtc_txn_commit(txn, cb->dtc_cookie);
131 }
132}
133EXPORT_SYMBOL(dt_txn_hook_commit);
134
135int dt_device_init(struct dt_device *dev, struct lu_device_type *t)
136{
137
138 INIT_LIST_HEAD(&dev->dd_txn_callbacks);
139 return lu_device_init(&dev->dd_lu_dev, t);
140}
141EXPORT_SYMBOL(dt_device_init);
142
143void dt_device_fini(struct dt_device *dev)
144{
145 lu_device_fini(&dev->dd_lu_dev);
146}
147EXPORT_SYMBOL(dt_device_fini);
148
149int dt_object_init(struct dt_object *obj,
150 struct lu_object_header *h, struct lu_device *d)
151
152{
153 return lu_object_init(&obj->do_lu, h, d);
154}
155EXPORT_SYMBOL(dt_object_init);
156
157void dt_object_fini(struct dt_object *obj)
158{
159 lu_object_fini(&obj->do_lu);
160}
161EXPORT_SYMBOL(dt_object_fini);
162
163int dt_try_as_dir(const struct lu_env *env, struct dt_object *obj)
164{
165 if (obj->do_index_ops == NULL)
166 obj->do_ops->do_index_try(env, obj, &dt_directory_features);
167 return obj->do_index_ops != NULL;
168}
169EXPORT_SYMBOL(dt_try_as_dir);
170
171enum dt_format_type dt_mode_to_dft(__u32 mode)
172{
173 enum dt_format_type result;
174
175 switch (mode & S_IFMT) {
176 case S_IFDIR:
177 result = DFT_DIR;
178 break;
179 case S_IFREG:
180 result = DFT_REGULAR;
181 break;
182 case S_IFLNK:
183 result = DFT_SYM;
184 break;
185 case S_IFCHR:
186 case S_IFBLK:
187 case S_IFIFO:
188 case S_IFSOCK:
189 result = DFT_NODE;
190 break;
191 default:
192 LBUG();
193 break;
194 }
195 return result;
196}
197EXPORT_SYMBOL(dt_mode_to_dft);
198
199
200
201
202
203int dt_lookup_dir(const struct lu_env *env, struct dt_object *dir,
204 const char *name, struct lu_fid *fid)
205{
206 if (dt_try_as_dir(env, dir))
207 return dt_lookup(env, dir, (struct dt_rec *)fid,
208 (const struct dt_key *)name, BYPASS_CAPA);
209 return -ENOTDIR;
210}
211EXPORT_SYMBOL(dt_lookup_dir);
212
213
214
215struct dt_object *dt_locate_at(const struct lu_env *env,
216 struct dt_device *dev, const struct lu_fid *fid,
217 struct lu_device *top_dev)
218{
219 struct lu_object *lo, *n;
220
221 lo = lu_object_find_at(env, top_dev, fid, NULL);
222 if (IS_ERR(lo))
223 return (void *)lo;
224
225 LASSERT(lo != NULL);
226
227 list_for_each_entry(n, &lo->lo_header->loh_layers, lo_linkage) {
228 if (n->lo_dev == &dev->dd_lu_dev)
229 return container_of0(n, struct dt_object, do_lu);
230 }
231 return ERR_PTR(-ENOENT);
232}
233EXPORT_SYMBOL(dt_locate_at);
234
235
236
237
238static int dt_find_entry(const struct lu_env *env,
239 const char *entry, void *data)
240{
241 struct dt_find_hint *dfh = data;
242 struct dt_device *dt = dfh->dfh_dt;
243 struct lu_fid *fid = dfh->dfh_fid;
244 struct dt_object *obj = dfh->dfh_o;
245 int result;
246
247 result = dt_lookup_dir(env, obj, entry, fid);
248 lu_object_put(env, &obj->do_lu);
249 if (result == 0) {
250 obj = dt_locate(env, dt, fid);
251 if (IS_ERR(obj))
252 result = PTR_ERR(obj);
253 }
254 dfh->dfh_o = obj;
255 return result;
256}
257
258
259
260
261
262int dt_path_parser(const struct lu_env *env,
263 char *path, dt_entry_func_t entry_func,
264 void *data)
265{
266 char *e;
267 int rc = 0;
268
269 while (1) {
270 e = strsep(&path, "/");
271 if (e == NULL)
272 break;
273
274 if (e[0] == 0) {
275 if (!path || path[0] == '\0')
276 break;
277 continue;
278 }
279 rc = entry_func(env, e, data);
280 if (rc)
281 break;
282 }
283
284 return rc;
285}
286
287struct dt_object *
288dt_store_resolve(const struct lu_env *env, struct dt_device *dt,
289 const char *path, struct lu_fid *fid)
290{
291 struct dt_thread_info *info = dt_info(env);
292 struct dt_find_hint *dfh = &info->dti_dfh;
293 struct dt_object *obj;
294 char *local = info->dti_buf;
295 int result;
296
297
298 dfh->dfh_dt = dt;
299 dfh->dfh_fid = fid;
300
301 strncpy(local, path, DT_MAX_PATH);
302 local[DT_MAX_PATH - 1] = '\0';
303
304 result = dt->dd_ops->dt_root_get(env, dt, fid);
305 if (result == 0) {
306 obj = dt_locate(env, dt, fid);
307 if (!IS_ERR(obj)) {
308 dfh->dfh_o = obj;
309 result = dt_path_parser(env, local, dt_find_entry, dfh);
310 if (result != 0)
311 obj = ERR_PTR(result);
312 else
313 obj = dfh->dfh_o;
314 }
315 } else {
316 obj = ERR_PTR(result);
317 }
318 return obj;
319}
320EXPORT_SYMBOL(dt_store_resolve);
321
322static struct dt_object *dt_reg_open(const struct lu_env *env,
323 struct dt_device *dt,
324 struct dt_object *p,
325 const char *name,
326 struct lu_fid *fid)
327{
328 struct dt_object *o;
329 int result;
330
331 result = dt_lookup_dir(env, p, name, fid);
332 if (result == 0)
333 o = dt_locate(env, dt, fid);
334 else
335 o = ERR_PTR(result);
336
337 return o;
338}
339
340
341
342
343
344
345struct dt_object *dt_store_open(const struct lu_env *env,
346 struct dt_device *dt,
347 const char *dirname,
348 const char *filename,
349 struct lu_fid *fid)
350{
351 struct dt_object *file;
352 struct dt_object *dir;
353
354 dir = dt_store_resolve(env, dt, dirname, fid);
355 if (!IS_ERR(dir)) {
356 file = dt_reg_open(env, dt, dir,
357 filename, fid);
358 lu_object_put(env, &dir->do_lu);
359 } else {
360 file = dir;
361 }
362 return file;
363}
364EXPORT_SYMBOL(dt_store_open);
365
366struct dt_object *dt_find_or_create(const struct lu_env *env,
367 struct dt_device *dt,
368 const struct lu_fid *fid,
369 struct dt_object_format *dof,
370 struct lu_attr *at)
371{
372 struct dt_object *dto;
373 struct thandle *th;
374 int rc;
375
376 dto = dt_locate(env, dt, fid);
377 if (IS_ERR(dto))
378 return dto;
379
380 LASSERT(dto != NULL);
381 if (dt_object_exists(dto))
382 return dto;
383
384 th = dt_trans_create(env, dt);
385 if (IS_ERR(th)) {
386 rc = PTR_ERR(th);
387 goto out;
388 }
389
390 rc = dt_declare_create(env, dto, at, NULL, dof, th);
391 if (rc)
392 goto trans_stop;
393
394 rc = dt_trans_start_local(env, dt, th);
395 if (rc)
396 goto trans_stop;
397
398 dt_write_lock(env, dto, 0);
399 if (dt_object_exists(dto)) {
400 rc = 0;
401 goto unlock;
402 }
403
404 CDEBUG(D_OTHER, "create new object "DFID"\n", PFID(fid));
405
406 rc = dt_create(env, dto, at, NULL, dof, th);
407 if (rc)
408 goto unlock;
409 LASSERT(dt_object_exists(dto));
410unlock:
411 dt_write_unlock(env, dto);
412trans_stop:
413 dt_trans_stop(env, dt, th);
414out:
415 if (rc) {
416 lu_object_put(env, &dto->do_lu);
417 return ERR_PTR(rc);
418 }
419 return dto;
420}
421EXPORT_SYMBOL(dt_find_or_create);
422
423
424int dt_global_init(void)
425{
426 LU_CONTEXT_KEY_INIT(&dt_key);
427 return lu_context_key_register(&dt_key);
428}
429
430void dt_global_fini(void)
431{
432 lu_context_key_degister(&dt_key);
433}
434
435
436
437
438
439
440
441
442
443
444
445
446int dt_read(const struct lu_env *env, struct dt_object *dt,
447 struct lu_buf *buf, loff_t *pos)
448{
449 LASSERTF(dt != NULL, "dt is NULL when we want to read record\n");
450 return dt->do_body_ops->dbo_read(env, dt, buf, pos, BYPASS_CAPA);
451}
452EXPORT_SYMBOL(dt_read);
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467int dt_record_read(const struct lu_env *env, struct dt_object *dt,
468 struct lu_buf *buf, loff_t *pos)
469{
470 int rc;
471
472 LASSERTF(dt != NULL, "dt is NULL when we want to read record\n");
473
474 rc = dt->do_body_ops->dbo_read(env, dt, buf, pos, BYPASS_CAPA);
475
476 if (rc == buf->lb_len)
477 rc = 0;
478 else if (rc >= 0)
479 rc = -EFAULT;
480 return rc;
481}
482EXPORT_SYMBOL(dt_record_read);
483
484int dt_record_write(const struct lu_env *env, struct dt_object *dt,
485 const struct lu_buf *buf, loff_t *pos, struct thandle *th)
486{
487 int rc;
488
489 LASSERTF(dt != NULL, "dt is NULL when we want to write record\n");
490 LASSERT(th != NULL);
491 LASSERT(dt->do_body_ops);
492 LASSERT(dt->do_body_ops->dbo_write);
493 rc = dt->do_body_ops->dbo_write(env, dt, buf, pos, th, BYPASS_CAPA, 1);
494 if (rc == buf->lb_len)
495 rc = 0;
496 else if (rc >= 0)
497 rc = -EFAULT;
498 return rc;
499}
500EXPORT_SYMBOL(dt_record_write);
501
502int dt_declare_version_set(const struct lu_env *env, struct dt_object *o,
503 struct thandle *th)
504{
505 struct lu_buf vbuf;
506 char *xname = XATTR_NAME_VERSION;
507
508 LASSERT(o);
509 vbuf.lb_buf = NULL;
510 vbuf.lb_len = sizeof(dt_obj_version_t);
511 return dt_declare_xattr_set(env, o, &vbuf, xname, 0, th);
512
513}
514EXPORT_SYMBOL(dt_declare_version_set);
515
516void dt_version_set(const struct lu_env *env, struct dt_object *o,
517 dt_obj_version_t version, struct thandle *th)
518{
519 struct lu_buf vbuf;
520 char *xname = XATTR_NAME_VERSION;
521 int rc;
522
523 LASSERT(o);
524 vbuf.lb_buf = &version;
525 vbuf.lb_len = sizeof(version);
526
527 rc = dt_xattr_set(env, o, &vbuf, xname, 0, th, BYPASS_CAPA);
528 if (rc < 0)
529 CDEBUG(D_INODE, "Can't set version, rc %d\n", rc);
530 return;
531}
532EXPORT_SYMBOL(dt_version_set);
533
534dt_obj_version_t dt_version_get(const struct lu_env *env, struct dt_object *o)
535{
536 struct lu_buf vbuf;
537 char *xname = XATTR_NAME_VERSION;
538 dt_obj_version_t version;
539 int rc;
540
541 LASSERT(o);
542 vbuf.lb_buf = &version;
543 vbuf.lb_len = sizeof(version);
544 rc = dt_xattr_get(env, o, &vbuf, xname, BYPASS_CAPA);
545 if (rc != sizeof(version)) {
546 CDEBUG(D_INODE, "Can't get version, rc %d\n", rc);
547 version = 0;
548 }
549 return version;
550}
551EXPORT_SYMBOL(dt_version_get);
552
553
554
555
556const struct dt_index_features dt_directory_features;
557EXPORT_SYMBOL(dt_directory_features);
558
559
560const struct dt_index_features dt_otable_features;
561EXPORT_SYMBOL(dt_otable_features);
562
563
564const struct dt_index_features dt_lfsck_features = {
565 .dif_flags = DT_IND_UPDATE,
566 .dif_keysize_min = sizeof(struct lu_fid),
567 .dif_keysize_max = sizeof(struct lu_fid),
568 .dif_recsize_min = sizeof(__u8),
569 .dif_recsize_max = sizeof(__u8),
570 .dif_ptrsize = 4
571};
572EXPORT_SYMBOL(dt_lfsck_features);
573
574
575const struct dt_index_features dt_acct_features = {
576 .dif_flags = DT_IND_UPDATE,
577 .dif_keysize_min = sizeof(__u64),
578 .dif_keysize_max = sizeof(__u64),
579 .dif_recsize_min = sizeof(struct lquota_acct_rec),
580 .dif_recsize_max = sizeof(struct lquota_acct_rec),
581 .dif_ptrsize = 4
582};
583EXPORT_SYMBOL(dt_acct_features);
584
585
586const struct dt_index_features dt_quota_glb_features = {
587 .dif_flags = DT_IND_UPDATE,
588
589 .dif_keysize_min = sizeof(__u64),
590 .dif_keysize_max = sizeof(__u64),
591 .dif_recsize_min = sizeof(struct lquota_glb_rec),
592 .dif_recsize_max = sizeof(struct lquota_glb_rec),
593 .dif_ptrsize = 4
594};
595EXPORT_SYMBOL(dt_quota_glb_features);
596
597
598const struct dt_index_features dt_quota_slv_features = {
599 .dif_flags = DT_IND_UPDATE,
600
601 .dif_keysize_min = sizeof(__u64),
602 .dif_keysize_max = sizeof(__u64),
603 .dif_recsize_min = sizeof(struct lquota_slv_rec),
604 .dif_recsize_max = sizeof(struct lquota_slv_rec),
605 .dif_ptrsize = 4
606};
607EXPORT_SYMBOL(dt_quota_slv_features);
608
609
610
611static inline const struct dt_index_features *dt_index_feat_select(__u64 seq,
612 __u32 mode)
613{
614 if (seq == FID_SEQ_QUOTA_GLB) {
615
616 if (!S_ISREG(mode))
617
618 return ERR_PTR(-ENOENT);
619 return &dt_quota_glb_features;
620 } else if (seq == FID_SEQ_QUOTA) {
621
622 if (!S_ISREG(mode))
623
624 return ERR_PTR(-ENOENT);
625 return &dt_quota_slv_features;
626 } else if (seq >= FID_SEQ_NORMAL) {
627
628
629 if (!S_ISDIR(mode))
630
631 return ERR_PTR(-ENOTDIR);
632 return &dt_directory_features;
633 }
634
635 return ERR_PTR(-EOPNOTSUPP);
636}
637
638
639
640
641
642
643
644
645
646
647
648
649
650static int dt_index_page_build(const struct lu_env *env, union lu_page *lp,
651 int nob, const struct dt_it_ops *iops,
652 struct dt_it *it, __u32 attr, void *arg)
653{
654 struct idx_info *ii = (struct idx_info *)arg;
655 struct lu_idxpage *lip = &lp->lp_idx;
656 char *entry;
657 int rc, size;
658
659
660 LASSERT((ii->ii_flags & II_FL_VARKEY) == 0);
661 LASSERT((ii->ii_flags & II_FL_VARREC) == 0);
662
663
664 memset(lip, 0, LIP_HDR_SIZE);
665 lip->lip_magic = LIP_MAGIC;
666 nob -= LIP_HDR_SIZE;
667
668
669 size = ii->ii_recsize + ii->ii_keysize;
670 if ((ii->ii_flags & II_FL_NOHASH) == 0)
671
672 size += sizeof(__u64);
673
674 entry = lip->lip_entries;
675 do {
676 char *tmp_entry = entry;
677 struct dt_key *key;
678 __u64 hash;
679
680
681 hash = iops->store(env, it);
682 ii->ii_hash_end = hash;
683
684 if (OBD_FAIL_CHECK(OBD_FAIL_OBD_IDX_READ_BREAK)) {
685 if (lip->lip_nr != 0) {
686 rc = 0;
687 goto out;
688 }
689 }
690
691 if (nob < size) {
692 if (lip->lip_nr == 0)
693 rc = -EINVAL;
694 else
695 rc = 0;
696 goto out;
697 }
698
699 if ((ii->ii_flags & II_FL_NOHASH) == 0) {
700
701
702 memcpy(tmp_entry, &hash, sizeof(hash));
703 tmp_entry += sizeof(hash);
704 }
705
706
707 LASSERT(iops->key_size(env, it) == ii->ii_keysize);
708 key = iops->key(env, it);
709 memcpy(tmp_entry, key, ii->ii_keysize);
710 tmp_entry += ii->ii_keysize;
711
712
713 rc = iops->rec(env, it, (struct dt_rec *)tmp_entry, attr);
714 if (rc != -ESTALE) {
715 if (rc != 0)
716 goto out;
717
718
719 lip->lip_nr++;
720 if (unlikely(lip->lip_nr == 1 && ii->ii_count == 0))
721 ii->ii_hash_start = hash;
722 entry = tmp_entry + ii->ii_recsize;
723 nob -= size;
724 }
725
726
727 do {
728 rc = iops->next(env, it);
729 } while (rc == -ESTALE);
730
731 } while (rc == 0);
732
733 goto out;
734out:
735 if (rc >= 0 && lip->lip_nr > 0)
736
737 ii->ii_count++;
738 if (rc > 0)
739
740 ii->ii_hash_end = II_END_OFF;
741 return rc;
742}
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757int dt_index_walk(const struct lu_env *env, struct dt_object *obj,
758 const struct lu_rdpg *rdpg, dt_index_page_build_t filler,
759 void *arg)
760{
761 struct dt_it *it;
762 const struct dt_it_ops *iops;
763 unsigned int pageidx, nob, nlupgs = 0;
764 int rc;
765
766 LASSERT(rdpg->rp_pages != NULL);
767 LASSERT(obj->do_index_ops != NULL);
768
769 nob = rdpg->rp_count;
770 if (nob <= 0)
771 return -EFAULT;
772
773
774 iops = &obj->do_index_ops->dio_it;
775 LASSERT(iops != NULL);
776 it = iops->init(env, obj, rdpg->rp_attrs, BYPASS_CAPA);
777 if (IS_ERR(it))
778 return PTR_ERR(it);
779
780 rc = iops->load(env, it, rdpg->rp_hash);
781 if (rc == 0) {
782
783
784
785
786
787
788
789
790
791
792 rc = iops->next(env, it);
793 } else if (rc > 0) {
794 rc = 0;
795 }
796
797
798
799
800
801
802
803
804 for (pageidx = 0; rc == 0 && nob > 0; pageidx++) {
805 union lu_page *lp;
806 int i;
807
808 LASSERT(pageidx < rdpg->rp_npages);
809 lp = kmap(rdpg->rp_pages[pageidx]);
810
811
812 for (i = 0; i < LU_PAGE_COUNT; i++, lp++, nob -= LU_PAGE_SIZE) {
813 rc = filler(env, lp, min_t(int, nob, LU_PAGE_SIZE),
814 iops, it, rdpg->rp_attrs, arg);
815 if (rc < 0)
816 break;
817
818 nlupgs++;
819 if (rc > 0)
820
821 break;
822 }
823 kunmap(rdpg->rp_pages[i]);
824 }
825
826 iops->put(env, it);
827 iops->fini(env, it);
828
829 if (rc >= 0)
830 rc = min_t(unsigned int, nlupgs * LU_PAGE_SIZE, rdpg->rp_count);
831
832 return rc;
833}
834EXPORT_SYMBOL(dt_index_walk);
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850int dt_index_read(const struct lu_env *env, struct dt_device *dev,
851 struct idx_info *ii, const struct lu_rdpg *rdpg)
852{
853 const struct dt_index_features *feat;
854 struct dt_object *obj;
855 int rc;
856
857
858
859 if (rdpg->rp_count <= 0 && (rdpg->rp_count & (LU_PAGE_SIZE - 1)) != 0)
860 return -EFAULT;
861
862 if (fid_seq(&ii->ii_fid) >= FID_SEQ_NORMAL)
863
864
865 return -EOPNOTSUPP;
866
867 if (!fid_is_quota(&ii->ii_fid))
868
869 return -EPERM;
870
871
872 obj = dt_locate(env, dev, &ii->ii_fid);
873 if (IS_ERR(obj))
874 return PTR_ERR(obj);
875 if (dt_object_exists(obj) == 0) {
876 rc = -ENOENT;
877 goto out;
878 }
879
880
881 feat = dt_index_feat_select(fid_seq(&ii->ii_fid),
882 lu_object_attr(&obj->do_lu));
883 if (IS_ERR(feat)) {
884 rc = PTR_ERR(feat);
885 goto out;
886 }
887
888
889 if (obj->do_index_ops == NULL) {
890 rc = obj->do_ops->do_index_try(env, obj, feat);
891 if (rc)
892 goto out;
893 }
894
895
896 ii->ii_flags &= II_FL_NOHASH;
897
898 ii->ii_keysize = feat->dif_keysize_max;
899 if ((feat->dif_flags & DT_IND_VARKEY) != 0) {
900
901 ii->ii_flags |= II_FL_VARKEY;
902
903 rc = -EOPNOTSUPP;
904 goto out;
905 }
906
907 ii->ii_recsize = feat->dif_recsize_max;
908 if ((feat->dif_flags & DT_IND_VARREC) != 0) {
909
910 ii->ii_flags |= II_FL_VARREC;
911
912 rc = -EOPNOTSUPP;
913 goto out;
914 }
915
916 if ((feat->dif_flags & DT_IND_NONUNQ) != 0)
917
918 ii->ii_flags |= II_FL_NONUNQ;
919
920 dt_read_lock(env, obj, 0);
921
922 ii->ii_version = dt_version_get(env, obj);
923
924
925 rc = dt_index_walk(env, obj, rdpg, dt_index_page_build, ii);
926 dt_read_unlock(env, obj);
927
928 if (rc == 0) {
929
930 LASSERT(ii->ii_count == 0);
931 ii->ii_hash_end = II_END_OFF;
932 }
933
934 goto out;
935out:
936 lu_object_put(env, &obj->do_lu);
937 return rc;
938}
939EXPORT_SYMBOL(dt_index_read);
940
941int lprocfs_dt_rd_blksize(char *page, char **start, off_t off,
942 int count, int *eof, void *data)
943{
944 struct dt_device *dt = data;
945 struct obd_statfs osfs;
946 int rc = dt_statfs(NULL, dt, &osfs);
947
948 if (rc == 0) {
949 *eof = 1;
950 rc = snprintf(page, count, "%u\n",
951 (unsigned) osfs.os_bsize);
952 }
953
954 return rc;
955}
956EXPORT_SYMBOL(lprocfs_dt_rd_blksize);
957
958int lprocfs_dt_rd_kbytestotal(char *page, char **start, off_t off,
959 int count, int *eof, void *data)
960{
961 struct dt_device *dt = data;
962 struct obd_statfs osfs;
963 int rc = dt_statfs(NULL, dt, &osfs);
964
965 if (rc == 0) {
966 __u32 blk_size = osfs.os_bsize >> 10;
967 __u64 result = osfs.os_blocks;
968
969 while (blk_size >>= 1)
970 result <<= 1;
971
972 *eof = 1;
973 rc = snprintf(page, count, "%llu\n", result);
974 }
975
976 return rc;
977}
978EXPORT_SYMBOL(lprocfs_dt_rd_kbytestotal);
979
980int lprocfs_dt_rd_kbytesfree(char *page, char **start, off_t off,
981 int count, int *eof, void *data)
982{
983 struct dt_device *dt = data;
984 struct obd_statfs osfs;
985 int rc = dt_statfs(NULL, dt, &osfs);
986
987 if (rc == 0) {
988 __u32 blk_size = osfs.os_bsize >> 10;
989 __u64 result = osfs.os_bfree;
990
991 while (blk_size >>= 1)
992 result <<= 1;
993
994 *eof = 1;
995 rc = snprintf(page, count, "%llu\n", result);
996 }
997
998 return rc;
999}
1000EXPORT_SYMBOL(lprocfs_dt_rd_kbytesfree);
1001
1002int lprocfs_dt_rd_kbytesavail(char *page, char **start, off_t off,
1003 int count, int *eof, void *data)
1004{
1005 struct dt_device *dt = data;
1006 struct obd_statfs osfs;
1007 int rc = dt_statfs(NULL, dt, &osfs);
1008
1009 if (rc == 0) {
1010 __u32 blk_size = osfs.os_bsize >> 10;
1011 __u64 result = osfs.os_bavail;
1012
1013 while (blk_size >>= 1)
1014 result <<= 1;
1015
1016 *eof = 1;
1017 rc = snprintf(page, count, "%llu\n", result);
1018 }
1019
1020 return rc;
1021}
1022EXPORT_SYMBOL(lprocfs_dt_rd_kbytesavail);
1023
1024int lprocfs_dt_rd_filestotal(char *page, char **start, off_t off,
1025 int count, int *eof, void *data)
1026{
1027 struct dt_device *dt = data;
1028 struct obd_statfs osfs;
1029 int rc = dt_statfs(NULL, dt, &osfs);
1030
1031 if (rc == 0) {
1032 *eof = 1;
1033 rc = snprintf(page, count, "%llu\n", osfs.os_files);
1034 }
1035
1036 return rc;
1037}
1038EXPORT_SYMBOL(lprocfs_dt_rd_filestotal);
1039
1040int lprocfs_dt_rd_filesfree(char *page, char **start, off_t off,
1041 int count, int *eof, void *data)
1042{
1043 struct dt_device *dt = data;
1044 struct obd_statfs osfs;
1045 int rc = dt_statfs(NULL, dt, &osfs);
1046
1047 if (rc == 0) {
1048 *eof = 1;
1049 rc = snprintf(page, count, "%llu\n", osfs.os_ffree);
1050 }
1051
1052 return rc;
1053}
1054EXPORT_SYMBOL(lprocfs_dt_rd_filesfree);
1055