]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - db/inode.c
cmd/xfs/bmap/Makefile 1.8 Renamed to cmd/xfsprogs/bmap/Makefile
[thirdparty/xfsprogs-dev.git] / db / inode.c
1 /*
2 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 *
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like. Any license provided herein, whether implied or
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc., 59
21 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
22 *
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
25 *
26 * http://www.sgi.com
27 *
28 * For further information regarding this notice, see:
29 *
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
31 */
32
33 #include <libxfs.h>
34 #include "command.h"
35 #include "data.h"
36 #include "type.h"
37 #include "faddr.h"
38 #include "fprint.h"
39 #include "field.h"
40 #include "inode.h"
41 #include "io.h"
42 #include "print.h"
43 #include "block.h"
44 #include "bit.h"
45 #include "output.h"
46 #include "mount.h"
47
48 static int inode_a_bmbt_count(void *obj, int startoff);
49 static int inode_a_bmx_count(void *obj, int startoff);
50 static int inode_a_count(void *obj, int startoff);
51 static int inode_a_offset(void *obj, int startoff, int idx);
52 static int inode_a_sfattr_count(void *obj, int startoff);
53 static int inode_core_nlinkv2_count(void *obj, int startoff);
54 static int inode_core_onlink_count(void *obj, int startoff);
55 static int inode_core_projid_count(void *obj, int startoff);
56 static int inode_core_nlinkv1_count(void *obj, int startoff);
57 static int inode_f(int argc, char **argv);
58 static int inode_u_bmbt_count(void *obj, int startoff);
59 static int inode_u_bmx_count(void *obj, int startoff);
60 static int inode_u_c_count(void *obj, int startoff);
61 static int inode_u_dev_count(void *obj, int startoff);
62 static int inode_u_muuid_count(void *obj, int startoff);
63 static int inode_u_sfdir_count(void *obj, int startoff);
64 static int inode_u_sfdir2_count(void *obj, int startoff);
65 static int inode_u_symlink_count(void *obj, int startoff);
66
67 static const cmdinfo_t inode_cmd =
68 { "inode", NULL, inode_f, 0, 1, 1, "[inode#]",
69 "set current inode", NULL };
70
71 const field_t inode_hfld[] = {
72 { "", FLDT_INODE, OI(0), C1, 0, TYP_NONE },
73 { NULL }
74 };
75
76 #define OFF(f) bitize(offsetof(xfs_dinode_t, di_ ## f))
77 const field_t inode_flds[] = {
78 { "core", FLDT_DINODE_CORE, OI(OFF(core)), C1, 0, TYP_NONE },
79 { "next_unlinked", FLDT_AGINO, OI(OFF(next_unlinked)), C1, 0,
80 TYP_INODE },
81 { "u", FLDT_DINODE_U, OI(OFF(u)), C1, 0, TYP_NONE },
82 { "a", FLDT_DINODE_A, inode_a_offset, inode_a_count,
83 FLD_COUNT|FLD_OFFSET, TYP_NONE },
84 { NULL }
85 };
86
87 #define COFF(f) bitize(offsetof(xfs_dinode_core_t, di_ ## f))
88 const field_t inode_core_flds[] = {
89 { "magic", FLDT_UINT16X, OI(COFF(magic)), C1, 0, TYP_NONE },
90 { "mode", FLDT_UINT16O, OI(COFF(mode)), C1, 0, TYP_NONE },
91 { "version", FLDT_INT8D, OI(COFF(version)), C1, 0, TYP_NONE },
92 { "format", FLDT_DINODE_FMT, OI(COFF(format)), C1, 0, TYP_NONE },
93 { "nlinkv1", FLDT_UINT16D, OI(COFF(onlink)), inode_core_nlinkv1_count,
94 FLD_COUNT, TYP_NONE },
95 { "nlinkv2", FLDT_UINT32D, OI(COFF(nlink)), inode_core_nlinkv2_count,
96 FLD_COUNT, TYP_NONE },
97 { "onlink", FLDT_UINT16D, OI(COFF(onlink)), inode_core_onlink_count,
98 FLD_COUNT, TYP_NONE },
99 { "projid", FLDT_UINT16D, OI(COFF(projid)), inode_core_projid_count,
100 FLD_COUNT, TYP_NONE },
101 { "uid", FLDT_UINT32D, OI(COFF(uid)), C1, 0, TYP_NONE },
102 { "gid", FLDT_UINT32D, OI(COFF(gid)), C1, 0, TYP_NONE },
103 { "atime", FLDT_TIMESTAMP, OI(COFF(atime)), C1, 0, TYP_NONE },
104 { "mtime", FLDT_TIMESTAMP, OI(COFF(mtime)), C1, 0, TYP_NONE },
105 { "ctime", FLDT_TIMESTAMP, OI(COFF(ctime)), C1, 0, TYP_NONE },
106 { "size", FLDT_FSIZE, OI(COFF(size)), C1, 0, TYP_NONE },
107 { "nblocks", FLDT_DRFSBNO, OI(COFF(nblocks)), C1, 0, TYP_NONE },
108 { "extsize", FLDT_EXTLEN, OI(COFF(extsize)), C1, 0, TYP_NONE },
109 { "nextents", FLDT_EXTNUM, OI(COFF(nextents)), C1, 0, TYP_NONE },
110 { "naextents", FLDT_AEXTNUM, OI(COFF(anextents)), C1, 0, TYP_NONE },
111 { "forkoff", FLDT_UINT8D, OI(COFF(forkoff)), C1, 0, TYP_NONE },
112 { "aformat", FLDT_DINODE_FMT, OI(COFF(aformat)), C1, 0, TYP_NONE },
113 { "dmevmask", FLDT_UINT32X, OI(COFF(dmevmask)), C1, 0, TYP_NONE },
114 { "dmstate", FLDT_UINT16D, OI(COFF(dmstate)), C1, 0, TYP_NONE },
115 { "flags", FLDT_UINT16X, OI(COFF(flags)), C1, FLD_SKIPALL, TYP_NONE },
116 { "newrtbm", FLDT_UINT1,
117 OI(COFF(flags) + bitsz(__uint16_t) - XFS_DIFLAG_NEWRTBM_BIT - 1), C1,
118 0, TYP_NONE },
119 { "prealloc", FLDT_UINT1,
120 OI(COFF(flags) + bitsz(__uint16_t) - XFS_DIFLAG_PREALLOC_BIT - 1), C1,
121 0, TYP_NONE },
122 { "realtime", FLDT_UINT1,
123 OI(COFF(flags) + bitsz(__uint16_t) - XFS_DIFLAG_REALTIME_BIT - 1), C1,
124 0, TYP_NONE },
125 { "gen", FLDT_UINT32D, OI(COFF(gen)), C1, 0, TYP_NONE },
126 { NULL }
127 };
128
129 #define TOFF(f) bitize(offsetof(xfs_timestamp_t, t_ ## f))
130 const field_t timestamp_flds[] = {
131 { "sec", FLDT_TIME, OI(TOFF(sec)), C1, 0, TYP_NONE },
132 { "nsec", FLDT_NSEC, OI(TOFF(nsec)), C1, 0, TYP_NONE },
133 { NULL }
134 };
135
136 const field_t inode_u_flds[] = {
137 { "bmbt", FLDT_BMROOTD, 0, inode_u_bmbt_count, FLD_COUNT, TYP_NONE },
138 { "bmx", FLDT_BMAPBTDREC, 0, inode_u_bmx_count, FLD_ARRAY|FLD_COUNT,
139 TYP_NONE },
140 { "c", FLDT_CHARNS, 0, inode_u_c_count, FLD_COUNT, TYP_NONE },
141 { "dev", FLDT_DEV, 0, inode_u_dev_count, FLD_COUNT, TYP_NONE },
142 { "muuid", FLDT_UUID, 0, inode_u_muuid_count, FLD_COUNT, TYP_NONE },
143 { "sfdir", FLDT_DIRSHORT, 0, inode_u_sfdir_count, FLD_COUNT, TYP_NONE },
144 { "sfdir2", FLDT_DIR2SF, 0, inode_u_sfdir2_count, FLD_COUNT, TYP_NONE },
145 { "symlink", FLDT_CHARNS, 0, inode_u_symlink_count, FLD_COUNT,
146 TYP_NONE },
147 { NULL }
148 };
149
150 const field_t inode_a_flds[] = {
151 { "bmbt", FLDT_BMROOTA, 0, inode_a_bmbt_count, FLD_COUNT, TYP_NONE },
152 { "bmx", FLDT_BMAPBTAREC, 0, inode_a_bmx_count, FLD_ARRAY|FLD_COUNT,
153 TYP_NONE },
154 { "sfattr", FLDT_ATTRSHORT, 0, inode_a_sfattr_count, FLD_COUNT,
155 TYP_NONE },
156 { NULL }
157 };
158
159 static const char *dinode_fmt_name[] =
160 { "dev", "local", "extents", "btree", "uuid" };
161 static const int dinode_fmt_name_size =
162 sizeof(dinode_fmt_name) / sizeof(dinode_fmt_name[0]);
163
164 /*ARGSUSED*/
165 int
166 fp_dinode_fmt(
167 void *obj,
168 int bit,
169 int count,
170 char *fmtstr,
171 int size,
172 int arg,
173 int base,
174 int array)
175 {
176 int bitpos;
177 xfs_dinode_fmt_t f;
178 int i;
179
180 for (i = 0, bitpos = bit; i < count; i++, bitpos += size) {
181 f = (xfs_dinode_fmt_t)getbitval(obj, bitpos, size, BVSIGNED);
182 if (array)
183 dbprintf("%d:", i + base);
184 if (f < 0 || f >= dinode_fmt_name_size)
185 dbprintf("%d", (int)f);
186 else
187 dbprintf("%d (%s)", (int)f, dinode_fmt_name[(int)f]);
188 if (i < count - 1)
189 dbprintf(" ");
190 }
191 return 1;
192 }
193
194 static int
195 inode_a_bmbt_count(
196 void *obj,
197 int startoff)
198 {
199 xfs_dinode_t *dip;
200
201 ASSERT(bitoffs(startoff) == 0);
202 ASSERT(obj == iocur_top->data);
203 dip = obj;
204 if (!XFS_DFORK_Q_ARCH(dip, ARCH_CONVERT))
205 return 0;
206 ASSERT((char *)XFS_DFORK_APTR_ARCH(dip, ARCH_CONVERT) - (char *)dip == byteize(startoff));
207 return INT_GET(dip->di_core.di_aformat, ARCH_CONVERT) == XFS_DINODE_FMT_BTREE;
208 }
209
210 static int
211 inode_a_bmx_count(
212 void *obj,
213 int startoff)
214 {
215 xfs_dinode_t *dip;
216
217 ASSERT(bitoffs(startoff) == 0);
218 ASSERT(obj == iocur_top->data);
219 dip = obj;
220 if (!XFS_DFORK_Q_ARCH(dip, ARCH_CONVERT))
221 return 0;
222 ASSERT((char *)XFS_DFORK_APTR_ARCH(dip, ARCH_CONVERT) - (char *)dip == byteize(startoff));
223 return INT_GET(dip->di_core.di_aformat, ARCH_CONVERT) == XFS_DINODE_FMT_EXTENTS ?
224 INT_GET(dip->di_core.di_anextents, ARCH_CONVERT) : 0;
225 }
226
227 static int
228 inode_a_count(
229 void *obj,
230 int startoff)
231 {
232 xfs_dinode_t *dip;
233
234 ASSERT(startoff == 0);
235 dip = obj;
236 return XFS_DFORK_Q_ARCH(dip, ARCH_CONVERT);
237 }
238
239 static int
240 inode_a_offset(
241 void *obj,
242 int startoff,
243 int idx)
244 {
245 xfs_dinode_t *dip;
246
247 ASSERT(startoff == 0);
248 ASSERT(idx == 0);
249 dip = obj;
250 ASSERT(XFS_DFORK_Q_ARCH(dip, ARCH_CONVERT));
251 return bitize((int)((char *)XFS_DFORK_APTR_ARCH(dip, ARCH_CONVERT) - (char *)dip));
252 }
253
254 static int
255 inode_a_sfattr_count(
256 void *obj,
257 int startoff)
258 {
259 xfs_dinode_t *dip;
260
261 ASSERT(bitoffs(startoff) == 0);
262 ASSERT(obj == iocur_top->data);
263 dip = obj;
264 if (!XFS_DFORK_Q_ARCH(dip, ARCH_CONVERT))
265 return 0;
266 ASSERT((char *)XFS_DFORK_APTR_ARCH(dip, ARCH_CONVERT) - (char *)dip == byteize(startoff));
267 return INT_GET(dip->di_core.di_aformat, ARCH_CONVERT) == XFS_DINODE_FMT_LOCAL;
268 }
269
270 int
271 inode_a_size(
272 void *obj,
273 int startoff,
274 int idx)
275 {
276 xfs_attr_shortform_t *asf;
277 xfs_dinode_t *dip;
278
279 ASSERT(startoff == 0);
280 ASSERT(idx == 0);
281 dip = obj;
282 switch (INT_GET(dip->di_core.di_aformat, ARCH_CONVERT)) {
283 case XFS_DINODE_FMT_LOCAL:
284 asf = (xfs_attr_shortform_t *)XFS_DFORK_APTR_ARCH(dip, ARCH_CONVERT);
285 return bitize((int)asf->hdr.totsize);
286 case XFS_DINODE_FMT_EXTENTS:
287 return (int)(INT_GET(dip->di_core.di_anextents, ARCH_CONVERT) * bitsz(xfs_bmbt_rec_t));
288 case XFS_DINODE_FMT_BTREE:
289 return bitize((int)XFS_DFORK_ASIZE_ARCH(dip, mp, ARCH_CONVERT));
290 default:
291 return 0;
292 }
293 }
294
295 static int
296 inode_core_nlinkv1_count(
297 void *obj,
298 int startoff)
299 {
300 xfs_dinode_core_t *dic;
301
302 ASSERT(startoff == 0);
303 ASSERT(obj == iocur_top->data);
304 dic = obj;
305 return dic->di_version == XFS_DINODE_VERSION_1;
306 }
307
308 static int
309 inode_core_nlinkv2_count(
310 void *obj,
311 int startoff)
312 {
313 xfs_dinode_core_t *dic;
314
315 ASSERT(startoff == 0);
316 ASSERT(obj == iocur_top->data);
317 dic = obj;
318 return dic->di_version == XFS_DINODE_VERSION_2;
319 }
320
321 static int
322 inode_core_onlink_count(
323 void *obj,
324 int startoff)
325 {
326 xfs_dinode_core_t *dic;
327
328 ASSERT(startoff == 0);
329 ASSERT(obj == iocur_top->data);
330 dic = obj;
331 return dic->di_version == XFS_DINODE_VERSION_2;
332 }
333
334 static int
335 inode_core_projid_count(
336 void *obj,
337 int startoff)
338 {
339 xfs_dinode_core_t *dic;
340
341 ASSERT(startoff == 0);
342 ASSERT(obj == iocur_top->data);
343 dic = obj;
344 return dic->di_version == XFS_DINODE_VERSION_2;
345 }
346
347 static int
348 inode_f(
349 int argc,
350 char **argv)
351 {
352 xfs_ino_t ino;
353 char *p;
354
355 if (argc > 1) {
356 ino = strtoull(argv[1], &p, 0);
357 if (*p != '\0') {
358 dbprintf("bad value for inode number %s\n", argv[1]);
359 return 0;
360 }
361 set_cur_inode(ino);
362 } else if (iocur_top->ino == NULLFSINO)
363 dbprintf("no current inode\n");
364 else
365 dbprintf("current inode number is %lld\n", iocur_top->ino);
366 return 0;
367 }
368
369 void
370 inode_init(void)
371 {
372 add_command(&inode_cmd);
373 }
374
375 typnm_t
376 inode_next_type(void)
377 {
378 switch (iocur_top->mode & IFMT) {
379 case IFDIR:
380 return XFS_DIR_IS_V2(mp) ? TYP_DIR2 : TYP_DIR;
381 case IFLNK:
382 return TYP_SYMLINK;
383 case IFREG:
384 if (iocur_top->ino == mp->m_sb.sb_rbmino)
385 return TYP_RTBITMAP;
386 else if (iocur_top->ino == mp->m_sb.sb_rsumino)
387 return TYP_RTSUMMARY;
388 else if (iocur_top->ino == mp->m_sb.sb_uquotino ||
389 iocur_top->ino == mp->m_sb.sb_pquotino)
390 return TYP_DQBLK;
391 else
392 return TYP_DATA;
393 default:
394 return TYP_NONE;
395 }
396 }
397
398 int
399 inode_size(
400 void *obj,
401 int startoff,
402 int idx)
403 {
404 return bitize(mp->m_sb.sb_inodesize);
405 }
406
407 static int
408 inode_u_bmbt_count(
409 void *obj,
410 int startoff)
411 {
412 xfs_dinode_t *dip;
413
414 ASSERT(bitoffs(startoff) == 0);
415 ASSERT(obj == iocur_top->data);
416 dip = obj;
417 ASSERT((char *)&dip->di_u - (char *)dip == byteize(startoff));
418 return INT_GET(dip->di_core.di_format, ARCH_CONVERT) == XFS_DINODE_FMT_BTREE;
419 }
420
421 static int
422 inode_u_bmx_count(
423 void *obj,
424 int startoff)
425 {
426 xfs_dinode_t *dip;
427
428 ASSERT(bitoffs(startoff) == 0);
429 ASSERT(obj == iocur_top->data);
430 dip = obj;
431 ASSERT((char *)&dip->di_u - (char *)dip == byteize(startoff));
432 return INT_GET(dip->di_core.di_format, ARCH_CONVERT) == XFS_DINODE_FMT_EXTENTS ?
433 INT_GET(dip->di_core.di_nextents, ARCH_CONVERT) : 0;
434 }
435
436 static int
437 inode_u_c_count(
438 void *obj,
439 int startoff)
440 {
441 xfs_dinode_t *dip;
442
443 ASSERT(bitoffs(startoff) == 0);
444 ASSERT(obj == iocur_top->data);
445 dip = obj;
446 ASSERT((char *)&dip->di_u - (char *)dip == byteize(startoff));
447 return INT_GET(dip->di_core.di_format, ARCH_CONVERT) == XFS_DINODE_FMT_LOCAL &&
448 (INT_GET(dip->di_core.di_mode, ARCH_CONVERT) & IFMT) == IFREG ?
449 (int)INT_GET(dip->di_core.di_size, ARCH_CONVERT) : 0;
450 }
451
452 static int
453 inode_u_dev_count(
454 void *obj,
455 int startoff)
456 {
457 xfs_dinode_t *dip;
458
459 ASSERT(bitoffs(startoff) == 0);
460 ASSERT(obj == iocur_top->data);
461 dip = obj;
462 ASSERT((char *)&dip->di_u - (char *)dip == byteize(startoff));
463 return INT_GET(dip->di_core.di_format, ARCH_CONVERT) == XFS_DINODE_FMT_DEV;
464 }
465
466 static int
467 inode_u_muuid_count(
468 void *obj,
469 int startoff)
470 {
471 xfs_dinode_t *dip;
472
473 ASSERT(bitoffs(startoff) == 0);
474 ASSERT(obj == iocur_top->data);
475 dip = obj;
476 ASSERT((char *)&dip->di_u - (char *)dip == byteize(startoff));
477 return INT_GET(dip->di_core.di_format, ARCH_CONVERT) == XFS_DINODE_FMT_UUID;
478 }
479
480 static int
481 inode_u_sfdir_count(
482 void *obj,
483 int startoff)
484 {
485 xfs_dinode_t *dip;
486
487 ASSERT(bitoffs(startoff) == 0);
488 ASSERT(obj == iocur_top->data);
489 dip = obj;
490 ASSERT((char *)&dip->di_u - (char *)dip == byteize(startoff));
491 return INT_GET(dip->di_core.di_format, ARCH_CONVERT) == XFS_DINODE_FMT_LOCAL &&
492 (INT_GET(dip->di_core.di_mode, ARCH_CONVERT) & IFMT) == IFDIR
493 && XFS_DIR_IS_V1(mp);
494 }
495
496 static int
497 inode_u_sfdir2_count(
498 void *obj,
499 int startoff)
500 {
501 xfs_dinode_t *dip;
502
503 ASSERT(bitoffs(startoff) == 0);
504 ASSERT(obj == iocur_top->data);
505 dip = obj;
506 ASSERT((char *)&dip->di_u - (char *)dip == byteize(startoff));
507 return INT_GET(dip->di_core.di_format, ARCH_CONVERT) == XFS_DINODE_FMT_LOCAL &&
508 (INT_GET(dip->di_core.di_mode, ARCH_CONVERT) & IFMT) == IFDIR &&
509 XFS_DIR_IS_V2(mp);
510 }
511
512 int
513 inode_u_size(
514 void *obj,
515 int startoff,
516 int idx)
517 {
518 xfs_dinode_t *dip;
519
520 ASSERT(startoff == 0);
521 ASSERT(idx == 0);
522 dip = obj;
523 switch (INT_GET(dip->di_core.di_format, ARCH_CONVERT)) {
524 case XFS_DINODE_FMT_DEV:
525 return bitsz(xfs_dev_t);
526 case XFS_DINODE_FMT_LOCAL:
527 return bitize((int)INT_GET(dip->di_core.di_size, ARCH_CONVERT));
528 case XFS_DINODE_FMT_EXTENTS:
529 return (int)(INT_GET(dip->di_core.di_nextents, ARCH_CONVERT) * bitsz(xfs_bmbt_rec_t));
530 case XFS_DINODE_FMT_BTREE:
531 return bitize((int)XFS_DFORK_DSIZE_ARCH(dip, mp, ARCH_CONVERT));
532 case XFS_DINODE_FMT_UUID:
533 return bitsz(uuid_t);
534 default:
535 return 0;
536 }
537 }
538
539 static int
540 inode_u_symlink_count(
541 void *obj,
542 int startoff)
543 {
544 xfs_dinode_t *dip;
545
546 ASSERT(bitoffs(startoff) == 0);
547 ASSERT(obj == iocur_top->data);
548 dip = obj;
549 ASSERT((char *)&dip->di_u - (char *)dip == byteize(startoff));
550 return INT_GET(dip->di_core.di_format, ARCH_CONVERT) == XFS_DINODE_FMT_LOCAL &&
551 (INT_GET(dip->di_core.di_mode, ARCH_CONVERT) & IFMT) == IFLNK ?
552 (int)INT_GET(dip->di_core.di_size, ARCH_CONVERT) : 0;
553 }
554
555 void
556 set_cur_inode(
557 xfs_ino_t ino)
558 {
559 xfs_agblock_t agbno;
560 xfs_agino_t agino;
561 xfs_agnumber_t agno;
562 xfs_dinode_t *dip;
563 int offset;
564
565 agno = XFS_INO_TO_AGNO(mp, ino);
566 agino = XFS_INO_TO_AGINO(mp, ino);
567 agbno = XFS_AGINO_TO_AGBNO(mp, agino);
568 offset = XFS_AGINO_TO_OFFSET(mp, agino);
569 if (agno >= mp->m_sb.sb_agcount || agbno >= mp->m_sb.sb_agblocks ||
570 offset >= mp->m_sb.sb_inopblock ||
571 XFS_AGINO_TO_INO(mp, agno, agino) != ino) {
572 dbprintf("bad inode number %lld\n", ino);
573 return;
574 }
575 cur_agno = agno;
576 /*
577 * First set_cur to the block with the inode
578 * then use off_cur to get the right part of the buffer.
579 */
580 ASSERT(typtab[TYP_INODE].typnm == TYP_INODE);
581
582 /* ingore ring update here, do it explicitly below */
583 set_cur(&typtab[TYP_INODE], XFS_AGB_TO_DADDR(mp, agno, agbno),
584 blkbb, DB_RING_IGN, NULL);
585 off_cur(offset << mp->m_sb.sb_inodelog, mp->m_sb.sb_inodesize);
586 dip = iocur_top->data;
587 iocur_top->ino = ino;
588 iocur_top->mode = INT_GET(dip->di_core.di_mode, ARCH_CONVERT);
589 if ((iocur_top->mode & IFMT) == IFDIR)
590 iocur_top->dirino = ino;
591
592 /* track updated info in ring */
593 ring_add();
594 }