]>
Commit | Line | Data |
---|---|---|
2bd0ea18 | 1 | /* |
da23017d NS |
2 | * Copyright (c) 2000-2005 Silicon Graphics, Inc. |
3 | * All Rights Reserved. | |
dfc130f3 | 4 | * |
da23017d NS |
5 | * This program is free software; you can redistribute it and/or |
6 | * modify it under the terms of the GNU General Public License as | |
2bd0ea18 | 7 | * published by the Free Software Foundation. |
dfc130f3 | 8 | * |
da23017d NS |
9 | * This program is distributed in the hope that it would be useful, |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
dfc130f3 | 13 | * |
da23017d NS |
14 | * You should have received a copy of the GNU General Public License |
15 | * along with this program; if not, write the Free Software Foundation, | |
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
2bd0ea18 NS |
17 | */ |
18 | ||
6b803e5a | 19 | #include "libxfs.h" |
2bd0ea18 | 20 | #include "command.h" |
2bd0ea18 NS |
21 | #include "type.h" |
22 | #include "faddr.h" | |
23 | #include "fprint.h" | |
24 | #include "field.h" | |
25 | #include "inode.h" | |
26 | #include "io.h" | |
27 | #include "print.h" | |
28 | #include "block.h" | |
29 | #include "bit.h" | |
30 | #include "output.h" | |
4ca431fc | 31 | #include "init.h" |
2bd0ea18 NS |
32 | |
33 | static int inode_a_bmbt_count(void *obj, int startoff); | |
34 | static int inode_a_bmx_count(void *obj, int startoff); | |
35 | static int inode_a_count(void *obj, int startoff); | |
36 | static int inode_a_offset(void *obj, int startoff, int idx); | |
37 | static int inode_a_sfattr_count(void *obj, int startoff); | |
38 | static int inode_core_nlinkv2_count(void *obj, int startoff); | |
39 | static int inode_core_onlink_count(void *obj, int startoff); | |
40 | static int inode_core_projid_count(void *obj, int startoff); | |
41 | static int inode_core_nlinkv1_count(void *obj, int startoff); | |
42 | static int inode_f(int argc, char **argv); | |
56b2de80 | 43 | static int inode_u_offset(void *obj, int startoff, int idx); |
2bd0ea18 NS |
44 | static int inode_u_bmbt_count(void *obj, int startoff); |
45 | static int inode_u_bmx_count(void *obj, int startoff); | |
46 | static int inode_u_c_count(void *obj, int startoff); | |
47 | static int inode_u_dev_count(void *obj, int startoff); | |
48 | static int inode_u_muuid_count(void *obj, int startoff); | |
2bd0ea18 | 49 | static int inode_u_sfdir2_count(void *obj, int startoff); |
3beed08e | 50 | static int inode_u_sfdir3_count(void *obj, int startoff); |
2bd0ea18 NS |
51 | static int inode_u_symlink_count(void *obj, int startoff); |
52 | ||
53 | static const cmdinfo_t inode_cmd = | |
54 | { "inode", NULL, inode_f, 0, 1, 1, "[inode#]", | |
55 | "set current inode", NULL }; | |
56 | ||
57 | const field_t inode_hfld[] = { | |
58 | { "", FLDT_INODE, OI(0), C1, 0, TYP_NONE }, | |
59 | { NULL } | |
60 | }; | |
c2907bd7 DC |
61 | const field_t inode_crc_hfld[] = { |
62 | { "", FLDT_INODE_CRC, OI(0), C1, 0, TYP_NONE }, | |
63 | { NULL } | |
64 | }; | |
2bd0ea18 | 65 | |
56b2de80 | 66 | /* XXX: fix this up! */ |
2bd0ea18 NS |
67 | #define OFF(f) bitize(offsetof(xfs_dinode_t, di_ ## f)) |
68 | const field_t inode_flds[] = { | |
56b2de80 | 69 | { "core", FLDT_DINODE_CORE, OI(OFF(magic)), C1, 0, TYP_NONE }, |
2bd0ea18 NS |
70 | { "next_unlinked", FLDT_AGINO, OI(OFF(next_unlinked)), C1, 0, |
71 | TYP_INODE }, | |
56b2de80 | 72 | { "u", FLDT_DINODE_U, inode_u_offset, C1, FLD_OFFSET, TYP_NONE }, |
2bd0ea18 NS |
73 | { "a", FLDT_DINODE_A, inode_a_offset, inode_a_count, |
74 | FLD_COUNT|FLD_OFFSET, TYP_NONE }, | |
75 | { NULL } | |
76 | }; | |
c2907bd7 DC |
77 | const field_t inode_crc_flds[] = { |
78 | { "core", FLDT_DINODE_CORE, OI(OFF(magic)), C1, 0, TYP_NONE }, | |
79 | { "next_unlinked", FLDT_AGINO, OI(OFF(next_unlinked)), C1, 0, | |
80 | TYP_INODE }, | |
81 | { "v3", FLDT_DINODE_V3, OI(OFF(magic)), C1, 0, TYP_NONE }, | |
3beed08e | 82 | { "u3", FLDT_DINODE_U, inode_u_offset, C1, FLD_OFFSET, TYP_NONE }, |
c2907bd7 DC |
83 | { "a", FLDT_DINODE_A, inode_a_offset, inode_a_count, |
84 | FLD_COUNT|FLD_OFFSET, TYP_NONE }, | |
85 | { NULL } | |
86 | }; | |
87 | ||
2bd0ea18 | 88 | |
56b2de80 | 89 | #define COFF(f) bitize(offsetof(xfs_dinode_t, di_ ## f)) |
2bd0ea18 NS |
90 | const field_t inode_core_flds[] = { |
91 | { "magic", FLDT_UINT16X, OI(COFF(magic)), C1, 0, TYP_NONE }, | |
92 | { "mode", FLDT_UINT16O, OI(COFF(mode)), C1, 0, TYP_NONE }, | |
93 | { "version", FLDT_INT8D, OI(COFF(version)), C1, 0, TYP_NONE }, | |
94 | { "format", FLDT_DINODE_FMT, OI(COFF(format)), C1, 0, TYP_NONE }, | |
95 | { "nlinkv1", FLDT_UINT16D, OI(COFF(onlink)), inode_core_nlinkv1_count, | |
96 | FLD_COUNT, TYP_NONE }, | |
97 | { "nlinkv2", FLDT_UINT32D, OI(COFF(nlink)), inode_core_nlinkv2_count, | |
98 | FLD_COUNT, TYP_NONE }, | |
99 | { "onlink", FLDT_UINT16D, OI(COFF(onlink)), inode_core_onlink_count, | |
100 | FLD_COUNT, TYP_NONE }, | |
22bc10ed AM |
101 | { "projid_lo", FLDT_UINT16D, OI(COFF(projid_lo)), |
102 | inode_core_projid_count, FLD_COUNT, TYP_NONE }, | |
103 | { "projid_hi", FLDT_UINT16D, OI(COFF(projid_hi)), | |
104 | inode_core_projid_count, FLD_COUNT, TYP_NONE }, | |
2bd0ea18 NS |
105 | { "uid", FLDT_UINT32D, OI(COFF(uid)), C1, 0, TYP_NONE }, |
106 | { "gid", FLDT_UINT32D, OI(COFF(gid)), C1, 0, TYP_NONE }, | |
ec783255 | 107 | { "flushiter", FLDT_UINT16D, OI(COFF(flushiter)), C1, 0, TYP_NONE }, |
2bd0ea18 NS |
108 | { "atime", FLDT_TIMESTAMP, OI(COFF(atime)), C1, 0, TYP_NONE }, |
109 | { "mtime", FLDT_TIMESTAMP, OI(COFF(mtime)), C1, 0, TYP_NONE }, | |
110 | { "ctime", FLDT_TIMESTAMP, OI(COFF(ctime)), C1, 0, TYP_NONE }, | |
111 | { "size", FLDT_FSIZE, OI(COFF(size)), C1, 0, TYP_NONE }, | |
112 | { "nblocks", FLDT_DRFSBNO, OI(COFF(nblocks)), C1, 0, TYP_NONE }, | |
113 | { "extsize", FLDT_EXTLEN, OI(COFF(extsize)), C1, 0, TYP_NONE }, | |
114 | { "nextents", FLDT_EXTNUM, OI(COFF(nextents)), C1, 0, TYP_NONE }, | |
115 | { "naextents", FLDT_AEXTNUM, OI(COFF(anextents)), C1, 0, TYP_NONE }, | |
116 | { "forkoff", FLDT_UINT8D, OI(COFF(forkoff)), C1, 0, TYP_NONE }, | |
117 | { "aformat", FLDT_DINODE_FMT, OI(COFF(aformat)), C1, 0, TYP_NONE }, | |
118 | { "dmevmask", FLDT_UINT32X, OI(COFF(dmevmask)), C1, 0, TYP_NONE }, | |
119 | { "dmstate", FLDT_UINT16D, OI(COFF(dmstate)), C1, 0, TYP_NONE }, | |
120 | { "flags", FLDT_UINT16X, OI(COFF(flags)), C1, FLD_SKIPALL, TYP_NONE }, | |
121 | { "newrtbm", FLDT_UINT1, | |
14f8b681 | 122 | OI(COFF(flags) + bitsz(uint16_t) - XFS_DIFLAG_NEWRTBM_BIT - 1), C1, |
2bd0ea18 NS |
123 | 0, TYP_NONE }, |
124 | { "prealloc", FLDT_UINT1, | |
14f8b681 | 125 | OI(COFF(flags) + bitsz(uint16_t) - XFS_DIFLAG_PREALLOC_BIT - 1), C1, |
2bd0ea18 NS |
126 | 0, TYP_NONE }, |
127 | { "realtime", FLDT_UINT1, | |
14f8b681 | 128 | OI(COFF(flags) + bitsz(uint16_t) - XFS_DIFLAG_REALTIME_BIT - 1), C1, |
2bd0ea18 | 129 | 0, TYP_NONE }, |
2b288ccf | 130 | { "immutable", FLDT_UINT1, |
14f8b681 | 131 | OI(COFF(flags) + bitsz(uint16_t) - XFS_DIFLAG_IMMUTABLE_BIT-1), C1, |
2b288ccf NS |
132 | 0, TYP_NONE }, |
133 | { "append", FLDT_UINT1, | |
14f8b681 | 134 | OI(COFF(flags) + bitsz(uint16_t) - XFS_DIFLAG_APPEND_BIT - 1), C1, |
2b288ccf NS |
135 | 0, TYP_NONE }, |
136 | { "sync", FLDT_UINT1, | |
14f8b681 | 137 | OI(COFF(flags) + bitsz(uint16_t) - XFS_DIFLAG_SYNC_BIT - 1), C1, |
2b288ccf NS |
138 | 0, TYP_NONE }, |
139 | { "noatime", FLDT_UINT1, | |
14f8b681 | 140 | OI(COFF(flags) + bitsz(uint16_t) - XFS_DIFLAG_NOATIME_BIT - 1), C1, |
2b288ccf NS |
141 | 0, TYP_NONE }, |
142 | { "nodump", FLDT_UINT1, | |
14f8b681 | 143 | OI(COFF(flags) + bitsz(uint16_t) - XFS_DIFLAG_NODUMP_BIT - 1), C1, |
2b288ccf | 144 | 0, TYP_NONE }, |
4ebdd912 | 145 | { "rtinherit", FLDT_UINT1, |
14f8b681 | 146 | OI(COFF(flags) + bitsz(uint16_t) - XFS_DIFLAG_RTINHERIT_BIT-1), C1, |
4ebdd912 | 147 | 0, TYP_NONE }, |
5ecb3de2 | 148 | { "projinherit", FLDT_UINT1, |
14f8b681 | 149 | OI(COFF(flags) + bitsz(uint16_t) - XFS_DIFLAG_PROJINHERIT_BIT-1), C1, |
5ecb3de2 NS |
150 | 0, TYP_NONE }, |
151 | { "nosymlinks", FLDT_UINT1, | |
14f8b681 | 152 | OI(COFF(flags) + bitsz(uint16_t) - XFS_DIFLAG_NOSYMLINKS_BIT-1), C1, |
5ecb3de2 | 153 | 0, TYP_NONE }, |
ae541a2b | 154 | { "extsz", FLDT_UINT1, |
14f8b681 | 155 | OI(COFF(flags) + bitsz(uint16_t) - XFS_DIFLAG_EXTSIZE_BIT-1), C1, |
ae541a2b NS |
156 | 0, TYP_NONE }, |
157 | { "extszinherit", FLDT_UINT1, | |
14f8b681 | 158 | OI(COFF(flags) + bitsz(uint16_t) - XFS_DIFLAG_EXTSZINHERIT_BIT-1), C1, |
ae541a2b | 159 | 0, TYP_NONE }, |
ed832ad2 | 160 | { "nodefrag", FLDT_UINT1, |
14f8b681 | 161 | OI(COFF(flags) + bitsz(uint16_t) - XFS_DIFLAG_NODEFRAG_BIT-1), C1, |
ed832ad2 | 162 | 0, TYP_NONE }, |
2d5121ac | 163 | { "filestream", FLDT_UINT1, |
14f8b681 | 164 | OI(COFF(flags) + bitsz(uint16_t) - XFS_DIFLAG_FILESTREAM_BIT-1), C1, |
2d5121ac | 165 | 0, TYP_NONE }, |
2bd0ea18 NS |
166 | { "gen", FLDT_UINT32D, OI(COFF(gen)), C1, 0, TYP_NONE }, |
167 | { NULL } | |
168 | }; | |
169 | ||
c2907bd7 | 170 | const field_t inode_v3_flds[] = { |
0522f1cc | 171 | { "crc", FLDT_CRC, OI(COFF(crc)), C1, 0, TYP_NONE }, |
c2907bd7 DC |
172 | { "change_count", FLDT_UINT64D, OI(COFF(changecount)), C1, 0, TYP_NONE }, |
173 | { "lsn", FLDT_UINT64X, OI(COFF(lsn)), C1, 0, TYP_NONE }, | |
174 | { "flags2", FLDT_UINT64X, OI(COFF(flags2)), C1, 0, TYP_NONE }, | |
1f5407ac | 175 | { "cowextsize", FLDT_EXTLEN, OI(COFF(cowextsize)), C1, 0, TYP_NONE }, |
c2907bd7 DC |
176 | { "crtime", FLDT_TIMESTAMP, OI(COFF(crtime)), C1, 0, TYP_NONE }, |
177 | { "inumber", FLDT_INO, OI(COFF(ino)), C1, 0, TYP_NONE }, | |
178 | { "uuid", FLDT_UUID, OI(COFF(uuid)), C1, 0, TYP_NONE }, | |
9fb2cb27 | 179 | { "reflink", FLDT_UINT1, |
14f8b681 | 180 | OI(COFF(flags2) + bitsz(uint64_t) - XFS_DIFLAG2_REFLINK_BIT-1), C1, |
9fb2cb27 | 181 | 0, TYP_NONE }, |
1f5407ac | 182 | { "cowextsz", FLDT_UINT1, |
14f8b681 | 183 | OI(COFF(flags2) + bitsz(uint64_t) - XFS_DIFLAG2_COWEXTSIZE_BIT-1), C1, |
1f5407ac | 184 | 0, TYP_NONE }, |
c2907bd7 DC |
185 | { NULL } |
186 | }; | |
187 | ||
188 | ||
2bd0ea18 NS |
189 | #define TOFF(f) bitize(offsetof(xfs_timestamp_t, t_ ## f)) |
190 | const field_t timestamp_flds[] = { | |
191 | { "sec", FLDT_TIME, OI(TOFF(sec)), C1, 0, TYP_NONE }, | |
192 | { "nsec", FLDT_NSEC, OI(TOFF(nsec)), C1, 0, TYP_NONE }, | |
193 | { NULL } | |
194 | }; | |
195 | ||
196 | const field_t inode_u_flds[] = { | |
5e656dbb BN |
197 | { "bmbt", FLDT_BMROOTD, NULL, inode_u_bmbt_count, FLD_COUNT, TYP_NONE }, |
198 | { "bmx", FLDT_BMAPBTDREC, NULL, inode_u_bmx_count, FLD_ARRAY|FLD_COUNT, | |
2bd0ea18 | 199 | TYP_NONE }, |
5e656dbb BN |
200 | { "c", FLDT_CHARNS, NULL, inode_u_c_count, FLD_COUNT, TYP_NONE }, |
201 | { "dev", FLDT_DEV, NULL, inode_u_dev_count, FLD_COUNT, TYP_NONE }, | |
202 | { "muuid", FLDT_UUID, NULL, inode_u_muuid_count, FLD_COUNT, TYP_NONE }, | |
5e656dbb | 203 | { "sfdir2", FLDT_DIR2SF, NULL, inode_u_sfdir2_count, FLD_COUNT, TYP_NONE }, |
3beed08e | 204 | { "sfdir3", FLDT_DIR3SF, NULL, inode_u_sfdir3_count, FLD_COUNT, TYP_NONE }, |
5e656dbb | 205 | { "symlink", FLDT_CHARNS, NULL, inode_u_symlink_count, FLD_COUNT, |
2bd0ea18 NS |
206 | TYP_NONE }, |
207 | { NULL } | |
208 | }; | |
209 | ||
210 | const field_t inode_a_flds[] = { | |
5e656dbb BN |
211 | { "bmbt", FLDT_BMROOTA, NULL, inode_a_bmbt_count, FLD_COUNT, TYP_NONE }, |
212 | { "bmx", FLDT_BMAPBTAREC, NULL, inode_a_bmx_count, FLD_ARRAY|FLD_COUNT, | |
2bd0ea18 | 213 | TYP_NONE }, |
5e656dbb | 214 | { "sfattr", FLDT_ATTRSHORT, NULL, inode_a_sfattr_count, FLD_COUNT, |
2bd0ea18 NS |
215 | TYP_NONE }, |
216 | { NULL } | |
217 | }; | |
218 | ||
219 | static const char *dinode_fmt_name[] = | |
220 | { "dev", "local", "extents", "btree", "uuid" }; | |
221 | static const int dinode_fmt_name_size = | |
222 | sizeof(dinode_fmt_name) / sizeof(dinode_fmt_name[0]); | |
223 | ||
224 | /*ARGSUSED*/ | |
225 | int | |
226 | fp_dinode_fmt( | |
227 | void *obj, | |
228 | int bit, | |
229 | int count, | |
230 | char *fmtstr, | |
231 | int size, | |
232 | int arg, | |
233 | int base, | |
234 | int array) | |
235 | { | |
236 | int bitpos; | |
237 | xfs_dinode_fmt_t f; | |
238 | int i; | |
239 | ||
240 | for (i = 0, bitpos = bit; i < count; i++, bitpos += size) { | |
47dd6743 | 241 | f = (xfs_dinode_fmt_t)getbitval(obj, bitpos, size, BVUNSIGNED); |
2bd0ea18 NS |
242 | if (array) |
243 | dbprintf("%d:", i + base); | |
244 | if (f < 0 || f >= dinode_fmt_name_size) | |
245 | dbprintf("%d", (int)f); | |
246 | else | |
247 | dbprintf("%d (%s)", (int)f, dinode_fmt_name[(int)f]); | |
248 | if (i < count - 1) | |
249 | dbprintf(" "); | |
250 | } | |
251 | return 1; | |
252 | } | |
253 | ||
254 | static int | |
255 | inode_a_bmbt_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; | |
46eca962 | 264 | if (!XFS_DFORK_Q(dip)) |
2bd0ea18 | 265 | return 0; |
46eca962 | 266 | ASSERT((char *)XFS_DFORK_APTR(dip) - (char *)dip == byteize(startoff)); |
56b2de80 | 267 | return dip->di_aformat == XFS_DINODE_FMT_BTREE; |
2bd0ea18 NS |
268 | } |
269 | ||
270 | static int | |
271 | inode_a_bmx_count( | |
272 | void *obj, | |
273 | int startoff) | |
274 | { | |
275 | xfs_dinode_t *dip; | |
276 | ||
277 | ASSERT(bitoffs(startoff) == 0); | |
278 | ASSERT(obj == iocur_top->data); | |
279 | dip = obj; | |
46eca962 | 280 | if (!XFS_DFORK_Q(dip)) |
2bd0ea18 | 281 | return 0; |
46eca962 | 282 | ASSERT((char *)XFS_DFORK_APTR(dip) - (char *)dip == byteize(startoff)); |
56b2de80 DC |
283 | return dip->di_aformat == XFS_DINODE_FMT_EXTENTS ? |
284 | be16_to_cpu(dip->di_anextents) : 0; | |
2bd0ea18 NS |
285 | } |
286 | ||
287 | static int | |
288 | inode_a_count( | |
289 | void *obj, | |
290 | int startoff) | |
291 | { | |
292 | xfs_dinode_t *dip; | |
293 | ||
294 | ASSERT(startoff == 0); | |
295 | dip = obj; | |
46eca962 | 296 | return XFS_DFORK_Q(dip); |
2bd0ea18 NS |
297 | } |
298 | ||
299 | static int | |
300 | inode_a_offset( | |
301 | void *obj, | |
302 | int startoff, | |
303 | int idx) | |
304 | { | |
305 | xfs_dinode_t *dip; | |
306 | ||
307 | ASSERT(startoff == 0); | |
308 | ASSERT(idx == 0); | |
309 | dip = obj; | |
46eca962 NS |
310 | ASSERT(XFS_DFORK_Q(dip)); |
311 | return bitize((int)((char *)XFS_DFORK_APTR(dip) - (char *)dip)); | |
2bd0ea18 NS |
312 | } |
313 | ||
314 | static int | |
315 | inode_a_sfattr_count( | |
316 | void *obj, | |
317 | int startoff) | |
318 | { | |
319 | xfs_dinode_t *dip; | |
320 | ||
321 | ASSERT(bitoffs(startoff) == 0); | |
322 | ASSERT(obj == iocur_top->data); | |
323 | dip = obj; | |
46eca962 | 324 | if (!XFS_DFORK_Q(dip)) |
2bd0ea18 | 325 | return 0; |
46eca962 | 326 | ASSERT((char *)XFS_DFORK_APTR(dip) - (char *)dip == byteize(startoff)); |
56b2de80 | 327 | return dip->di_aformat == XFS_DINODE_FMT_LOCAL; |
2bd0ea18 NS |
328 | } |
329 | ||
330 | int | |
331 | inode_a_size( | |
332 | void *obj, | |
333 | int startoff, | |
334 | int idx) | |
335 | { | |
336 | xfs_attr_shortform_t *asf; | |
337 | xfs_dinode_t *dip; | |
338 | ||
339 | ASSERT(startoff == 0); | |
340 | ASSERT(idx == 0); | |
341 | dip = obj; | |
56b2de80 | 342 | switch (dip->di_aformat) { |
2bd0ea18 | 343 | case XFS_DINODE_FMT_LOCAL: |
46eca962 | 344 | asf = (xfs_attr_shortform_t *)XFS_DFORK_APTR(dip); |
5e656dbb | 345 | return bitize(be16_to_cpu(asf->hdr.totsize)); |
2bd0ea18 | 346 | case XFS_DINODE_FMT_EXTENTS: |
f8149110 | 347 | return (int)be16_to_cpu(dip->di_anextents) * |
5e656dbb | 348 | bitsz(xfs_bmbt_rec_t); |
2bd0ea18 | 349 | case XFS_DINODE_FMT_BTREE: |
46eca962 | 350 | return bitize((int)XFS_DFORK_ASIZE(dip, mp)); |
2bd0ea18 NS |
351 | default: |
352 | return 0; | |
353 | } | |
354 | } | |
355 | ||
356 | static int | |
357 | inode_core_nlinkv1_count( | |
56b2de80 DC |
358 | void *obj, |
359 | int startoff) | |
2bd0ea18 | 360 | { |
56b2de80 | 361 | xfs_dinode_t *dic; |
2bd0ea18 NS |
362 | |
363 | ASSERT(startoff == 0); | |
364 | ASSERT(obj == iocur_top->data); | |
365 | dic = obj; | |
56b2de80 | 366 | return dic->di_version == 1; |
2bd0ea18 NS |
367 | } |
368 | ||
369 | static int | |
370 | inode_core_nlinkv2_count( | |
56b2de80 DC |
371 | void *obj, |
372 | int startoff) | |
2bd0ea18 | 373 | { |
56b2de80 | 374 | xfs_dinode_t *dic; |
2bd0ea18 NS |
375 | |
376 | ASSERT(startoff == 0); | |
377 | ASSERT(obj == iocur_top->data); | |
378 | dic = obj; | |
6367f2a3 | 379 | return dic->di_version >= 2; |
2bd0ea18 NS |
380 | } |
381 | ||
382 | static int | |
383 | inode_core_onlink_count( | |
56b2de80 DC |
384 | void *obj, |
385 | int startoff) | |
2bd0ea18 | 386 | { |
56b2de80 | 387 | xfs_dinode_t *dic; |
2bd0ea18 NS |
388 | |
389 | ASSERT(startoff == 0); | |
390 | ASSERT(obj == iocur_top->data); | |
391 | dic = obj; | |
6367f2a3 | 392 | return dic->di_version >= 2; |
2bd0ea18 NS |
393 | } |
394 | ||
395 | static int | |
396 | inode_core_projid_count( | |
56b2de80 DC |
397 | void *obj, |
398 | int startoff) | |
2bd0ea18 | 399 | { |
56b2de80 | 400 | xfs_dinode_t *dic; |
2bd0ea18 NS |
401 | |
402 | ASSERT(startoff == 0); | |
403 | ASSERT(obj == iocur_top->data); | |
404 | dic = obj; | |
6367f2a3 | 405 | return dic->di_version >= 2; |
2bd0ea18 NS |
406 | } |
407 | ||
408 | static int | |
409 | inode_f( | |
410 | int argc, | |
411 | char **argv) | |
412 | { | |
413 | xfs_ino_t ino; | |
414 | char *p; | |
415 | ||
416 | if (argc > 1) { | |
417 | ino = strtoull(argv[1], &p, 0); | |
418 | if (*p != '\0') { | |
9ee7055c | 419 | dbprintf(_("bad value for inode number %s\n"), argv[1]); |
2bd0ea18 NS |
420 | return 0; |
421 | } | |
422 | set_cur_inode(ino); | |
423 | } else if (iocur_top->ino == NULLFSINO) | |
9ee7055c | 424 | dbprintf(_("no current inode\n")); |
2bd0ea18 | 425 | else |
9ee7055c | 426 | dbprintf(_("current inode number is %lld\n"), iocur_top->ino); |
2bd0ea18 NS |
427 | return 0; |
428 | } | |
429 | ||
430 | void | |
431 | inode_init(void) | |
432 | { | |
433 | add_command(&inode_cmd); | |
434 | } | |
435 | ||
436 | typnm_t | |
437 | inode_next_type(void) | |
438 | { | |
322f2a29 SL |
439 | switch (iocur_top->mode & S_IFMT) { |
440 | case S_IFDIR: | |
9a048535 | 441 | return TYP_DIR2; |
322f2a29 | 442 | case S_IFLNK: |
2bd0ea18 | 443 | return TYP_SYMLINK; |
322f2a29 | 444 | case S_IFREG: |
2bd0ea18 NS |
445 | if (iocur_top->ino == mp->m_sb.sb_rbmino) |
446 | return TYP_RTBITMAP; | |
447 | else if (iocur_top->ino == mp->m_sb.sb_rsumino) | |
448 | return TYP_RTSUMMARY; | |
449 | else if (iocur_top->ino == mp->m_sb.sb_uquotino || | |
0340d706 CS |
450 | iocur_top->ino == mp->m_sb.sb_gquotino || |
451 | iocur_top->ino == mp->m_sb.sb_pquotino) | |
2bd0ea18 NS |
452 | return TYP_DQBLK; |
453 | else | |
454 | return TYP_DATA; | |
455 | default: | |
456 | return TYP_NONE; | |
457 | } | |
458 | } | |
459 | ||
460 | int | |
461 | inode_size( | |
462 | void *obj, | |
463 | int startoff, | |
464 | int idx) | |
465 | { | |
466 | return bitize(mp->m_sb.sb_inodesize); | |
467 | } | |
468 | ||
56b2de80 DC |
469 | static int |
470 | inode_u_offset( | |
471 | void *obj, | |
472 | int startoff, | |
473 | int idx) | |
474 | { | |
475 | xfs_dinode_t *dip; | |
476 | ||
477 | ASSERT(startoff == 0); | |
478 | ASSERT(idx == 0); | |
479 | dip = obj; | |
480 | return bitize((int)((char *)XFS_DFORK_DPTR(dip) - (char *)dip)); | |
481 | } | |
482 | ||
2bd0ea18 NS |
483 | static int |
484 | inode_u_bmbt_count( | |
485 | void *obj, | |
486 | int startoff) | |
487 | { | |
488 | xfs_dinode_t *dip; | |
489 | ||
490 | ASSERT(bitoffs(startoff) == 0); | |
491 | ASSERT(obj == iocur_top->data); | |
492 | dip = obj; | |
56b2de80 DC |
493 | ASSERT((char *)XFS_DFORK_DPTR(dip) - (char *)dip == byteize(startoff)); |
494 | return dip->di_format == XFS_DINODE_FMT_BTREE; | |
2bd0ea18 NS |
495 | } |
496 | ||
497 | static int | |
498 | inode_u_bmx_count( | |
499 | void *obj, | |
500 | int startoff) | |
501 | { | |
502 | xfs_dinode_t *dip; | |
503 | ||
504 | ASSERT(bitoffs(startoff) == 0); | |
505 | ASSERT(obj == iocur_top->data); | |
506 | dip = obj; | |
56b2de80 DC |
507 | ASSERT((char *)XFS_DFORK_DPTR(dip) - (char *)dip == byteize(startoff)); |
508 | return dip->di_format == XFS_DINODE_FMT_EXTENTS ? | |
509 | be32_to_cpu(dip->di_nextents) : 0; | |
2bd0ea18 NS |
510 | } |
511 | ||
512 | static int | |
513 | inode_u_c_count( | |
514 | void *obj, | |
515 | int startoff) | |
516 | { | |
517 | xfs_dinode_t *dip; | |
518 | ||
519 | ASSERT(bitoffs(startoff) == 0); | |
520 | ASSERT(obj == iocur_top->data); | |
521 | dip = obj; | |
56b2de80 DC |
522 | ASSERT((char *)XFS_DFORK_DPTR(dip) - (char *)dip == byteize(startoff)); |
523 | return dip->di_format == XFS_DINODE_FMT_LOCAL && | |
524 | (be16_to_cpu(dip->di_mode) & S_IFMT) == S_IFREG ? | |
525 | (int)be64_to_cpu(dip->di_size) : 0; | |
2bd0ea18 NS |
526 | } |
527 | ||
528 | static int | |
529 | inode_u_dev_count( | |
530 | void *obj, | |
531 | int startoff) | |
532 | { | |
533 | xfs_dinode_t *dip; | |
534 | ||
535 | ASSERT(bitoffs(startoff) == 0); | |
536 | ASSERT(obj == iocur_top->data); | |
537 | dip = obj; | |
56b2de80 DC |
538 | ASSERT((char *)XFS_DFORK_DPTR(dip) - (char *)dip == byteize(startoff)); |
539 | return dip->di_format == XFS_DINODE_FMT_DEV; | |
2bd0ea18 NS |
540 | } |
541 | ||
542 | static int | |
543 | inode_u_muuid_count( | |
544 | void *obj, | |
545 | int startoff) | |
546 | { | |
547 | xfs_dinode_t *dip; | |
548 | ||
549 | ASSERT(bitoffs(startoff) == 0); | |
550 | ASSERT(obj == iocur_top->data); | |
551 | dip = obj; | |
56b2de80 DC |
552 | ASSERT((char *)XFS_DFORK_DPTR(dip) - (char *)dip == byteize(startoff)); |
553 | return dip->di_format == XFS_DINODE_FMT_UUID; | |
2bd0ea18 NS |
554 | } |
555 | ||
2bd0ea18 NS |
556 | static int |
557 | inode_u_sfdir2_count( | |
558 | void *obj, | |
559 | int startoff) | |
560 | { | |
561 | xfs_dinode_t *dip; | |
562 | ||
563 | ASSERT(bitoffs(startoff) == 0); | |
564 | ASSERT(obj == iocur_top->data); | |
565 | dip = obj; | |
56b2de80 DC |
566 | ASSERT((char *)XFS_DFORK_DPTR(dip) - (char *)dip == byteize(startoff)); |
567 | return dip->di_format == XFS_DINODE_FMT_LOCAL && | |
568 | (be16_to_cpu(dip->di_mode) & S_IFMT) == S_IFDIR && | |
3beed08e DC |
569 | !xfs_sb_version_hasftype(&mp->m_sb); |
570 | } | |
571 | ||
572 | static int | |
573 | inode_u_sfdir3_count( | |
574 | void *obj, | |
575 | int startoff) | |
576 | { | |
577 | xfs_dinode_t *dip; | |
578 | ||
579 | ASSERT(bitoffs(startoff) == 0); | |
580 | ASSERT(obj == iocur_top->data); | |
581 | dip = obj; | |
582 | ASSERT((char *)XFS_DFORK_DPTR(dip) - (char *)dip == byteize(startoff)); | |
583 | return dip->di_format == XFS_DINODE_FMT_LOCAL && | |
584 | (be16_to_cpu(dip->di_mode) & S_IFMT) == S_IFDIR && | |
585 | xfs_sb_version_hasftype(&mp->m_sb); | |
2bd0ea18 NS |
586 | } |
587 | ||
588 | int | |
589 | inode_u_size( | |
590 | void *obj, | |
591 | int startoff, | |
592 | int idx) | |
593 | { | |
594 | xfs_dinode_t *dip; | |
595 | ||
596 | ASSERT(startoff == 0); | |
597 | ASSERT(idx == 0); | |
598 | dip = obj; | |
56b2de80 | 599 | switch (dip->di_format) { |
2bd0ea18 NS |
600 | case XFS_DINODE_FMT_DEV: |
601 | return bitsz(xfs_dev_t); | |
602 | case XFS_DINODE_FMT_LOCAL: | |
56b2de80 | 603 | return bitize((int)be64_to_cpu(dip->di_size)); |
2bd0ea18 | 604 | case XFS_DINODE_FMT_EXTENTS: |
f8149110 | 605 | return (int)be32_to_cpu(dip->di_nextents) * |
5e656dbb | 606 | bitsz(xfs_bmbt_rec_t); |
2bd0ea18 | 607 | case XFS_DINODE_FMT_BTREE: |
46eca962 | 608 | return bitize((int)XFS_DFORK_DSIZE(dip, mp)); |
2bd0ea18 NS |
609 | case XFS_DINODE_FMT_UUID: |
610 | return bitsz(uuid_t); | |
611 | default: | |
612 | return 0; | |
613 | } | |
614 | } | |
615 | ||
616 | static int | |
617 | inode_u_symlink_count( | |
618 | void *obj, | |
619 | int startoff) | |
620 | { | |
621 | xfs_dinode_t *dip; | |
622 | ||
623 | ASSERT(bitoffs(startoff) == 0); | |
624 | ASSERT(obj == iocur_top->data); | |
625 | dip = obj; | |
56b2de80 DC |
626 | ASSERT((char *)XFS_DFORK_DPTR(dip) - (char *)dip == byteize(startoff)); |
627 | return dip->di_format == XFS_DINODE_FMT_LOCAL && | |
628 | (be16_to_cpu(dip->di_mode) & S_IFMT) == S_IFLNK ? | |
629 | (int)be64_to_cpu(dip->di_size) : 0; | |
2bd0ea18 NS |
630 | } |
631 | ||
06d80a7c DC |
632 | /* |
633 | * We are now using libxfs for our IO backend, so we should always try to use | |
634 | * inode cluster buffers rather than filesystem block sized buffers for reading | |
635 | * inodes. This means that we always use the same buffers as libxfs operations | |
636 | * does, and that avoids buffer cache issues caused by overlapping buffers. This | |
637 | * can be seen clearly when trying to read the root inode. Much of this logic is | |
638 | * similar to libxfs_imap(). | |
639 | */ | |
2bd0ea18 NS |
640 | void |
641 | set_cur_inode( | |
642 | xfs_ino_t ino) | |
643 | { | |
644 | xfs_agblock_t agbno; | |
645 | xfs_agino_t agino; | |
646 | xfs_agnumber_t agno; | |
647 | xfs_dinode_t *dip; | |
648 | int offset; | |
06d80a7c DC |
649 | int numblks = blkbb; |
650 | xfs_agblock_t cluster_agbno; | |
651 | ||
2bd0ea18 NS |
652 | |
653 | agno = XFS_INO_TO_AGNO(mp, ino); | |
654 | agino = XFS_INO_TO_AGINO(mp, ino); | |
655 | agbno = XFS_AGINO_TO_AGBNO(mp, agino); | |
656 | offset = XFS_AGINO_TO_OFFSET(mp, agino); | |
657 | if (agno >= mp->m_sb.sb_agcount || agbno >= mp->m_sb.sb_agblocks || | |
658 | offset >= mp->m_sb.sb_inopblock || | |
659 | XFS_AGINO_TO_INO(mp, agno, agino) != ino) { | |
9ee7055c | 660 | dbprintf(_("bad inode number %lld\n"), ino); |
2bd0ea18 NS |
661 | return; |
662 | } | |
663 | cur_agno = agno; | |
06d80a7c DC |
664 | |
665 | if (mp->m_inode_cluster_size > mp->m_sb.sb_blocksize && | |
666 | mp->m_inoalign_mask) { | |
667 | xfs_agblock_t chunk_agbno; | |
668 | xfs_agblock_t offset_agbno; | |
669 | int blks_per_cluster; | |
670 | ||
671 | blks_per_cluster = mp->m_inode_cluster_size >> | |
672 | mp->m_sb.sb_blocklog; | |
673 | offset_agbno = agbno & mp->m_inoalign_mask; | |
674 | chunk_agbno = agbno - offset_agbno; | |
675 | cluster_agbno = chunk_agbno + | |
676 | ((offset_agbno / blks_per_cluster) * blks_per_cluster); | |
677 | offset += ((agbno - cluster_agbno) * mp->m_sb.sb_inopblock); | |
678 | numblks = XFS_FSB_TO_BB(mp, blks_per_cluster); | |
679 | } else | |
680 | cluster_agbno = agbno; | |
681 | ||
2bd0ea18 NS |
682 | /* |
683 | * First set_cur to the block with the inode | |
684 | * then use off_cur to get the right part of the buffer. | |
685 | */ | |
686 | ASSERT(typtab[TYP_INODE].typnm == TYP_INODE); | |
687 | ||
688 | /* ingore ring update here, do it explicitly below */ | |
06d80a7c DC |
689 | set_cur(&typtab[TYP_INODE], XFS_AGB_TO_DADDR(mp, agno, cluster_agbno), |
690 | numblks, DB_RING_IGN, NULL); | |
2bd0ea18 | 691 | off_cur(offset << mp->m_sb.sb_inodelog, mp->m_sb.sb_inodesize); |
603ab21e DW |
692 | if (!iocur_top->data) |
693 | return; | |
2bd0ea18 | 694 | dip = iocur_top->data; |
a73b88f2 | 695 | iocur_top->ino_buf = 1; |
2bd0ea18 | 696 | iocur_top->ino = ino; |
56b2de80 | 697 | iocur_top->mode = be16_to_cpu(dip->di_mode); |
322f2a29 | 698 | if ((iocur_top->mode & S_IFMT) == S_IFDIR) |
2bd0ea18 NS |
699 | iocur_top->dirino = ino; |
700 | ||
b335ecb5 ES |
701 | if (xfs_sb_version_hascrc(&mp->m_sb)) { |
702 | iocur_top->ino_crc_ok = libxfs_verify_cksum((char *)dip, | |
703 | mp->m_sb.sb_inodesize, | |
704 | XFS_DINODE_CRC_OFF); | |
705 | if (!iocur_top->ino_crc_ok) | |
706 | dbprintf( | |
707 | _("Metadata CRC error detected for ino %lld\n"), | |
708 | ino); | |
709 | } | |
710 | ||
2bd0ea18 NS |
711 | /* track updated info in ring */ |
712 | ring_add(); | |
713 | } |