]>
Commit | Line | Data |
---|---|---|
2bd0ea18 | 1 | /* |
da23017d NS |
2 | * Copyright (c) 2000-2001,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 | 21 | #include "type.h" |
128efca1 NS |
22 | #include "fprint.h" |
23 | #include "faddr.h" | |
24 | #include "field.h" | |
2bd0ea18 NS |
25 | #include "bmap.h" |
26 | #include "io.h" | |
27 | #include "inode.h" | |
28 | #include "output.h" | |
4ca431fc | 29 | #include "init.h" |
2bd0ea18 NS |
30 | |
31 | static int bmap_f(int argc, char **argv); | |
56b2de80 | 32 | static int bmap_one_extent(xfs_bmbt_rec_t *ep, |
5a35bf2c | 33 | xfs_fileoff_t *offp, xfs_fileoff_t eoff, |
2bd0ea18 | 34 | int *idxp, bmap_ext_t *bep); |
5a35bf2c | 35 | static xfs_fsblock_t select_child(xfs_fileoff_t off, xfs_bmbt_key_t *kp, |
2bd0ea18 NS |
36 | xfs_bmbt_ptr_t *pp, int nrecs); |
37 | ||
38 | static const cmdinfo_t bmap_cmd = | |
9ee7055c AM |
39 | { "bmap", NULL, bmap_f, 0, 3, 0, N_("[-ad] [block [len]]"), |
40 | N_("show block map for current file"), NULL }; | |
2bd0ea18 NS |
41 | |
42 | void | |
43 | bmap( | |
5a35bf2c DC |
44 | xfs_fileoff_t offset, |
45 | xfs_filblks_t len, | |
2bd0ea18 NS |
46 | int whichfork, |
47 | int *nexp, | |
48 | bmap_ext_t *bep) | |
49 | { | |
b3563c19 | 50 | struct xfs_btree_block *block; |
2bd0ea18 | 51 | xfs_fsblock_t bno; |
5a35bf2c | 52 | xfs_fileoff_t curoffset; |
2bd0ea18 | 53 | xfs_dinode_t *dip; |
5a35bf2c | 54 | xfs_fileoff_t eoffset; |
56b2de80 | 55 | xfs_bmbt_rec_t *ep; |
2bd0ea18 NS |
56 | xfs_dinode_fmt_t fmt; |
57 | int fsize; | |
58 | xfs_bmbt_key_t *kp; | |
59 | int n; | |
60 | int nex; | |
61 | xfs_fsblock_t nextbno; | |
62 | int nextents; | |
63 | xfs_bmbt_ptr_t *pp; | |
64 | xfs_bmdr_block_t *rblock; | |
65 | typnm_t typ; | |
56b2de80 | 66 | xfs_bmbt_rec_t *xp; |
2bd0ea18 NS |
67 | |
68 | push_cur(); | |
69 | set_cur_inode(iocur_top->ino); | |
70 | nex = *nexp; | |
71 | *nexp = 0; | |
72 | ASSERT(nex > 0); | |
73 | dip = iocur_top->data; | |
74 | n = 0; | |
75 | eoffset = offset + len - 1; | |
76 | curoffset = offset; | |
46eca962 | 77 | fmt = (xfs_dinode_fmt_t)XFS_DFORK_FORMAT(dip, whichfork); |
2bd0ea18 NS |
78 | typ = whichfork == XFS_DATA_FORK ? TYP_BMAPBTD : TYP_BMAPBTA; |
79 | ASSERT(typtab[typ].typnm == typ); | |
c9ee470e BN |
80 | ASSERT(fmt == XFS_DINODE_FMT_LOCAL || fmt == XFS_DINODE_FMT_EXTENTS || |
81 | fmt == XFS_DINODE_FMT_BTREE); | |
2bd0ea18 | 82 | if (fmt == XFS_DINODE_FMT_EXTENTS) { |
46eca962 | 83 | nextents = XFS_DFORK_NEXTENTS(dip, whichfork); |
56b2de80 | 84 | xp = (xfs_bmbt_rec_t *)XFS_DFORK_PTR(dip, whichfork); |
2bd0ea18 NS |
85 | for (ep = xp; ep < &xp[nextents] && n < nex; ep++) { |
86 | if (!bmap_one_extent(ep, &curoffset, eoffset, &n, bep)) | |
87 | break; | |
88 | } | |
c9ee470e | 89 | } else if (fmt == XFS_DINODE_FMT_BTREE) { |
2bd0ea18 | 90 | push_cur(); |
46eca962 NS |
91 | rblock = (xfs_bmdr_block_t *)XFS_DFORK_PTR(dip, whichfork); |
92 | fsize = XFS_DFORK_SIZE(dip, mp, whichfork); | |
e2f60652 | 93 | pp = XFS_BMDR_PTR_ADDR(rblock, 1, libxfs_bmdr_maxrecs(fsize, 0)); |
b3563c19 | 94 | kp = XFS_BMDR_KEY_ADDR(rblock, 1); |
f8149110 | 95 | bno = select_child(curoffset, kp, pp, |
5e656dbb | 96 | be16_to_cpu(rblock->bb_numrecs)); |
2bd0ea18 NS |
97 | for (;;) { |
98 | set_cur(&typtab[typ], XFS_FSB_TO_DADDR(mp, bno), | |
99 | blkbb, DB_RING_IGN, NULL); | |
b3563c19 | 100 | block = (struct xfs_btree_block *)iocur_top->data; |
5e656dbb | 101 | if (be16_to_cpu(block->bb_level) == 0) |
2bd0ea18 | 102 | break; |
7db1e7b9 | 103 | pp = XFS_BMBT_PTR_ADDR(mp, block, 1, |
e2f60652 | 104 | libxfs_bmbt_maxrecs(mp, mp->m_sb.sb_blocksize, 0)); |
7db1e7b9 | 105 | kp = XFS_BMBT_KEY_ADDR(mp, block, 1); |
2bd0ea18 | 106 | bno = select_child(curoffset, kp, pp, |
5e656dbb | 107 | be16_to_cpu(block->bb_numrecs)); |
2bd0ea18 NS |
108 | } |
109 | for (;;) { | |
b3563c19 | 110 | nextbno = be64_to_cpu(block->bb_u.l.bb_rightsib); |
5e656dbb | 111 | nextents = be16_to_cpu(block->bb_numrecs); |
56b2de80 | 112 | xp = (xfs_bmbt_rec_t *) |
b3563c19 | 113 | XFS_BMBT_REC_ADDR(mp, block, 1); |
2bd0ea18 NS |
114 | for (ep = xp; ep < &xp[nextents] && n < nex; ep++) { |
115 | if (!bmap_one_extent(ep, &curoffset, eoffset, | |
116 | &n, bep)) { | |
117 | nextbno = NULLFSBLOCK; | |
118 | break; | |
119 | } | |
120 | } | |
121 | bno = nextbno; | |
122 | if (bno == NULLFSBLOCK) | |
123 | break; | |
124 | set_cur(&typtab[typ], XFS_FSB_TO_DADDR(mp, bno), | |
125 | blkbb, DB_RING_IGN, NULL); | |
b3563c19 | 126 | block = (struct xfs_btree_block *)iocur_top->data; |
2bd0ea18 NS |
127 | } |
128 | pop_cur(); | |
129 | } | |
130 | pop_cur(); | |
131 | *nexp = n; | |
132 | } | |
133 | ||
134 | static int | |
135 | bmap_f( | |
136 | int argc, | |
137 | char **argv) | |
138 | { | |
139 | int afork = 0; | |
140 | bmap_ext_t be; | |
141 | int c; | |
5a35bf2c | 142 | xfs_fileoff_t co, cosave; |
2bd0ea18 NS |
143 | int dfork = 0; |
144 | xfs_dinode_t *dip; | |
5a35bf2c DC |
145 | xfs_fileoff_t eo; |
146 | xfs_filblks_t len; | |
2bd0ea18 NS |
147 | int nex; |
148 | char *p; | |
149 | int whichfork; | |
150 | ||
151 | if (iocur_top->ino == NULLFSINO) { | |
9ee7055c | 152 | dbprintf(_("no current inode\n")); |
2bd0ea18 NS |
153 | return 0; |
154 | } | |
155 | optind = 0; | |
156 | if (argc) while ((c = getopt(argc, argv, "ad")) != EOF) { | |
157 | switch (c) { | |
158 | case 'a': | |
159 | afork = 1; | |
160 | break; | |
161 | case 'd': | |
162 | dfork = 1; | |
163 | break; | |
164 | default: | |
9ee7055c | 165 | dbprintf(_("bad option for bmap command\n")); |
2bd0ea18 NS |
166 | return 0; |
167 | } | |
168 | } | |
169 | if (afork + dfork == 0) { | |
170 | push_cur(); | |
171 | set_cur_inode(iocur_top->ino); | |
172 | dip = iocur_top->data; | |
56b2de80 | 173 | if (be32_to_cpu(dip->di_nextents)) |
2bd0ea18 | 174 | dfork = 1; |
56b2de80 | 175 | if (be16_to_cpu(dip->di_anextents)) |
2bd0ea18 NS |
176 | afork = 1; |
177 | pop_cur(); | |
178 | } | |
179 | if (optind < argc) { | |
5a35bf2c | 180 | co = (xfs_fileoff_t)strtoull(argv[optind], &p, 0); |
2bd0ea18 | 181 | if (*p != '\0') { |
9ee7055c | 182 | dbprintf(_("bad block number for bmap %s\n"), |
2bd0ea18 NS |
183 | argv[optind]); |
184 | return 0; | |
185 | } | |
186 | optind++; | |
187 | if (optind < argc) { | |
5a35bf2c | 188 | len = (xfs_filblks_t)strtoull(argv[optind], &p, 0); |
2bd0ea18 | 189 | if (*p != '\0') { |
9ee7055c | 190 | dbprintf(_("bad len for bmap %s\n"), argv[optind]); |
2bd0ea18 NS |
191 | return 0; |
192 | } | |
193 | eo = co + len - 1; | |
194 | } else | |
195 | eo = co; | |
196 | } else { | |
197 | co = 0; | |
198 | eo = -1; | |
199 | } | |
c9ee470e | 200 | cosave = co; |
2bd0ea18 NS |
201 | for (whichfork = XFS_DATA_FORK; |
202 | whichfork <= XFS_ATTR_FORK; | |
203 | whichfork++) { | |
204 | if (whichfork == XFS_DATA_FORK && !dfork) | |
205 | continue; | |
206 | if (whichfork == XFS_ATTR_FORK && !afork) | |
207 | continue; | |
208 | for (;;) { | |
209 | nex = 1; | |
210 | bmap(co, eo - co + 1, whichfork, &nex, &be); | |
211 | if (nex == 0) | |
212 | break; | |
9ee7055c AM |
213 | dbprintf(_("%s offset %lld startblock %llu (%u/%u) count " |
214 | "%llu flag %u\n"), | |
215 | whichfork == XFS_DATA_FORK ? _("data") : _("attr"), | |
2bd0ea18 NS |
216 | be.startoff, be.startblock, |
217 | XFS_FSB_TO_AGNO(mp, be.startblock), | |
218 | XFS_FSB_TO_AGBNO(mp, be.startblock), | |
219 | be.blockcount, be.flag); | |
220 | co = be.startoff + be.blockcount; | |
221 | } | |
c9ee470e | 222 | co = cosave; |
2bd0ea18 NS |
223 | } |
224 | return 0; | |
225 | } | |
226 | ||
227 | void | |
228 | bmap_init(void) | |
229 | { | |
230 | add_command(&bmap_cmd); | |
231 | } | |
232 | ||
233 | static int | |
234 | bmap_one_extent( | |
56b2de80 | 235 | xfs_bmbt_rec_t *ep, |
5a35bf2c DC |
236 | xfs_fileoff_t *offp, |
237 | xfs_fileoff_t eoff, | |
2bd0ea18 NS |
238 | int *idxp, |
239 | bmap_ext_t *bep) | |
240 | { | |
5a35bf2c DC |
241 | xfs_filblks_t c; |
242 | xfs_fileoff_t curoffset; | |
2bd0ea18 NS |
243 | int f; |
244 | int idx; | |
5a35bf2c DC |
245 | xfs_fileoff_t o; |
246 | xfs_fsblock_t s; | |
2bd0ea18 NS |
247 | |
248 | convert_extent(ep, &o, &s, &c, &f); | |
249 | curoffset = *offp; | |
250 | idx = *idxp; | |
251 | if (o + c <= curoffset) | |
252 | return 1; | |
253 | if (o > eoff) | |
254 | return 0; | |
255 | if (o < curoffset) { | |
256 | c -= curoffset - o; | |
257 | s += curoffset - o; | |
258 | o = curoffset; | |
259 | } | |
260 | if (o + c - 1 > eoff) | |
261 | c -= (o + c - 1) - eoff; | |
262 | bep[idx].startoff = o; | |
263 | bep[idx].startblock = s; | |
264 | bep[idx].blockcount = c; | |
265 | bep[idx].flag = f; | |
266 | *idxp = idx + 1; | |
267 | *offp = o + c; | |
268 | return 1; | |
269 | } | |
270 | ||
271 | void | |
272 | convert_extent( | |
56b2de80 | 273 | xfs_bmbt_rec_t *rp, |
5a35bf2c DC |
274 | xfs_fileoff_t *op, |
275 | xfs_fsblock_t *sp, | |
276 | xfs_filblks_t *cp, | |
2bd0ea18 NS |
277 | int *fp) |
278 | { | |
ff105f75 | 279 | struct xfs_bmbt_irec irec; |
2bd0ea18 | 280 | |
9c32ccfc | 281 | libxfs_bmbt_disk_get_all(rp, &irec); |
9c32ccfc BN |
282 | *fp = irec.br_state == XFS_EXT_UNWRITTEN; |
283 | *op = irec.br_startoff; | |
284 | *sp = irec.br_startblock; | |
285 | *cp = irec.br_blockcount; | |
2bd0ea18 NS |
286 | } |
287 | ||
288 | void | |
289 | make_bbmap( | |
290 | bbmap_t *bbmap, | |
291 | int nex, | |
292 | bmap_ext_t *bmp) | |
293 | { | |
2bd0ea18 | 294 | int i; |
2bd0ea18 | 295 | |
48e32b40 DC |
296 | for (i = 0; i < nex; i++) { |
297 | bbmap->b[i].bm_bn = XFS_FSB_TO_DADDR(mp, bmp[i].startblock); | |
298 | bbmap->b[i].bm_len = XFS_FSB_TO_BB(mp, bmp[i].blockcount); | |
2bd0ea18 | 299 | } |
48e32b40 | 300 | bbmap->nmaps = nex; |
2bd0ea18 NS |
301 | } |
302 | ||
303 | static xfs_fsblock_t | |
304 | select_child( | |
5a35bf2c | 305 | xfs_fileoff_t off, |
2bd0ea18 NS |
306 | xfs_bmbt_key_t *kp, |
307 | xfs_bmbt_ptr_t *pp, | |
308 | int nrecs) | |
309 | { | |
310 | int i; | |
311 | ||
312 | for (i = 0; i < nrecs; i++) { | |
5e656dbb BN |
313 | if (be64_to_cpu(kp[i].br_startoff) == off) |
314 | return be64_to_cpu(pp[i]); | |
315 | if (be64_to_cpu(kp[i].br_startoff) > off) { | |
2bd0ea18 | 316 | if (i == 0) |
5e656dbb | 317 | return be64_to_cpu(pp[i]); |
2bd0ea18 | 318 | else |
5e656dbb | 319 | return be64_to_cpu(pp[i - 1]); |
2bd0ea18 NS |
320 | } |
321 | } | |
5e656dbb | 322 | return be64_to_cpu(pp[nrecs - 1]); |
2bd0ea18 | 323 | } |