]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - repair/phase6.c
xfsprogs: add crc format support to db
[thirdparty/xfsprogs-dev.git] / repair / phase6.c
CommitLineData
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
2bd0ea18
NS
19#include <libxfs.h>
20#include "avl.h"
21#include "globals.h"
22#include "agheader.h"
23#include "incore.h"
2bd0ea18 24#include "dir2.h"
2bd0ea18
NS
25#include "protos.h"
26#include "err_protos.h"
27#include "dinode.h"
cb5b3ef4 28#include "prefetch.h"
06fbdda9 29#include "progress.h"
2556c98b 30#include "threads.h"
2bd0ea18
NS
31#include "versions.h"
32
6c39a3cb
BN
33static struct cred zerocr;
34static struct fsxattr zerofsx;
35static xfs_ino_t orphanage_ino;
2bd0ea18 36
56b2de80 37static struct xfs_name xfs_name_dot = {(unsigned char *)".", 1};
5e656dbb 38
575ca697
BN
39/*
40 * Data structures used to keep track of directories where the ".."
41 * entries are updated. These must be rebuilt after the initial pass
42 */
43typedef struct dotdot_update {
44 struct dotdot_update *next;
45 ino_tree_node_t *irec;
46 xfs_agnumber_t agno;
47 int ino_offset;
48} dotdot_update_t;
49
50static dotdot_update_t *dotdot_update_list;
51static int dotdot_update;
52
53static void
54add_dotdot_update(
55 xfs_agnumber_t agno,
56 ino_tree_node_t *irec,
57 int ino_offset)
58{
59 dotdot_update_t *dir = malloc(sizeof(dotdot_update_t));
60
61 if (!dir)
5d1b7f0f 62 do_error(_("malloc failed add_dotdot_update (%zu bytes)\n"),
575ca697
BN
63 sizeof(dotdot_update_t));
64
65 dir->next = dotdot_update_list;
66 dir->irec = irec;
67 dir->agno = agno;
68 dir->ino_offset = ino_offset;
69
70 dotdot_update_list = dir;
71}
72
2bd0ea18
NS
73/*
74 * Data structures and routines to keep track of directory entries
33165ec3
BN
75 * and whether their leaf entry has been seen. Also used for name
76 * duplicate checking and rebuilding step if required.
2bd0ea18
NS
77 */
78typedef struct dir_hash_ent {
33165ec3
BN
79 struct dir_hash_ent *nextbyaddr; /* next in addr bucket */
80 struct dir_hash_ent *nextbyhash; /* next in name bucket */
81 struct dir_hash_ent *nextbyorder; /* next in order added */
82 xfs_dahash_t hashval; /* hash value of name */
83 __uint32_t address; /* offset of data entry */
84 xfs_ino_t inum; /* inode num of entry */
85 short junkit; /* name starts with / */
86 short seen; /* have seen leaf entry */
5e656dbb 87 struct xfs_name name;
2bd0ea18
NS
88} dir_hash_ent_t;
89
90typedef struct dir_hash_tab {
33165ec3
BN
91 int size; /* size of hash tables */
92 int names_duped; /* 1 = ent names malloced */
93 dir_hash_ent_t *first; /* ptr to first added entry */
94 dir_hash_ent_t *last; /* ptr to last added entry */
95 dir_hash_ent_t **byhash; /* ptr to name hash buckets */
96 dir_hash_ent_t **byaddr; /* ptr to addr hash buckets */
2bd0ea18 97} dir_hash_tab_t;
33165ec3 98
2bd0ea18 99#define DIR_HASH_TAB_SIZE(n) \
33165ec3 100 (sizeof(dir_hash_tab_t) + (sizeof(dir_hash_ent_t *) * (n) * 2))
2bd0ea18
NS
101#define DIR_HASH_FUNC(t,a) ((a) % (t)->size)
102
103/*
104 * Track the contents of the freespace table in a directory.
105 */
106typedef struct freetab {
9d7d6241
NS
107 int naents; /* expected number of data blocks */
108 int nents; /* number of data blocks processed */
2bd0ea18
NS
109 struct freetab_ent {
110 xfs_dir2_data_off_t v;
111 short s;
112 } ents[1];
113} freetab_t;
114#define FREETAB_SIZE(n) \
115 (offsetof(freetab_t, ents) + (sizeof(struct freetab_ent) * (n)))
116
117#define DIR_HASH_CK_OK 0
118#define DIR_HASH_CK_DUPLEAF 1
119#define DIR_HASH_CK_BADHASH 2
120#define DIR_HASH_CK_NODATA 3
121#define DIR_HASH_CK_NOLEAF 4
122#define DIR_HASH_CK_BADSTALE 5
507f4e33 123#define DIR_HASH_CK_TOTAL 6
2bd0ea18 124
33165ec3
BN
125/*
126 * Returns 0 if the name already exists (ie. a duplicate)
127 */
128static int
2bd0ea18 129dir_hash_add(
51ca7008 130 xfs_mount_t *mp,
2bd0ea18 131 dir_hash_tab_t *hashtab,
0f012a4c 132 __uint32_t addr,
33165ec3
BN
133 xfs_ino_t inum,
134 int namelen,
56b2de80 135 unsigned char *name)
2bd0ea18 136{
33165ec3
BN
137 xfs_dahash_t hash = 0;
138 int byaddr;
139 int byhash = 0;
2bd0ea18 140 dir_hash_ent_t *p;
33165ec3
BN
141 int dup;
142 short junk;
5e656dbb 143 struct xfs_name xname;
0f012a4c 144
33165ec3 145 ASSERT(!hashtab->names_duped);
0f012a4c 146
5e656dbb
BN
147 xname.name = name;
148 xname.len = namelen;
149
33165ec3
BN
150 junk = name[0] == '/';
151 byaddr = DIR_HASH_FUNC(hashtab, addr);
152 dup = 0;
2bd0ea18 153
33165ec3 154 if (!junk) {
5e656dbb 155 hash = mp->m_dirnameops->hashname(&xname);
33165ec3
BN
156 byhash = DIR_HASH_FUNC(hashtab, hash);
157
0f012a4c 158 /*
33165ec3
BN
159 * search hash bucket for existing name.
160 */
161 for (p = hashtab->byhash[byhash]; p; p = p->nextbyhash) {
5e656dbb
BN
162 if (p->hashval == hash && p->name.len == namelen) {
163 if (memcmp(p->name.name, name, namelen) == 0) {
33165ec3
BN
164 dup = 1;
165 junk = 1;
166 break;
167 }
168 }
169 }
170 }
0f012a4c 171
507f4e33 172 if ((p = malloc(sizeof(*p))) == NULL)
5d1b7f0f 173 do_error(_("malloc failed in dir_hash_add (%zu bytes)\n"),
2bd0ea18 174 sizeof(*p));
0f012a4c 175
33165ec3
BN
176 p->nextbyaddr = hashtab->byaddr[byaddr];
177 hashtab->byaddr[byaddr] = p;
0f012a4c 178 if (hashtab->last)
33165ec3
BN
179 hashtab->last->nextbyorder = p;
180 else
181 hashtab->first = p;
182 p->nextbyorder = NULL;
183 hashtab->last = p;
0f012a4c 184
33165ec3
BN
185 if (!(p->junkit = junk)) {
186 p->hashval = hash;
187 p->nextbyhash = hashtab->byhash[byhash];
188 hashtab->byhash[byhash] = p;
189 }
190 p->address = addr;
191 p->inum = inum;
2bd0ea18 192 p->seen = 0;
5e656dbb 193 p->name = xname;
0f012a4c 194
33165ec3 195 return !dup;
2bd0ea18
NS
196}
197
33165ec3 198/*
0f012a4c 199 * checks to see if any data entries are not in the leaf blocks
33165ec3 200 */
2bd0ea18
NS
201static int
202dir_hash_unseen(
203 dir_hash_tab_t *hashtab)
204{
205 int i;
206 dir_hash_ent_t *p;
207
208 for (i = 0; i < hashtab->size; i++) {
33165ec3 209 for (p = hashtab->byaddr[i]; p; p = p->nextbyaddr) {
2bd0ea18
NS
210 if (p->seen == 0)
211 return 1;
212 }
213 }
214 return 0;
215}
216
217static int
218dir_hash_check(
219 dir_hash_tab_t *hashtab,
220 xfs_inode_t *ip,
221 int seeval)
222{
507f4e33
NS
223 static char *seevalstr[DIR_HASH_CK_TOTAL];
224 static int done;
225
226 if (!done) {
227 seevalstr[DIR_HASH_CK_OK] = _("ok");
228 seevalstr[DIR_HASH_CK_DUPLEAF] = _("duplicate leaf");
229 seevalstr[DIR_HASH_CK_BADHASH] = _("hash value mismatch");
230 seevalstr[DIR_HASH_CK_NODATA] = _("no data entry");
231 seevalstr[DIR_HASH_CK_NOLEAF] = _("no leaf entry");
232 seevalstr[DIR_HASH_CK_BADSTALE] = _("bad stale count");
233 done = 1;
234 }
2bd0ea18
NS
235
236 if (seeval == DIR_HASH_CK_OK && dir_hash_unseen(hashtab))
237 seeval = DIR_HASH_CK_NOLEAF;
238 if (seeval == DIR_HASH_CK_OK)
239 return 0;
5d1b7f0f 240 do_warn(_("bad hash table for directory inode %" PRIu64 " (%s): "),
507f4e33 241 ip->i_ino, seevalstr[seeval]);
2bd0ea18 242 if (!no_modify)
507f4e33 243 do_warn(_("rebuilding\n"));
2bd0ea18 244 else
507f4e33 245 do_warn(_("would rebuild\n"));
2bd0ea18
NS
246 return 1;
247}
248
249static void
250dir_hash_done(
251 dir_hash_tab_t *hashtab)
252{
253 int i;
254 dir_hash_ent_t *n;
255 dir_hash_ent_t *p;
256
257 for (i = 0; i < hashtab->size; i++) {
33165ec3
BN
258 for (p = hashtab->byaddr[i]; p; p = n) {
259 n = p->nextbyaddr;
260 if (hashtab->names_duped)
5e656dbb 261 free((void *)p->name.name);
2bd0ea18
NS
262 free(p);
263 }
264 }
265 free(hashtab);
266}
267
268static dir_hash_tab_t *
269dir_hash_init(
270 xfs_fsize_t size)
271{
272 dir_hash_tab_t *hashtab;
273 int hsize;
274
275 hsize = size / (16 * 4);
2556c98b
BN
276 if (hsize > 65536)
277 hsize = 63336;
2bd0ea18
NS
278 else if (hsize < 16)
279 hsize = 16;
507f4e33
NS
280 if ((hashtab = calloc(DIR_HASH_TAB_SIZE(hsize), 1)) == NULL)
281 do_error(_("calloc failed in dir_hash_init\n"));
2bd0ea18 282 hashtab->size = hsize;
0f012a4c 283 hashtab->byhash = (dir_hash_ent_t**)((char *)hashtab +
33165ec3 284 sizeof(dir_hash_tab_t));
0f012a4c 285 hashtab->byaddr = (dir_hash_ent_t**)((char *)hashtab +
33165ec3 286 sizeof(dir_hash_tab_t) + sizeof(dir_hash_ent_t*) * hsize);
2bd0ea18
NS
287 return hashtab;
288}
289
290static int
291dir_hash_see(
292 dir_hash_tab_t *hashtab,
293 xfs_dahash_t hash,
294 xfs_dir2_dataptr_t addr)
295{
296 int i;
297 dir_hash_ent_t *p;
298
299 i = DIR_HASH_FUNC(hashtab, addr);
33165ec3
BN
300 for (p = hashtab->byaddr[i]; p; p = p->nextbyaddr) {
301 if (p->address != addr)
2bd0ea18
NS
302 continue;
303 if (p->seen)
304 return DIR_HASH_CK_DUPLEAF;
33165ec3 305 if (p->junkit == 0 && p->hashval != hash)
2bd0ea18
NS
306 return DIR_HASH_CK_BADHASH;
307 p->seen = 1;
308 return DIR_HASH_CK_OK;
309 }
310 return DIR_HASH_CK_NODATA;
311}
312
33165ec3
BN
313/*
314 * checks to make sure leafs match a data entry, and that the stale
315 * count is valid.
316 */
2bd0ea18
NS
317static int
318dir_hash_see_all(
319 dir_hash_tab_t *hashtab,
320 xfs_dir2_leaf_entry_t *ents,
321 int count,
322 int stale)
323{
324 int i;
325 int j;
326 int rval;
327
328 for (i = j = 0; i < count; i++) {
5e656dbb 329 if (be32_to_cpu(ents[i].address) == XFS_DIR2_NULL_DATAPTR) {
2bd0ea18
NS
330 j++;
331 continue;
332 }
5e656dbb
BN
333 rval = dir_hash_see(hashtab, be32_to_cpu(ents[i].hashval),
334 be32_to_cpu(ents[i].address));
2bd0ea18
NS
335 if (rval != DIR_HASH_CK_OK)
336 return rval;
337 }
338 return j == stale ? DIR_HASH_CK_OK : DIR_HASH_CK_BADSTALE;
339}
340
64c54486 341/*
33165ec3
BN
342 * Convert name pointers into locally allocated memory.
343 * This must only be done after all the entries have been added.
64c54486 344 */
33165ec3
BN
345static void
346dir_hash_dup_names(dir_hash_tab_t *hashtab)
64c54486 347{
56b2de80 348 unsigned char *name;
33165ec3 349 dir_hash_ent_t *p;
0f012a4c 350
33165ec3
BN
351 if (hashtab->names_duped)
352 return;
0f012a4c 353
33165ec3 354 for (p = hashtab->first; p; p = p->nextbyorder) {
5e656dbb
BN
355 name = malloc(p->name.len);
356 memcpy(name, p->name.name, p->name.len);
357 p->name.name = name;
64c54486 358 }
33165ec3 359 hashtab->names_duped = 1;
64c54486
BN
360}
361
2bd0ea18 362/*
5e656dbb
BN
363 * Given a block number in a fork, return the next valid block number
364 * (not a hole).
365 * If this is the last block number then NULLFILEOFF is returned.
366 *
367 * This was originally in the kernel, but only used in xfs_repair.
368 */
2bd0ea18 369static int
5e656dbb
BN
370bmap_next_offset(
371 xfs_trans_t *tp, /* transaction pointer */
372 xfs_inode_t *ip, /* incore inode */
373 xfs_fileoff_t *bnop, /* current block */
374 int whichfork) /* data or attr fork */
2bd0ea18 375{
5e656dbb
BN
376 xfs_fileoff_t bno; /* current block */
377 int eof; /* hit end of file */
378 int error; /* error return value */
379 xfs_bmbt_irec_t got; /* current extent value */
380 xfs_ifork_t *ifp; /* inode fork pointer */
381 xfs_extnum_t lastx; /* last extent used */
382 xfs_bmbt_irec_t prev; /* previous extent value */
383
384 if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE &&
385 XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
386 XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL)
387 return EIO;
388 if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) {
389 *bnop = NULLFILEOFF;
390 return 0;
391 }
392 ifp = XFS_IFORK_PTR(ip, whichfork);
393 if (!(ifp->if_flags & XFS_IFEXTENTS) &&
394 (error = xfs_iread_extents(tp, ip, whichfork)))
395 return error;
396 bno = *bnop + 1;
397 xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got, &prev);
398 if (eof)
399 *bnop = NULLFILEOFF;
2bd0ea18 400 else
5e656dbb
BN
401 *bnop = got.br_startoff < bno ? bno : got.br_startoff;
402 return 0;
2bd0ea18
NS
403}
404
405
406static void
407res_failed(
408 int err)
409{
410 if (err == ENOSPC) {
507f4e33 411 do_error(_("ran out of disk space!\n"));
2bd0ea18 412 } else
507f4e33 413 do_error(_("xfs_trans_reserve returned %d\n"), err);
2bd0ea18
NS
414}
415
416void
417mk_rbmino(xfs_mount_t *mp)
418{
419 xfs_trans_t *tp;
420 xfs_inode_t *ip;
421 xfs_bmbt_irec_t *ep;
422 xfs_fsblock_t first;
423 int i;
424 int nmap;
425 int committed;
426 int error;
427 xfs_bmap_free_t flist;
428 xfs_dfiloff_t bno;
429 xfs_bmbt_irec_t map[XFS_BMAP_MAX_NMAP];
41ce5f36
DC
430 int vers;
431 int times;
2bd0ea18
NS
432
433 /*
434 * first set up inode
435 */
436 tp = libxfs_trans_alloc(mp, 0);
437
27527004 438 if ((i = libxfs_trans_reserve(tp, 10, 0, 0, 0, 0)))
2bd0ea18
NS
439 res_failed(i);
440
46eca962 441 error = libxfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0, 0, &ip);
2bd0ea18 442 if (error) {
507f4e33
NS
443 do_error(
444 _("couldn't iget realtime bitmap inode -- error - %d\n"),
2bd0ea18
NS
445 error);
446 }
447
41ce5f36 448 vers = xfs_sb_version_hascrc(&mp->m_sb) ? 3 : 1;
9b2e78a0 449 memset(&ip->i_d, 0, xfs_icdinode_size(vers));
2bd0ea18
NS
450
451 ip->i_d.di_magic = XFS_DINODE_MAGIC;
322f2a29 452 ip->i_d.di_mode = S_IFREG;
41ce5f36 453 ip->i_d.di_version = vers;
2bd0ea18
NS
454 ip->i_d.di_format = XFS_DINODE_FMT_EXTENTS;
455 ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
456
457 ip->i_d.di_nlink = 1; /* account for sb ptr */
458
41ce5f36
DC
459 times = XFS_ICHGTIME_CHG | XFS_ICHGTIME_MOD;
460 if (ip->i_d.di_version == 3) {
461 ip->i_d.di_crc = 0;
462 ip->i_d.di_changecount = 1;
463 ip->i_d.di_lsn = 0;
464 ip->i_d.di_flags2 = 0;
465 ip->i_d.di_ino = mp->m_sb.sb_rbmino;
466 memset(&(ip->i_d.di_pad2[0]), 0, sizeof(ip->i_d.di_pad2));
467 platform_uuid_copy(&ip->i_d.di_uuid, &mp->m_sb.sb_uuid);
468 times |= XFS_ICHGTIME_CREATE;
469 }
470 libxfs_trans_ichgtime(tp, ip, times);
471
2bd0ea18
NS
472 /*
473 * now the ifork
474 */
475 ip->i_df.if_flags = XFS_IFEXTENTS;
476 ip->i_df.if_bytes = ip->i_df.if_real_bytes = 0;
477 ip->i_df.if_u1.if_extents = NULL;
478
479 ip->i_d.di_size = mp->m_sb.sb_rbmblocks * mp->m_sb.sb_blocksize;
480
481 /*
482 * commit changes
483 */
484 libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
485 libxfs_trans_ihold(tp, ip);
5e656dbb 486 libxfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_SYNC);
2bd0ea18
NS
487
488 /*
489 * then allocate blocks for file and fill with zeroes (stolen
490 * from mkfs)
491 */
492 tp = libxfs_trans_alloc(mp, 0);
27527004
NS
493 if ((error = libxfs_trans_reserve(tp, mp->m_sb.sb_rbmblocks +
494 (XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) - 1), 0, 0, 0, 0)))
2bd0ea18
NS
495 res_failed(error);
496
497 libxfs_trans_ijoin(tp, ip, 0);
498 bno = 0;
56b2de80 499 xfs_bmap_init(&flist, &first);
2bd0ea18
NS
500 while (bno < mp->m_sb.sb_rbmblocks) {
501 nmap = XFS_BMAP_MAX_NMAP;
a2ceac1f 502 error = libxfs_bmapi_write(tp, ip, bno,
2bd0ea18 503 (xfs_extlen_t)(mp->m_sb.sb_rbmblocks - bno),
a2ceac1f 504 0, &first, mp->m_sb.sb_rbmblocks,
56b2de80 505 map, &nmap, &flist);
2bd0ea18 506 if (error) {
507f4e33
NS
507 do_error(
508 _("couldn't allocate realtime bitmap, error = %d\n"),
2bd0ea18
NS
509 error);
510 }
511 for (i = 0, ep = map; i < nmap; i++, ep++) {
75c8b434 512 libxfs_device_zero(mp->m_ddev_targp,
2bd0ea18
NS
513 XFS_FSB_TO_DADDR(mp, ep->br_startblock),
514 XFS_FSB_TO_BB(mp, ep->br_blockcount));
515 bno += ep->br_blockcount;
516 }
517 }
5e656dbb 518 error = libxfs_bmap_finish(&tp, &flist, &committed);
2bd0ea18
NS
519 if (error) {
520 do_error(
507f4e33 521 _("allocation of the realtime bitmap failed, error = %d\n"),
2bd0ea18
NS
522 error);
523 }
5e656dbb 524 libxfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_SYNC);
2bd0ea18
NS
525}
526
8b8a6b02 527static int
2bd0ea18
NS
528fill_rbmino(xfs_mount_t *mp)
529{
530 xfs_buf_t *bp;
531 xfs_trans_t *tp;
532 xfs_inode_t *ip;
533 xfs_rtword_t *bmp;
534 xfs_fsblock_t first;
535 int nmap;
536 int error;
537 xfs_dfiloff_t bno;
538 xfs_bmbt_irec_t map;
539
540 bmp = btmcompute;
541 bno = 0;
542
543 tp = libxfs_trans_alloc(mp, 0);
544
27527004 545 if ((error = libxfs_trans_reserve(tp, 10, 0, 0, 0, 0)))
2bd0ea18
NS
546 res_failed(error);
547
46eca962 548 error = libxfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0, 0, &ip);
2bd0ea18 549 if (error) {
507f4e33
NS
550 do_error(
551 _("couldn't iget realtime bitmap inode -- error - %d\n"),
2bd0ea18
NS
552 error);
553 }
554
555 while (bno < mp->m_sb.sb_rbmblocks) {
556 /*
557 * fill the file one block at a time
558 */
559 nmap = 1;
a2ceac1f 560 error = libxfs_bmapi_write(tp, ip, bno, 1, 0,
56b2de80 561 &first, 1, &map, &nmap, NULL);
2bd0ea18
NS
562 if (error || nmap != 1) {
563 do_error(
5d1b7f0f 564 _("couldn't map realtime bitmap block %" PRIu64 ", error = %d\n"),
2bd0ea18
NS
565 bno, error);
566 }
567
568 ASSERT(map.br_startblock != HOLESTARTBLOCK);
569
570 error = libxfs_trans_read_buf(
571 mp, tp, mp->m_dev,
dfc130f3 572 XFS_FSB_TO_DADDR(mp, map.br_startblock),
a2ceac1f 573 XFS_FSB_TO_BB(mp, 1), 1, &bp, NULL);
2bd0ea18
NS
574
575 if (error) {
576 do_warn(
5d1b7f0f 577_("can't access block %" PRIu64 " (fsbno %" PRIu64 ") of realtime bitmap inode %" PRIu64 "\n"),
2bd0ea18
NS
578 bno, map.br_startblock, mp->m_sb.sb_rbmino);
579 return(1);
580 }
581
dab9b8d6 582 memmove(XFS_BUF_PTR(bp), bmp, mp->m_sb.sb_blocksize);
2bd0ea18
NS
583
584 libxfs_trans_log_buf(tp, bp, 0, mp->m_sb.sb_blocksize - 1);
585
586 bmp = (xfs_rtword_t *)((__psint_t) bmp + mp->m_sb.sb_blocksize);
587 bno++;
588 }
589
5e656dbb 590 libxfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_SYNC);
2bd0ea18
NS
591 return(0);
592}
593
8b8a6b02 594static int
2bd0ea18
NS
595fill_rsumino(xfs_mount_t *mp)
596{
597 xfs_buf_t *bp;
598 xfs_trans_t *tp;
599 xfs_inode_t *ip;
600 xfs_suminfo_t *smp;
601 xfs_fsblock_t first;
602 int nmap;
603 int error;
604 xfs_dfiloff_t bno;
605 xfs_dfiloff_t end_bno;
606 xfs_bmbt_irec_t map;
607
608 smp = sumcompute;
609 bno = 0;
610 end_bno = mp->m_rsumsize >> mp->m_sb.sb_blocklog;
611
612 tp = libxfs_trans_alloc(mp, 0);
613
27527004 614 if ((error = libxfs_trans_reserve(tp, 10, 0, 0, 0, 0)))
2bd0ea18
NS
615 res_failed(error);
616
46eca962 617 error = libxfs_trans_iget(mp, tp, mp->m_sb.sb_rsumino, 0, 0, &ip);
2bd0ea18 618 if (error) {
507f4e33
NS
619 do_error(
620 _("couldn't iget realtime summary inode -- error - %d\n"),
2bd0ea18
NS
621 error);
622 }
623
624 while (bno < end_bno) {
625 /*
626 * fill the file one block at a time
627 */
628 nmap = 1;
a2ceac1f 629 error = libxfs_bmapi_write(tp, ip, bno, 1, 0,
56b2de80 630 &first, 1, &map, &nmap, NULL);
2bd0ea18
NS
631 if (error || nmap != 1) {
632 do_error(
5d1b7f0f 633 _("couldn't map realtime summary inode block %" PRIu64 ", error = %d\n"),
2bd0ea18
NS
634 bno, error);
635 }
636
637 ASSERT(map.br_startblock != HOLESTARTBLOCK);
638
639 error = libxfs_trans_read_buf(
640 mp, tp, mp->m_dev,
dfc130f3 641 XFS_FSB_TO_DADDR(mp, map.br_startblock),
a2ceac1f 642 XFS_FSB_TO_BB(mp, 1), 1, &bp, NULL);
2bd0ea18
NS
643
644 if (error) {
645 do_warn(
5d1b7f0f 646_("can't access block %" PRIu64 " (fsbno %" PRIu64 ") of realtime summary inode %" PRIu64 "\n"),
2bd0ea18
NS
647 bno, map.br_startblock, mp->m_sb.sb_rsumino);
648 return(1);
649 }
650
dab9b8d6 651 memmove(XFS_BUF_PTR(bp), smp, mp->m_sb.sb_blocksize);
2bd0ea18
NS
652
653 libxfs_trans_log_buf(tp, bp, 0, mp->m_sb.sb_blocksize - 1);
654
655 smp = (xfs_suminfo_t *)((__psint_t)smp + mp->m_sb.sb_blocksize);
656 bno++;
657 }
658
5e656dbb 659 libxfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_SYNC);
2bd0ea18
NS
660 return(0);
661}
662
8b8a6b02 663static void
2bd0ea18
NS
664mk_rsumino(xfs_mount_t *mp)
665{
666 xfs_trans_t *tp;
667 xfs_inode_t *ip;
668 xfs_bmbt_irec_t *ep;
669 xfs_fsblock_t first;
670 int i;
671 int nmap;
672 int committed;
673 int error;
674 int nsumblocks;
675 xfs_bmap_free_t flist;
676 xfs_dfiloff_t bno;
677 xfs_bmbt_irec_t map[XFS_BMAP_MAX_NMAP];
41ce5f36
DC
678 int vers;
679 int times;
2bd0ea18
NS
680
681 /*
682 * first set up inode
683 */
684 tp = libxfs_trans_alloc(mp, 0);
685
27527004
NS
686 if ((i = libxfs_trans_reserve(tp, 10, XFS_ICHANGE_LOG_RES(mp), 0,
687 XFS_TRANS_PERM_LOG_RES, XFS_MKDIR_LOG_COUNT)))
2bd0ea18
NS
688 res_failed(i);
689
46eca962 690 error = libxfs_trans_iget(mp, tp, mp->m_sb.sb_rsumino, 0, 0, &ip);
2bd0ea18 691 if (error) {
507f4e33
NS
692 do_error(
693 _("couldn't iget realtime summary inode -- error - %d\n"),
2bd0ea18
NS
694 error);
695 }
696
41ce5f36 697 vers = xfs_sb_version_hascrc(&mp->m_sb) ? 3 : 1;
9b2e78a0 698 memset(&ip->i_d, 0, xfs_icdinode_size(vers));
2bd0ea18
NS
699
700 ip->i_d.di_magic = XFS_DINODE_MAGIC;
322f2a29 701 ip->i_d.di_mode = S_IFREG;
41ce5f36 702 ip->i_d.di_version = vers;
2bd0ea18
NS
703 ip->i_d.di_format = XFS_DINODE_FMT_EXTENTS;
704 ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
705
706 ip->i_d.di_nlink = 1; /* account for sb ptr */
707
41ce5f36
DC
708 times = XFS_ICHGTIME_CHG | XFS_ICHGTIME_MOD;
709 if (ip->i_d.di_version == 3) {
710 ip->i_d.di_crc = 0;
711 ip->i_d.di_changecount = 1;
712 ip->i_d.di_lsn = 0;
713 ip->i_d.di_flags2 = 0;
714 ip->i_d.di_ino = mp->m_sb.sb_rsumino;
715 memset(&(ip->i_d.di_pad2[0]), 0, sizeof(ip->i_d.di_pad2));
716 platform_uuid_copy(&ip->i_d.di_uuid, &mp->m_sb.sb_uuid);
717 times |= XFS_ICHGTIME_CREATE;
718 }
719 libxfs_trans_ichgtime(tp, ip, times);
720
2bd0ea18
NS
721 /*
722 * now the ifork
723 */
724 ip->i_df.if_flags = XFS_IFEXTENTS;
725 ip->i_df.if_bytes = ip->i_df.if_real_bytes = 0;
726 ip->i_df.if_u1.if_extents = NULL;
727
728 ip->i_d.di_size = mp->m_rsumsize;
729
730 /*
731 * commit changes
732 */
733 libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
734 libxfs_trans_ihold(tp, ip);
5e656dbb 735 libxfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_SYNC);
2bd0ea18
NS
736
737 /*
738 * then allocate blocks for file and fill with zeroes (stolen
739 * from mkfs)
740 */
741 tp = libxfs_trans_alloc(mp, 0);
56b2de80 742 xfs_bmap_init(&flist, &first);
2bd0ea18
NS
743
744 nsumblocks = mp->m_rsumsize >> mp->m_sb.sb_blocklog;
27527004 745 if ((error = libxfs_trans_reserve(tp,
2bd0ea18
NS
746 mp->m_sb.sb_rbmblocks +
747 (XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) - 1),
748 BBTOB(128), 0, XFS_TRANS_PERM_LOG_RES,
27527004 749 XFS_DEFAULT_PERM_LOG_COUNT)))
2bd0ea18
NS
750 res_failed(error);
751
752 libxfs_trans_ijoin(tp, ip, 0);
753 bno = 0;
56b2de80 754 xfs_bmap_init(&flist, &first);
2bd0ea18
NS
755 while (bno < nsumblocks) {
756 nmap = XFS_BMAP_MAX_NMAP;
a2ceac1f 757 error = libxfs_bmapi_write(tp, ip, bno,
2bd0ea18 758 (xfs_extlen_t)(nsumblocks - bno),
a2ceac1f 759 0, &first, nsumblocks, map, &nmap, &flist);
2bd0ea18
NS
760 if (error) {
761 do_error(
507f4e33 762 _("couldn't allocate realtime summary inode, error = %d\n"),
2bd0ea18
NS
763 error);
764 }
765 for (i = 0, ep = map; i < nmap; i++, ep++) {
75c8b434 766 libxfs_device_zero(mp->m_ddev_targp,
2bd0ea18
NS
767 XFS_FSB_TO_DADDR(mp, ep->br_startblock),
768 XFS_FSB_TO_BB(mp, ep->br_blockcount));
2bd0ea18
NS
769 bno += ep->br_blockcount;
770 }
771 }
5e656dbb 772 error = libxfs_bmap_finish(&tp, &flist, &committed);
2bd0ea18
NS
773 if (error) {
774 do_error(
507f4e33 775 _("allocation of the realtime summary ino failed, error = %d\n"),
2bd0ea18
NS
776 error);
777 }
5e656dbb 778 libxfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_SYNC);
2bd0ea18
NS
779}
780
781/*
782 * makes a new root directory.
783 */
8b8a6b02 784static void
2bd0ea18
NS
785mk_root_dir(xfs_mount_t *mp)
786{
787 xfs_trans_t *tp;
788 xfs_inode_t *ip;
789 int i;
790 int error;
791 const mode_t mode = 0755;
69ec88b5 792 ino_tree_node_t *irec;
41ce5f36
DC
793 int vers;
794 int times;
2bd0ea18 795
5e656dbb
BN
796 ASSERT(xfs_sb_version_hasdirv2(&mp->m_sb));
797
2bd0ea18
NS
798 tp = libxfs_trans_alloc(mp, 0);
799 ip = NULL;
800
27527004
NS
801 if ((i = libxfs_trans_reserve(tp, 10, XFS_ICHANGE_LOG_RES(mp), 0,
802 XFS_TRANS_PERM_LOG_RES, XFS_MKDIR_LOG_COUNT)))
2bd0ea18
NS
803 res_failed(i);
804
46eca962 805 error = libxfs_trans_iget(mp, tp, mp->m_sb.sb_rootino, 0, 0, &ip);
2bd0ea18 806 if (error) {
507f4e33 807 do_error(_("could not iget root inode -- error - %d\n"), error);
2bd0ea18
NS
808 }
809
810 /*
811 * take care of the core -- initialization from xfs_ialloc()
812 */
41ce5f36 813 vers = xfs_sb_version_hascrc(&mp->m_sb) ? 3 : 1;
9b2e78a0 814 memset(&ip->i_d, 0, xfs_icdinode_size(vers));
2bd0ea18
NS
815
816 ip->i_d.di_magic = XFS_DINODE_MAGIC;
322f2a29 817 ip->i_d.di_mode = (__uint16_t) mode|S_IFDIR;
41ce5f36 818 ip->i_d.di_version = vers;
2bd0ea18
NS
819 ip->i_d.di_format = XFS_DINODE_FMT_EXTENTS;
820 ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
821
822 ip->i_d.di_nlink = 1; /* account for . */
823
41ce5f36
DC
824 times = XFS_ICHGTIME_CHG | XFS_ICHGTIME_MOD;
825 if (ip->i_d.di_version == 3) {
826 ip->i_d.di_crc = 0;
827 ip->i_d.di_changecount = 1;
828 ip->i_d.di_lsn = 0;
829 ip->i_d.di_flags2 = 0;
830 ip->i_d.di_ino = mp->m_sb.sb_rootino;
831 memset(&(ip->i_d.di_pad2[0]), 0, sizeof(ip->i_d.di_pad2));
832 platform_uuid_copy(&ip->i_d.di_uuid, &mp->m_sb.sb_uuid);
833 times |= XFS_ICHGTIME_CREATE;
834 }
835 libxfs_trans_ichgtime(tp, ip, times);
836
2bd0ea18
NS
837 libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
838
839 /*
840 * now the ifork
841 */
842 ip->i_df.if_flags = XFS_IFEXTENTS;
843 ip->i_df.if_bytes = ip->i_df.if_real_bytes = 0;
844 ip->i_df.if_u1.if_extents = NULL;
845
846 mp->m_rootip = ip;
847
848 /*
849 * initialize the directory
850 */
5e656dbb 851 libxfs_dir_init(tp, ip, ip);
2bd0ea18 852
5e656dbb 853 libxfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_SYNC);
69ec88b5 854
1ae311d5 855 irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, mp->m_sb.sb_rootino),
69ec88b5
BN
856 XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rootino));
857 set_inode_isadir(irec, XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rootino) -
858 irec->ino_startnum);
2bd0ea18
NS
859}
860
861/*
862 * orphanage name == lost+found
863 */
8b8a6b02 864static xfs_ino_t
2bd0ea18
NS
865mk_orphanage(xfs_mount_t *mp)
866{
867 xfs_ino_t ino;
868 xfs_trans_t *tp;
869 xfs_inode_t *ip;
870 xfs_inode_t *pip;
871 xfs_fsblock_t first;
198b747f
CM
872 ino_tree_node_t *irec;
873 int ino_offset = 0;
2bd0ea18
NS
874 int i;
875 int committed;
876 int error;
877 xfs_bmap_free_t flist;
878 const int mode = 0755;
2bd0ea18 879 int nres;
5e656dbb
BN
880 struct xfs_name xname;
881
882 ASSERT(xfs_sb_version_hasdirv2(&mp->m_sb));
2bd0ea18 883
6c39a3cb
BN
884 /*
885 * check for an existing lost+found first, if it exists, return
ff1f79a7 886 * its inode. Otherwise, we can create it. Bad lost+found inodes
6c39a3cb
BN
887 * would have been cleared in phase3 and phase4.
888 */
889
890 if ((i = libxfs_iget(mp, NULL, mp->m_sb.sb_rootino, 0, &pip, 0)))
891 do_error(_("%d - couldn't iget root inode to obtain %s\n"),
892 i, ORPHANAGE);
893
56b2de80 894 xname.name = (unsigned char *)ORPHANAGE;
5e656dbb
BN
895 xname.len = strlen(ORPHANAGE);
896 if (libxfs_dir_lookup(NULL, pip, &xname, &ino, NULL) == 0)
6c39a3cb
BN
897 return ino;
898
899 /*
900 * could not be found, create it
901 */
902
2bd0ea18 903 tp = libxfs_trans_alloc(mp, 0);
56b2de80 904 xfs_bmap_init(&flist, &first);
2bd0ea18 905
5e656dbb 906 nres = XFS_MKDIR_SPACE_RES(mp, xname.len);
27527004
NS
907 if ((i = libxfs_trans_reserve(tp, nres, XFS_MKDIR_LOG_RES(mp), 0,
908 XFS_TRANS_PERM_LOG_RES, XFS_MKDIR_LOG_COUNT)))
2bd0ea18
NS
909 res_failed(i);
910
911 /*
912 * use iget/ijoin instead of trans_iget because the ialloc
913 * wrapper can commit the transaction and start a new one
914 */
6c39a3cb 915/* if ((i = libxfs_iget(mp, NULL, mp->m_sb.sb_rootino, 0, &pip, 0)))
507f4e33 916 do_error(_("%d - couldn't iget root inode to make %s\n"),
6c39a3cb 917 i, ORPHANAGE);*/
2bd0ea18 918
322f2a29 919 error = libxfs_inode_alloc(&tp, pip, mode|S_IFDIR,
9f064b7e 920 1, 0, &zerocr, &zerofsx, &ip);
2bd0ea18 921 if (error) {
507f4e33 922 do_error(_("%s inode allocation failed %d\n"),
2bd0ea18
NS
923 ORPHANAGE, error);
924 }
2bd0ea18 925 ip->i_d.di_nlink++; /* account for . */
198b747f
CM
926 ino = ip->i_ino;
927
928 irec = find_inode_rec(mp,
929 XFS_INO_TO_AGNO(mp, ino),
930 XFS_INO_TO_AGINO(mp, ino));
931 ino_offset = get_inode_offset(mp, ino, irec);
932
933 /*
934 * Mark the inode allocated to lost+found as used in the AVL tree
935 * so it is not skipped in phase 7
936 */
937 set_inode_used(irec, ino_offset);
938 add_inode_ref(irec, ino_offset);
2bd0ea18
NS
939
940 /*
941 * now that we know the transaction will stay around,
942 * add the root inode to it
943 */
944 libxfs_trans_ijoin(tp, pip, 0);
945
946 /*
947 * create the actual entry
948 */
5e656dbb
BN
949 error = libxfs_dir_createname(tp, pip, &xname, ip->i_ino, &first,
950 &flist, nres);
951 if (error)
6c39a3cb
BN
952 do_error(
953 _("can't make %s, createname error %d\n"),
2bd0ea18 954 ORPHANAGE, error);
2bd0ea18 955
dfc130f3 956 /*
2bd0ea18
NS
957 * bump up the link count in the root directory to account
958 * for .. in the new directory
959 */
960 pip->i_d.di_nlink++;
1ae311d5
LC
961 add_inode_ref(find_inode_rec(mp,
962 XFS_INO_TO_AGNO(mp, mp->m_sb.sb_rootino),
6c39a3cb
BN
963 XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rootino)), 0);
964
2bd0ea18 965
198b747f 966
2bd0ea18 967 libxfs_trans_log_inode(tp, pip, XFS_ILOG_CORE);
5e656dbb 968 libxfs_dir_init(tp, ip, pip);
2bd0ea18
NS
969 libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
970
5e656dbb 971 error = libxfs_bmap_finish(&tp, &flist, &committed);
2bd0ea18 972 if (error) {
507f4e33 973 do_error(_("%s directory creation failed -- bmapf error %d\n"),
2bd0ea18
NS
974 ORPHANAGE, error);
975 }
976
2bd0ea18 977
5e656dbb 978 libxfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_SYNC);
198b747f 979 add_inode_reached(irec,ino_offset);
2bd0ea18 980
2bd0ea18
NS
981 return(ino);
982}
983
984/*
6c39a3cb 985 * move a file to the orphange.
2bd0ea18 986 */
6c39a3cb
BN
987static void
988mv_orphanage(
989 xfs_mount_t *mp,
990 xfs_ino_t ino, /* inode # to be moved */
991 int isa_dir) /* 1 if inode is a directory */
2bd0ea18 992{
2556c98b 993 xfs_inode_t *orphanage_ip;
6c39a3cb
BN
994 xfs_ino_t entry_ino_num;
995 xfs_inode_t *ino_p;
996 xfs_trans_t *tp;
997 xfs_fsblock_t first;
998 xfs_bmap_free_t flist;
999 int err;
1000 int committed;
56b2de80 1001 unsigned char fname[MAXPATHLEN + 1];
6c39a3cb
BN
1002 int nres;
1003 int incr;
1004 ino_tree_node_t *irec;
1005 int ino_offset = 0;
5e656dbb
BN
1006 struct xfs_name xname;
1007
1008 ASSERT(xfs_sb_version_hasdirv2(&mp->m_sb));
2bd0ea18 1009
5e656dbb 1010 xname.name = fname;
56b2de80 1011 xname.len = snprintf((char *)fname, sizeof(fname), "%llu",
5e656dbb 1012 (unsigned long long)ino);
2bd0ea18 1013
2556c98b
BN
1014 err = libxfs_iget(mp, NULL, orphanage_ino, 0, &orphanage_ip, 0);
1015 if (err)
1016 do_error(_("%d - couldn't iget orphanage inode\n"), err);
6c39a3cb
BN
1017 /*
1018 * Make sure the filename is unique in the lost+found
1019 */
1020 incr = 0;
5e656dbb
BN
1021 while (libxfs_dir_lookup(NULL, orphanage_ip, &xname, &entry_ino_num,
1022 NULL) == 0)
56b2de80 1023 xname.len = snprintf((char *)fname, sizeof(fname), "%llu.%d",
5e656dbb 1024 (unsigned long long)ino, ++incr);
2bd0ea18
NS
1025
1026 tp = libxfs_trans_alloc(mp, 0);
1027
27527004 1028 if ((err = libxfs_iget(mp, NULL, ino, 0, &ino_p, 0)))
507f4e33 1029 do_error(_("%d - couldn't iget disconnected inode\n"), err);
2bd0ea18
NS
1030
1031 if (isa_dir) {
1ae311d5 1032 irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, orphanage_ino),
6c39a3cb
BN
1033 XFS_INO_TO_AGINO(mp, orphanage_ino));
1034 if (irec)
1035 ino_offset = XFS_INO_TO_AGINO(mp, orphanage_ino) -
1036 irec->ino_startnum;
1037 nres = XFS_DIRENTER_SPACE_RES(mp, fnamelen) +
2bd0ea18 1038 XFS_DIRENTER_SPACE_RES(mp, 2);
5e656dbb
BN
1039 err = libxfs_dir_lookup(tp, ino_p, &xfs_name_dotdot,
1040 &entry_ino_num, NULL);
6c39a3cb 1041 if (err) {
2bd0ea18
NS
1042 ASSERT(err == ENOENT);
1043
27527004 1044 if ((err = libxfs_trans_reserve(tp, nres,
2bd0ea18
NS
1045 XFS_RENAME_LOG_RES(mp), 0,
1046 XFS_TRANS_PERM_LOG_RES,
27527004 1047 XFS_RENAME_LOG_COUNT)))
2bd0ea18 1048 do_error(
507f4e33 1049 _("space reservation failed (%d), filesystem may be out of space\n"),
2bd0ea18
NS
1050 err);
1051
6c39a3cb 1052 libxfs_trans_ijoin(tp, orphanage_ip, 0);
2bd0ea18
NS
1053 libxfs_trans_ijoin(tp, ino_p, 0);
1054
56b2de80 1055 xfs_bmap_init(&flist, &first);
5e656dbb
BN
1056 err = libxfs_dir_createname(tp, orphanage_ip, &xname,
1057 ino, &first, &flist, nres);
1058 if (err)
2bd0ea18 1059 do_error(
507f4e33 1060 _("name create failed in %s (%d), filesystem may be out of space\n"),
2bd0ea18
NS
1061 ORPHANAGE, err);
1062
6c39a3cb
BN
1063 if (irec)
1064 add_inode_ref(irec, ino_offset);
1065 else
1066 orphanage_ip->i_d.di_nlink++;
1067 libxfs_trans_log_inode(tp, orphanage_ip, XFS_ILOG_CORE);
2bd0ea18 1068
5e656dbb
BN
1069 err = libxfs_dir_createname(tp, ino_p, &xfs_name_dotdot,
1070 orphanage_ino, &first, &flist, nres);
1071 if (err)
2bd0ea18 1072 do_error(
507f4e33 1073 _("creation of .. entry failed (%d), filesystem may be out of space\n"),
2bd0ea18
NS
1074 err);
1075
1076 ino_p->i_d.di_nlink++;
1077 libxfs_trans_log_inode(tp, ino_p, XFS_ILOG_CORE);
1078
5e656dbb
BN
1079 err = libxfs_bmap_finish(&tp, &flist, &committed);
1080 if (err)
2bd0ea18 1081 do_error(
507f4e33 1082 _("bmap finish failed (err - %d), filesystem may be out of space\n"),
2bd0ea18
NS
1083 err);
1084
1085 libxfs_trans_commit(tp,
5e656dbb 1086 XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_SYNC);
2bd0ea18 1087 } else {
27527004 1088 if ((err = libxfs_trans_reserve(tp, nres,
2bd0ea18
NS
1089 XFS_RENAME_LOG_RES(mp), 0,
1090 XFS_TRANS_PERM_LOG_RES,
27527004 1091 XFS_RENAME_LOG_COUNT)))
2bd0ea18 1092 do_error(
507f4e33 1093 _("space reservation failed (%d), filesystem may be out of space\n"),
2bd0ea18
NS
1094 err);
1095
6c39a3cb 1096 libxfs_trans_ijoin(tp, orphanage_ip, 0);
2bd0ea18
NS
1097 libxfs_trans_ijoin(tp, ino_p, 0);
1098
56b2de80 1099 xfs_bmap_init(&flist, &first);
2bd0ea18 1100
5e656dbb
BN
1101 err = libxfs_dir_createname(tp, orphanage_ip, &xname,
1102 ino, &first, &flist, nres);
1103 if (err)
2bd0ea18 1104 do_error(
507f4e33 1105 _("name create failed in %s (%d), filesystem may be out of space\n"),
2bd0ea18
NS
1106 ORPHANAGE, err);
1107
6c39a3cb
BN
1108 if (irec)
1109 add_inode_ref(irec, ino_offset);
1110 else
1111 orphanage_ip->i_d.di_nlink++;
1112 libxfs_trans_log_inode(tp, orphanage_ip, XFS_ILOG_CORE);
2bd0ea18
NS
1113
1114 /*
1115 * don't replace .. value if it already points
1116 * to us. that'll pop a libxfs/kernel ASSERT.
1117 */
6c39a3cb 1118 if (entry_ino_num != orphanage_ino) {
5e656dbb
BN
1119 err = libxfs_dir_replace(tp, ino_p,
1120 &xfs_name_dotdot, orphanage_ino,
1121 &first, &flist, nres);
1122 if (err)
2bd0ea18 1123 do_error(
507f4e33 1124 _("name replace op failed (%d), filesystem may be out of space\n"),
2bd0ea18
NS
1125 err);
1126 }
1127
5e656dbb
BN
1128 err = libxfs_bmap_finish(&tp, &flist, &committed);
1129 if (err)
2bd0ea18 1130 do_error(
507f4e33 1131 _("bmap finish failed (%d), filesystem may be out of space\n"),
2bd0ea18
NS
1132 err);
1133
1134 libxfs_trans_commit(tp,
5e656dbb 1135 XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_SYNC);
2bd0ea18 1136 }
6c39a3cb 1137
2bd0ea18
NS
1138 } else {
1139 /*
1140 * use the remove log reservation as that's
1141 * more accurate. we're only creating the
1142 * links, we're not doing the inode allocation
1143 * also accounted for in the create
1144 */
5e656dbb
BN
1145 nres = XFS_DIRENTER_SPACE_RES(mp, xname.len);
1146 err = libxfs_trans_reserve(tp, nres, XFS_REMOVE_LOG_RES(mp), 0,
1147 XFS_TRANS_PERM_LOG_RES, XFS_REMOVE_LOG_COUNT);
1148 if (err)
2bd0ea18 1149 do_error(
507f4e33 1150 _("space reservation failed (%d), filesystem may be out of space\n"),
2bd0ea18
NS
1151 err);
1152
6c39a3cb 1153 libxfs_trans_ijoin(tp, orphanage_ip, 0);
2bd0ea18
NS
1154 libxfs_trans_ijoin(tp, ino_p, 0);
1155
56b2de80 1156 xfs_bmap_init(&flist, &first);
5e656dbb
BN
1157 err = libxfs_dir_createname(tp, orphanage_ip, &xname, ino,
1158 &first, &flist, nres);
1159 if (err)
2bd0ea18 1160 do_error(
507f4e33 1161 _("name create failed in %s (%d), filesystem may be out of space\n"),
2bd0ea18
NS
1162 ORPHANAGE, err);
1163 ASSERT(err == 0);
1164
1165 ino_p->i_d.di_nlink = 1;
1166 libxfs_trans_log_inode(tp, ino_p, XFS_ILOG_CORE);
1167
5e656dbb
BN
1168 err = libxfs_bmap_finish(&tp, &flist, &committed);
1169 if (err)
2bd0ea18 1170 do_error(
507f4e33 1171 _("bmap finish failed (%d), filesystem may be out of space\n"),
2bd0ea18
NS
1172 err);
1173
5e656dbb 1174 libxfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_SYNC);
2bd0ea18
NS
1175 }
1176}
1177
6c39a3cb
BN
1178static int
1179entry_junked(
1180 const char *msg,
1181 const char *iname,
1182 xfs_ino_t ino1,
1183 xfs_ino_t ino2)
1184{
1185 do_warn(msg, iname, ino1, ino2);
1186 if (!no_modify) {
1187 if (verbose)
1188 do_warn(_(", marking entry to be junked\n"));
9a048535
DC
1189 else
1190 do_warn("\n");
1191 } else
1192 do_warn(_(", would junk entry\n"));
1193 return !no_modify;
2bd0ea18
NS
1194}
1195
33165ec3
BN
1196/*
1197 * Unexpected failure during the rebuild will leave the entries in
1198 * lost+found on the next run
1199 */
1200
0f012a4c 1201static void
33165ec3 1202longform_dir2_rebuild(
6fa00c33
BN
1203 xfs_mount_t *mp,
1204 xfs_ino_t ino,
1205 xfs_inode_t *ip,
1206 ino_tree_node_t *irec,
1207 int ino_offset,
1208 dir_hash_tab_t *hashtab)
33165ec3
BN
1209{
1210 int error;
1211 int nres;
1212 xfs_trans_t *tp;
1213 xfs_fileoff_t lastblock;
1214 xfs_fsblock_t firstblock;
1215 xfs_bmap_free_t flist;
2556c98b 1216 xfs_inode_t pip;
33165ec3
BN
1217 dir_hash_ent_t *p;
1218 int committed;
1219 int done;
0f012a4c
BN
1220
1221 /*
33165ec3
BN
1222 * trash directory completely and rebuild from scratch using the
1223 * name/inode pairs in the hash table
1224 */
0f012a4c 1225
5d1b7f0f 1226 do_warn(_("rebuilding directory inode %" PRIu64 "\n"), ino);
0f012a4c
BN
1227
1228 /*
6fa00c33
BN
1229 * first attempt to locate the parent inode, if it can't be
1230 * found, set it to the root inode and it'll be moved to the
1231 * orphanage later (the inode number here needs to be valid
5e656dbb 1232 * for the libxfs_dir_init() call).
33165ec3 1233 */
6fa00c33
BN
1234 pip.i_ino = get_inode_parent(irec, ino_offset);
1235 if (pip.i_ino == NULLFSINO)
1236 pip.i_ino = mp->m_sb.sb_rootino;
33165ec3 1237
56b2de80 1238 xfs_bmap_init(&flist, &firstblock);
0f012a4c 1239
33165ec3
BN
1240 tp = libxfs_trans_alloc(mp, 0);
1241 nres = XFS_REMOVE_SPACE_RES(mp);
1242 error = libxfs_trans_reserve(tp, nres, XFS_REMOVE_LOG_RES(mp), 0,
1243 XFS_TRANS_PERM_LOG_RES, XFS_REMOVE_LOG_COUNT);
1244 if (error)
1245 res_failed(error);
1246 libxfs_trans_ijoin(tp, ip, 0);
1247 libxfs_trans_ihold(tp, ip);
0f012a4c
BN
1248
1249 if ((error = libxfs_bmap_last_offset(tp, ip, &lastblock,
33165ec3 1250 XFS_DATA_FORK)))
0f012a4c 1251 do_error(_("xfs_bmap_last_offset failed -- error - %d\n"),
33165ec3 1252 error);
0f012a4c 1253
33165ec3 1254 /* free all data, leaf, node and freespace blocks */
5e656dbb 1255 error = libxfs_bunmapi(tp, ip, 0, lastblock, XFS_BMAPI_METADATA, 0,
56b2de80 1256 &firstblock, &flist, &done);
5e656dbb 1257 if (error) {
33165ec3
BN
1258 do_warn(_("xfs_bunmapi failed -- error - %d\n"), error);
1259 libxfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES |
1260 XFS_TRANS_ABORT);
1261 return;
1262 }
0f012a4c 1263
33165ec3
BN
1264 ASSERT(done);
1265
5e656dbb 1266 libxfs_dir_init(tp, ip, &pip);
0f012a4c 1267
5e656dbb 1268 error = libxfs_bmap_finish(&tp, &flist, &committed);
0f012a4c 1269
5e656dbb 1270 libxfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_SYNC);
0f012a4c 1271
33165ec3
BN
1272 /* go through the hash list and re-add the inodes */
1273
1274 for (p = hashtab->first; p; p = p->nextbyorder) {
0f012a4c 1275
5e656dbb
BN
1276 if (p->name.name[0] == '/' || (p->name.name[0] == '.' &&
1277 (p->name.len == 1 || (p->name.len == 2 &&
1278 p->name.name[1] == '.'))))
33165ec3 1279 continue;
0f012a4c 1280
33165ec3 1281 tp = libxfs_trans_alloc(mp, 0);
5e656dbb
BN
1282 nres = XFS_CREATE_SPACE_RES(mp, p->name.len);
1283 error = libxfs_trans_reserve(tp, nres, XFS_CREATE_LOG_RES(mp),
1284 0, XFS_TRANS_PERM_LOG_RES, XFS_CREATE_LOG_COUNT);
1285 if (error) {
33165ec3
BN
1286 do_warn(
1287 _("space reservation failed (%d), filesystem may be out of space\n"),
1288 error);
1289 break;
1290 }
1291
1292 libxfs_trans_ijoin(tp, ip, 0);
1293 libxfs_trans_ihold(tp, ip);
1294
56b2de80 1295 xfs_bmap_init(&flist, &firstblock);
5e656dbb
BN
1296 error = libxfs_dir_createname(tp, ip, &p->name, p->inum,
1297 &firstblock, &flist, nres);
1298 if (error) {
33165ec3 1299 do_warn(
5d1b7f0f 1300_("name create failed in ino %" PRIu64 " (%d), filesystem may be out of space\n"),
33165ec3
BN
1301 ino, error);
1302 libxfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES |
1303 XFS_TRANS_ABORT);
1304 break;
1305 }
1306
5e656dbb
BN
1307 error = libxfs_bmap_finish(&tp, &flist, &committed);
1308 if (error) {
33165ec3
BN
1309 do_warn(
1310 _("bmap finish failed (%d), filesystem may be out of space\n"),
1311 error);
1312 libxfs_bmap_cancel(&flist);
1313 libxfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES |
1314 XFS_TRANS_ABORT);
1315 break;
1316 }
33165ec3 1317
0f012a4c 1318 libxfs_trans_commit(tp,
5e656dbb 1319 XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_SYNC);
33165ec3
BN
1320 }
1321}
1322
1323
2bd0ea18
NS
1324/*
1325 * Kill a block in a version 2 inode.
1326 * Makes its own transaction.
1327 */
1328static void
1329dir2_kill_block(
1330 xfs_mount_t *mp,
1331 xfs_inode_t *ip,
1332 xfs_dablk_t da_bno,
a2ceac1f 1333 struct xfs_buf *bp)
2bd0ea18
NS
1334{
1335 xfs_da_args_t args;
1336 int committed;
1337 int error;
1338 xfs_fsblock_t firstblock;
1339 xfs_bmap_free_t flist;
1340 int nres;
1341 xfs_trans_t *tp;
1342
1343 tp = libxfs_trans_alloc(mp, 0);
1344 nres = XFS_REMOVE_SPACE_RES(mp);
1345 error = libxfs_trans_reserve(tp, nres, XFS_REMOVE_LOG_RES(mp), 0,
1346 XFS_TRANS_PERM_LOG_RES, XFS_REMOVE_LOG_COUNT);
1347 if (error)
1348 res_failed(error);
1349 libxfs_trans_ijoin(tp, ip, 0);
1350 libxfs_trans_ihold(tp, ip);
a2ceac1f 1351 libxfs_trans_bjoin(tp, bp);
dab9b8d6 1352 memset(&args, 0, sizeof(args));
56b2de80 1353 xfs_bmap_init(&flist, &firstblock);
2bd0ea18
NS
1354 args.dp = ip;
1355 args.trans = tp;
1356 args.firstblock = &firstblock;
1357 args.flist = &flist;
1358 args.whichfork = XFS_DATA_FORK;
1359 if (da_bno >= mp->m_dirleafblk && da_bno < mp->m_dirfreeblk)
1360 error = libxfs_da_shrink_inode(&args, da_bno, bp);
1361 else
1362 error = libxfs_dir2_shrink_inode(&args,
5e656dbb 1363 xfs_dir2_da_to_db(mp, da_bno), bp);
2bd0ea18 1364 if (error)
5d1b7f0f 1365 do_error(_("shrink_inode failed inode %" PRIu64 " block %u\n"),
2bd0ea18 1366 ip->i_ino, da_bno);
5e656dbb
BN
1367 libxfs_bmap_finish(&tp, &flist, &committed);
1368 libxfs_trans_commit(tp, 0);
2bd0ea18
NS
1369}
1370
1371/*
1372 * process a data block, also checks for .. entry
1373 * and corrects it to match what we think .. should be
1374 */
1375static void
1376longform_dir2_entry_check_data(
1377 xfs_mount_t *mp,
1378 xfs_inode_t *ip,
1379 int *num_illegal,
1380 int *need_dot,
2bd0ea18
NS
1381 ino_tree_node_t *current_irec,
1382 int current_ino_offset,
a2ceac1f 1383 struct xfs_buf **bpp,
2bd0ea18
NS
1384 dir_hash_tab_t *hashtab,
1385 freetab_t **freetabp,
1386 xfs_dablk_t da_bno,
1387 int isblock)
1388{
1389 xfs_dir2_dataptr_t addr;
1390 xfs_dir2_leaf_entry_t *blp;
a2ceac1f 1391 struct xfs_buf *bp;
2bd0ea18
NS
1392 xfs_dir2_block_tail_t *btp;
1393 int committed;
1394 xfs_dir2_data_t *d;
1395 xfs_dir2_db_t db;
1396 xfs_dir2_data_entry_t *dep;
1397 xfs_dir2_data_unused_t *dup;
1398 char *endptr;
1399 int error;
1400 xfs_fsblock_t firstblock;
1401 xfs_bmap_free_t flist;
1402 char fname[MAXNAMELEN + 1];
1403 freetab_t *freetab;
1404 int i;
1405 int ino_offset;
33165ec3 1406 xfs_ino_t inum;
2bd0ea18
NS
1407 ino_tree_node_t *irec;
1408 int junkit;
1409 int lastfree;
1410 int len;
1411 int nbad;
1412 int needlog;
1413 int needscan;
1414 xfs_ino_t parent;
1415 char *ptr;
1416 xfs_trans_t *tp;
1417 int wantmagic;
1418
1419 bp = *bpp;
a2ceac1f 1420 d = bp->b_addr;
658ac3e3 1421 ptr = (char *)xfs_dir3_data_entry_p(&d->hdr);
2bd0ea18
NS
1422 nbad = 0;
1423 needscan = needlog = 0;
9d7d6241 1424 junkit = 0;
2bd0ea18
NS
1425 freetab = *freetabp;
1426 if (isblock) {
a2ceac1f 1427 btp = xfs_dir2_block_tail_p(mp, (struct xfs_dir2_data_hdr *)d);
5e656dbb 1428 blp = xfs_dir2_block_leaf_p(btp);
2bd0ea18
NS
1429 endptr = (char *)blp;
1430 if (endptr > (char *)btp)
1431 endptr = (char *)btp;
658ac3e3
DC
1432 if (xfs_sb_version_hascrc(&mp->m_sb))
1433 wantmagic = XFS_DIR3_BLOCK_MAGIC;
1434 else
1435 wantmagic = XFS_DIR2_BLOCK_MAGIC;
2bd0ea18
NS
1436 } else {
1437 endptr = (char *)d + mp->m_dirblksize;
658ac3e3
DC
1438 if (xfs_sb_version_hascrc(&mp->m_sb))
1439 wantmagic = XFS_DIR3_DATA_MAGIC;
1440 else
1441 wantmagic = XFS_DIR2_DATA_MAGIC;
2bd0ea18 1442 }
5e656dbb 1443 db = xfs_dir2_da_to_db(mp, da_bno);
9d7d6241
NS
1444
1445 /* check for data block beyond expected end */
2bd0ea18
NS
1446 if (freetab->naents <= db) {
1447 struct freetab_ent e;
1448
1449 *freetabp = freetab = realloc(freetab, FREETAB_SIZE(db + 1));
1450 if (!freetab) {
1451 do_error(
5d1b7f0f 1452 _("realloc failed in longform_dir2_entry_check_data (%zu bytes)\n"),
2bd0ea18 1453 FREETAB_SIZE(db + 1));
2bd0ea18
NS
1454 }
1455 e.v = NULLDATAOFF;
1456 e.s = 0;
1457 for (i = freetab->naents; i < db; i++)
1458 freetab->ents[i] = e;
1459 freetab->naents = db + 1;
1460 }
9d7d6241
NS
1461
1462 /* check the data block */
2bd0ea18 1463 while (ptr < endptr) {
9d7d6241
NS
1464
1465 /* check for freespace */
2bd0ea18 1466 dup = (xfs_dir2_data_unused_t *)ptr;
5e656dbb 1467 if (XFS_DIR2_DATA_FREE_TAG == be16_to_cpu(dup->freetag)) {
9d7d6241
NS
1468
1469 /* check for invalid freespace length */
5e656dbb
BN
1470 if (ptr + be16_to_cpu(dup->length) > endptr ||
1471 be16_to_cpu(dup->length) == 0 ||
1472 (be16_to_cpu(dup->length) &
1473 (XFS_DIR2_DATA_ALIGN - 1)))
2bd0ea18 1474 break;
9d7d6241
NS
1475
1476 /* check for invalid tag */
5e656dbb
BN
1477 if (be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)) !=
1478 (char *)dup - (char *)d)
2bd0ea18 1479 break;
9d7d6241
NS
1480
1481 /* check for block with no data entries */
658ac3e3
DC
1482 if ((ptr == (char *)xfs_dir3_data_entry_p(&d->hdr)) &&
1483 (ptr + be16_to_cpu(dup->length) >= endptr)) {
9d7d6241
NS
1484 junkit = 1;
1485 *num_illegal += 1;
1486 break;
1487 }
1488
1489 /* continue at the end of the freespace */
5e656dbb 1490 ptr += be16_to_cpu(dup->length);
2bd0ea18
NS
1491 if (ptr >= endptr)
1492 break;
1493 }
9d7d6241
NS
1494
1495 /* validate data entry size */
2bd0ea18 1496 dep = (xfs_dir2_data_entry_t *)ptr;
5e656dbb 1497 if (ptr + xfs_dir2_data_entsize(dep->namelen) > endptr)
2bd0ea18 1498 break;
5e656dbb
BN
1499 if (be16_to_cpu(*xfs_dir2_data_entry_tag_p(dep)) !=
1500 (char *)dep - (char *)d)
2bd0ea18 1501 break;
5e656dbb 1502 ptr += xfs_dir2_data_entsize(dep->namelen);
2bd0ea18 1503 }
9d7d6241
NS
1504
1505 /* did we find an empty or corrupt block? */
2bd0ea18 1506 if (ptr != endptr) {
9d7d6241 1507 if (junkit) {
507f4e33 1508 do_warn(
5d1b7f0f 1509 _("empty data block %u in directory inode %" PRIu64 ": "),
9d7d6241
NS
1510 da_bno, ip->i_ino);
1511 } else {
5d1b7f0f
CH
1512 do_warn(_
1513 ("corrupt block %u in directory inode %" PRIu64 ": "),
9d7d6241
NS
1514 da_bno, ip->i_ino);
1515 }
2bd0ea18 1516 if (!no_modify) {
507f4e33 1517 do_warn(_("junking block\n"));
2bd0ea18
NS
1518 dir2_kill_block(mp, ip, da_bno, bp);
1519 } else {
507f4e33 1520 do_warn(_("would junk block\n"));
a2ceac1f 1521 libxfs_putbuf(bp);
2bd0ea18
NS
1522 }
1523 freetab->ents[db].v = NULLDATAOFF;
1524 *bpp = NULL;
1525 return;
1526 }
9d7d6241
NS
1527
1528 /* update number of data blocks processed */
1529 if (freetab->nents < db + 1)
1530 freetab->nents = db + 1;
1531
2bd0ea18
NS
1532 tp = libxfs_trans_alloc(mp, 0);
1533 error = libxfs_trans_reserve(tp, 0, XFS_REMOVE_LOG_RES(mp), 0,
1534 XFS_TRANS_PERM_LOG_RES, XFS_REMOVE_LOG_COUNT);
1535 if (error)
1536 res_failed(error);
1537 libxfs_trans_ijoin(tp, ip, 0);
1538 libxfs_trans_ihold(tp, ip);
a2ceac1f
DC
1539 libxfs_trans_bjoin(tp, bp);
1540 libxfs_trans_bhold(tp, bp);
56b2de80 1541 xfs_bmap_init(&flist, &firstblock);
5e656dbb 1542 if (be32_to_cpu(d->hdr.magic) != wantmagic) {
5d1b7f0f
CH
1543 do_warn(
1544 _("bad directory block magic # %#x for directory inode %" PRIu64 " block %d: "),
5e656dbb 1545 be32_to_cpu(d->hdr.magic), ip->i_ino, da_bno);
2bd0ea18 1546 if (!no_modify) {
507f4e33 1547 do_warn(_("fixing magic # to %#x\n"), wantmagic);
5e656dbb 1548 d->hdr.magic = cpu_to_be32(wantmagic);
2bd0ea18
NS
1549 needlog = 1;
1550 } else
507f4e33 1551 do_warn(_("would fix magic # to %#x\n"), wantmagic);
2bd0ea18
NS
1552 }
1553 lastfree = 0;
658ac3e3 1554 ptr = (char *)xfs_dir3_data_entry_p(&d->hdr);
2bd0ea18
NS
1555 /*
1556 * look at each entry. reference inode pointed to by each
1557 * entry in the incore inode tree.
1558 * if not a directory, set reached flag, increment link count
1559 * if a directory and reached, mark entry as to be deleted.
1560 * if a directory, check to see if recorded parent
1561 * matches current inode #,
1562 * if so, then set reached flag, increment link count
1563 * of current and child dir inodes, push the child
1564 * directory inode onto the directory stack.
1565 * if current inode != parent, then mark entry to be deleted.
1566 */
1567 while (ptr < endptr) {
1568 dup = (xfs_dir2_data_unused_t *)ptr;
5e656dbb 1569 if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
2bd0ea18 1570 if (lastfree) {
5d1b7f0f
CH
1571 do_warn(
1572 _("directory inode %" PRIu64 " block %u has consecutive free entries: "),
2bd0ea18
NS
1573 ip->i_ino, da_bno);
1574 if (!no_modify) {
507f4e33 1575 do_warn(_("joining together\n"));
5e656dbb 1576 len = be16_to_cpu(dup->length);
2bd0ea18
NS
1577 libxfs_dir2_data_use_free(tp, bp, dup,
1578 ptr - (char *)d, len, &needlog,
1579 &needscan);
1580 libxfs_dir2_data_make_free(tp, bp,
1581 ptr - (char *)d, len, &needlog,
1582 &needscan);
1583 } else
507f4e33 1584 do_warn(_("would join together\n"));
2bd0ea18 1585 }
5e656dbb 1586 ptr += be16_to_cpu(dup->length);
2bd0ea18
NS
1587 lastfree = 1;
1588 continue;
1589 }
5e656dbb 1590 addr = xfs_dir2_db_off_to_dataptr(mp, db, ptr - (char *)d);
2bd0ea18 1591 dep = (xfs_dir2_data_entry_t *)ptr;
5e656dbb
BN
1592 ptr += xfs_dir2_data_entsize(dep->namelen);
1593 inum = be64_to_cpu(dep->inumber);
2bd0ea18 1594 lastfree = 0;
2bd0ea18
NS
1595 /*
1596 * skip bogus entries (leading '/'). they'll be deleted
c7f277c9
NS
1597 * later. must still log it, else we leak references to
1598 * buffers.
2bd0ea18
NS
1599 */
1600 if (dep->name[0] == '/') {
1601 nbad++;
c7f277c9
NS
1602 if (!no_modify)
1603 libxfs_dir2_data_log_entry(tp, bp, dep);
2bd0ea18
NS
1604 continue;
1605 }
2556c98b 1606
dab9b8d6 1607 memmove(fname, dep->name, dep->namelen);
2bd0ea18 1608 fname[dep->namelen] = '\0';
33165ec3 1609 ASSERT(inum != NULLFSINO);
6c39a3cb 1610
1ae311d5 1611 irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, inum),
6c39a3cb
BN
1612 XFS_INO_TO_AGINO(mp, inum));
1613 if (irec == NULL) {
1614 nbad++;
5d1b7f0f
CH
1615 if (entry_junked(
1616 _("entry \"%s\" in directory inode %" PRIu64 " points to non-existent inode %" PRIu64 ""),
6c39a3cb
BN
1617 fname, ip->i_ino, inum)) {
1618 dep->name[0] = '/';
1619 libxfs_dir2_data_log_entry(tp, bp, dep);
1620 }
1621 continue;
1622 }
1623 ino_offset = XFS_INO_TO_AGINO(mp, inum) - irec->ino_startnum;
1624
1625 /*
1626 * if it's a free inode, blow out the entry.
1627 * by now, any inode that we think is free
1628 * really is free.
1629 */
1630 if (is_inode_free(irec, ino_offset)) {
1631 nbad++;
5d1b7f0f 1632 if (entry_junked(
b52923f3 1633 _("entry \"%s\" in directory inode %" PRIu64 " points to free inode %" PRIu64),
6c39a3cb
BN
1634 fname, ip->i_ino, inum)) {
1635 dep->name[0] = '/';
1636 libxfs_dir2_data_log_entry(tp, bp, dep);
1637 }
1638 continue;
1639 }
1640
1641 /*
1642 * check if this inode is lost+found dir in the root
1643 */
1644 if (inum == mp->m_sb.sb_rootino && strcmp(fname, ORPHANAGE) == 0) {
1645 /*
1646 * if it's not a directory, trash it
1647 */
1648 if (!inode_isadir(irec, ino_offset)) {
1649 nbad++;
5d1b7f0f
CH
1650 if (entry_junked(
1651 _("%s (ino %" PRIu64 ") in root (%" PRIu64 ") is not a directory"),
6c39a3cb
BN
1652 ORPHANAGE, inum, ip->i_ino)) {
1653 dep->name[0] = '/';
1654 libxfs_dir2_data_log_entry(tp, bp, dep);
1655 }
1656 continue;
1657 }
1658 /*
1659 * if this is a dup, it will be picked up below,
1660 * otherwise, mark it as the orphanage for later.
1661 */
1662 if (!orphanage_ino)
1663 orphanage_ino = inum;
1664 }
1665 /*
1666 * check for duplicate names in directory.
1667 */
51ca7008 1668 if (!dir_hash_add(mp, hashtab, addr, inum, dep->namelen,
56b2de80 1669 dep->name)) {
6c39a3cb 1670 nbad++;
5d1b7f0f
CH
1671 if (entry_junked(
1672 _("entry \"%s\" (ino %" PRIu64 ") in dir %" PRIu64 " is a duplicate name"),
6c39a3cb
BN
1673 fname, inum, ip->i_ino)) {
1674 dep->name[0] = '/';
1675 libxfs_dir2_data_log_entry(tp, bp, dep);
1676 }
1677 if (inum == orphanage_ino)
1678 orphanage_ino = 0;
1679 continue;
1680 }
1681
575ca697
BN
1682 /*
1683 * if just scanning to rebuild a directory due to a ".."
1684 * update, just continue
1685 */
1686 if (dotdot_update)
1687 continue;
1688
2bd0ea18
NS
1689 /*
1690 * skip the '..' entry since it's checked when the
1691 * directory is reached by something else. if it never
1692 * gets reached, it'll be moved to the orphanage and we'll
6fa00c33
BN
1693 * take care of it then. If it doesn't exist at all, the
1694 * directory needs to be rebuilt first before being added
1695 * to the orphanage.
2bd0ea18
NS
1696 */
1697 if (dep->namelen == 2 && dep->name[0] == '.' &&
6fa00c33
BN
1698 dep->name[1] == '.') {
1699 if (da_bno != 0) {
1700 /* ".." should be in the first block */
1701 nbad++;
5d1b7f0f
CH
1702 if (entry_junked(
1703 _("entry \"%s\" (ino %" PRIu64 ") in dir %" PRIu64 " is not in the the first block"), fname,
6fa00c33
BN
1704 inum, ip->i_ino)) {
1705 dep->name[0] = '/';
1706 libxfs_dir2_data_log_entry(tp, bp, dep);
1707 }
1708 }
2bd0ea18 1709 continue;
6fa00c33 1710 }
33165ec3 1711 ASSERT(no_modify || !verify_inum(mp, inum));
2bd0ea18
NS
1712 /*
1713 * special case the . entry. we know there's only one
1714 * '.' and only '.' points to itself because bogus entries
1715 * got trashed in phase 3 if there were > 1.
1716 * bump up link count for '.' but don't set reached
1717 * until we're actually reached by another directory
1718 * '..' is already accounted for or will be taken care
1719 * of when directory is moved to orphanage.
1720 */
33165ec3 1721 if (ip->i_ino == inum) {
2bd0ea18
NS
1722 ASSERT(dep->name[0] == '.' && dep->namelen == 1);
1723 add_inode_ref(current_irec, current_ino_offset);
658ac3e3
DC
1724 if (da_bno != 0 ||
1725 dep != xfs_dir3_data_entry_p(&d->hdr)) {
6fa00c33
BN
1726 /* "." should be the first entry */
1727 nbad++;
5d1b7f0f
CH
1728 if (entry_junked(
1729 _("entry \"%s\" in dir %" PRIu64 " is not the first entry"),
6fa00c33
BN
1730 fname, inum, ip->i_ino)) {
1731 dep->name[0] = '/';
1732 libxfs_dir2_data_log_entry(tp, bp, dep);
1733 }
1734 }
2bd0ea18
NS
1735 *need_dot = 0;
1736 continue;
1737 }
2bd0ea18
NS
1738 /*
1739 * skip entries with bogus inumbers if we're in no modify mode
1740 */
33165ec3 1741 if (no_modify && verify_inum(mp, inum))
2bd0ea18 1742 continue;
2bd0ea18
NS
1743 /*
1744 * check easy case first, regular inode, just bump
1745 * the link count and continue
1746 */
1747 if (!inode_isadir(irec, ino_offset)) {
1748 add_inode_reached(irec, ino_offset);
1749 continue;
1750 }
1751 parent = get_inode_parent(irec, ino_offset);
1752 ASSERT(parent != 0);
6c39a3cb 1753 junkit = 0;
2bd0ea18
NS
1754 /*
1755 * bump up the link counts in parent and child
1756 * directory but if the link doesn't agree with
1757 * the .. in the child, blow out the entry.
1758 * if the directory has already been reached,
1759 * blow away the entry also.
1760 */
1761 if (is_inode_reached(irec, ino_offset)) {
1762 junkit = 1;
507f4e33 1763 do_warn(
5d1b7f0f 1764_("entry \"%s\" in dir %" PRIu64" points to an already connected directory inode %" PRIu64 "\n"),
33165ec3 1765 fname, ip->i_ino, inum);
2bd0ea18
NS
1766 } else if (parent == ip->i_ino) {
1767 add_inode_reached(irec, ino_offset);
1768 add_inode_ref(current_irec, current_ino_offset);
6fa00c33
BN
1769 } else if (parent == NULLFSINO) {
1770 /* ".." was missing, but this entry refers to it,
1771 so, set it as the parent and mark for rebuild */
5d1b7f0f
CH
1772 do_warn(
1773 _("entry \"%s\" in dir ino %" PRIu64 " doesn't have a .. entry, will set it in ino %" PRIu64 ".\n"),
6fa00c33
BN
1774 fname, ip->i_ino, inum);
1775 set_inode_parent(irec, ino_offset, ip->i_ino);
1776 add_inode_reached(irec, ino_offset);
1777 add_inode_ref(current_irec, current_ino_offset);
575ca697
BN
1778 add_dotdot_update(XFS_INO_TO_AGNO(mp, inum), irec,
1779 ino_offset);
2bd0ea18
NS
1780 } else {
1781 junkit = 1;
507f4e33 1782 do_warn(
5d1b7f0f 1783_("entry \"%s\" in dir inode %" PRIu64 " inconsistent with .. value (%" PRIu64 ") in ino %" PRIu64 "\n"),
33165ec3 1784 fname, ip->i_ino, parent, inum);
2bd0ea18
NS
1785 }
1786 if (junkit) {
6c39a3cb
BN
1787 if (inum == orphanage_ino)
1788 orphanage_ino = 0;
2bd0ea18
NS
1789 junkit = 0;
1790 nbad++;
1791 if (!no_modify) {
1792 dep->name[0] = '/';
1793 libxfs_dir2_data_log_entry(tp, bp, dep);
6c39a3cb 1794 if (verbose)
507f4e33
NS
1795 do_warn(
1796 _("\twill clear entry \"%s\"\n"),
2bd0ea18
NS
1797 fname);
1798 } else {
507f4e33
NS
1799 do_warn(_("\twould clear entry \"%s\"\n"),
1800 fname);
2bd0ea18
NS
1801 }
1802 }
1803 }
1804 *num_illegal += nbad;
1805 if (needscan)
a2ceac1f 1806 libxfs_dir2_data_freescan(mp, &d->hdr, &needlog);
2bd0ea18
NS
1807 if (needlog)
1808 libxfs_dir2_data_log_header(tp, bp);
5e656dbb
BN
1809 libxfs_bmap_finish(&tp, &flist, &committed);
1810 libxfs_trans_commit(tp, 0);
1811 freetab->ents[db].v = be16_to_cpu(d->hdr.bestfree[0].length);
2bd0ea18
NS
1812 freetab->ents[db].s = 0;
1813}
1814
1815/*
1816 * Check contents of leaf-form block.
1817 */
2556c98b 1818static int
2bd0ea18
NS
1819longform_dir2_check_leaf(
1820 xfs_mount_t *mp,
1821 xfs_inode_t *ip,
1822 dir_hash_tab_t *hashtab,
1823 freetab_t *freetab)
1824{
1825 int badtail;
5e656dbb 1826 __be16 *bestsp;
a2ceac1f 1827 struct xfs_buf *bp;
2bd0ea18
NS
1828 xfs_dablk_t da_bno;
1829 int i;
1830 xfs_dir2_leaf_t *leaf;
1831 xfs_dir2_leaf_tail_t *ltp;
1832 int seeval;
65b80c98 1833 struct xfs_dir2_leaf_entry *ents;
658ac3e3 1834 struct xfs_dir3_icleaf_hdr leafhdr;
2bd0ea18
NS
1835
1836 da_bno = mp->m_dirleafblk;
75c8b434
DC
1837 if (libxfs_da_read_buf(NULL, ip, da_bno, -1, &bp, XFS_DATA_FORK,
1838 &xfs_dir3_leaf1_buf_ops)) {
5d1b7f0f
CH
1839 do_error(
1840 _("can't read block %u for directory inode %" PRIu64 "\n"),
2bd0ea18
NS
1841 da_bno, ip->i_ino);
1842 /* NOTREACHED */
1843 }
a2ceac1f 1844 leaf = bp->b_addr;
658ac3e3 1845 xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf);
65b80c98 1846 ents = xfs_dir3_leaf_ents_p(leaf);
5e656dbb
BN
1847 ltp = xfs_dir2_leaf_tail_p(mp, leaf);
1848 bestsp = xfs_dir2_leaf_bests_p(ltp);
658ac3e3
DC
1849 if (!(leafhdr.magic == XFS_DIR2_LEAF1_MAGIC ||
1850 leafhdr.magic == XFS_DIR3_LEAF1_MAGIC) ||
1851 leafhdr.forw || leafhdr.back ||
1852 leafhdr.count < leaf->hdr.stale ||
1853 leafhdr.count >
65b80c98 1854 xfs_dir3_max_leaf_ents(mp, leaf) ||
658ac3e3 1855 (char *)&ents[leafhdr.count] > (char *)bestsp) {
507f4e33 1856 do_warn(
5d1b7f0f 1857 _("leaf block %u for directory inode %" PRIu64 " bad header\n"),
2bd0ea18 1858 da_bno, ip->i_ino);
a2ceac1f 1859 libxfs_putbuf(bp);
2bd0ea18
NS
1860 return 1;
1861 }
658ac3e3 1862 seeval = dir_hash_see_all(hashtab, ents, leafhdr.count, leafhdr.stale);
2bd0ea18 1863 if (dir_hash_check(hashtab, ip, seeval)) {
a2ceac1f 1864 libxfs_putbuf(bp);
2bd0ea18
NS
1865 return 1;
1866 }
5e656dbb
BN
1867 badtail = freetab->nents != be32_to_cpu(ltp->bestcount);
1868 for (i = 0; !badtail && i < be32_to_cpu(ltp->bestcount); i++) {
2bd0ea18 1869 freetab->ents[i].s = 1;
5e656dbb 1870 badtail = freetab->ents[i].v != be16_to_cpu(bestsp[i]);
2bd0ea18
NS
1871 }
1872 if (badtail) {
5d1b7f0f
CH
1873 do_warn(
1874 _("leaf block %u for directory inode %" PRIu64 " bad tail\n"),
2bd0ea18 1875 da_bno, ip->i_ino);
a2ceac1f 1876 libxfs_putbuf(bp);
2bd0ea18
NS
1877 return 1;
1878 }
a2ceac1f 1879 libxfs_putbuf(bp);
2bd0ea18
NS
1880 return 0;
1881}
1882
1883/*
1884 * Check contents of the node blocks (leaves)
1885 * Looks for matching hash values for the data entries.
1886 */
2556c98b 1887static int
2bd0ea18
NS
1888longform_dir2_check_node(
1889 xfs_mount_t *mp,
1890 xfs_inode_t *ip,
1891 dir_hash_tab_t *hashtab,
1892 freetab_t *freetab)
1893{
a2ceac1f 1894 struct xfs_buf *bp;
2bd0ea18
NS
1895 xfs_dablk_t da_bno;
1896 xfs_dir2_db_t fdb;
1897 xfs_dir2_free_t *free;
1898 int i;
1899 xfs_dir2_leaf_t *leaf;
1900 xfs_fileoff_t next_da_bno;
1901 int seeval = 0;
1902 int used;
65b80c98 1903 struct xfs_dir2_leaf_entry *ents;
658ac3e3
DC
1904 struct xfs_dir3_icleaf_hdr leafhdr;
1905 struct xfs_dir3_icfree_hdr freehdr;
1906 __be16 *bests;
0f012a4c 1907
2bd0ea18 1908 for (da_bno = mp->m_dirleafblk, next_da_bno = 0;
5e656dbb
BN
1909 next_da_bno != NULLFILEOFF && da_bno < mp->m_dirfreeblk;
1910 da_bno = (xfs_dablk_t)next_da_bno) {
2bd0ea18 1911 next_da_bno = da_bno + mp->m_dirblkfsbs - 1;
5e656dbb 1912 if (bmap_next_offset(NULL, ip, &next_da_bno, XFS_DATA_FORK))
2bd0ea18 1913 break;
a2ceac1f 1914 if (libxfs_da_read_buf(NULL, ip, da_bno, -1, &bp,
75c8b434 1915 XFS_DATA_FORK, &xfs_dir3_leafn_buf_ops)) {
33165ec3 1916 do_warn(
5d1b7f0f 1917 _("can't read leaf block %u for directory inode %" PRIu64 "\n"),
2bd0ea18 1918 da_bno, ip->i_ino);
33165ec3 1919 return 1;
2bd0ea18 1920 }
a2ceac1f 1921 leaf = bp->b_addr;
658ac3e3 1922 xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf);
65b80c98 1923 ents = xfs_dir3_leaf_ents_p(leaf);
658ac3e3
DC
1924 if (!(leafhdr.magic == XFS_DIR2_LEAFN_MAGIC ||
1925 leafhdr.magic == XFS_DIR3_LEAFN_MAGIC)) {
1926 if (leafhdr.magic == XFS_DA_NODE_MAGIC ||
1927 leafhdr.magic == XFS_DA3_NODE_MAGIC) {
a2ceac1f 1928 libxfs_putbuf(bp);
2bd0ea18
NS
1929 continue;
1930 }
5d1b7f0f
CH
1931 do_warn(
1932 _("unknown magic number %#x for block %u in directory inode %" PRIu64 "\n"),
658ac3e3 1933 leafhdr.magic, da_bno, ip->i_ino);
a2ceac1f 1934 libxfs_putbuf(bp);
2bd0ea18
NS
1935 return 1;
1936 }
658ac3e3
DC
1937 if (leafhdr.count > xfs_dir3_max_leaf_ents(mp, leaf) ||
1938 leafhdr.count < leafhdr.stale) {
5d1b7f0f
CH
1939 do_warn(
1940 _("leaf block %u for directory inode %" PRIu64 " bad header\n"),
2bd0ea18 1941 da_bno, ip->i_ino);
a2ceac1f 1942 libxfs_putbuf(bp);
2bd0ea18
NS
1943 return 1;
1944 }
65b80c98 1945 seeval = dir_hash_see_all(hashtab, ents,
658ac3e3 1946 leafhdr.count, leafhdr.stale);
a2ceac1f 1947 libxfs_putbuf(bp);
0f012a4c 1948 if (seeval != DIR_HASH_CK_OK)
2bd0ea18
NS
1949 return 1;
1950 }
0f012a4c 1951 if (dir_hash_check(hashtab, ip, seeval))
2bd0ea18 1952 return 1;
0f012a4c 1953
2bd0ea18
NS
1954 for (da_bno = mp->m_dirfreeblk, next_da_bno = 0;
1955 next_da_bno != NULLFILEOFF;
1956 da_bno = (xfs_dablk_t)next_da_bno) {
1957 next_da_bno = da_bno + mp->m_dirblkfsbs - 1;
5e656dbb 1958 if (bmap_next_offset(NULL, ip, &next_da_bno, XFS_DATA_FORK))
2bd0ea18 1959 break;
a2ceac1f 1960 if (libxfs_da_read_buf(NULL, ip, da_bno, -1, &bp,
75c8b434 1961 XFS_DATA_FORK, &xfs_dir3_free_buf_ops)) {
33165ec3 1962 do_warn(
5d1b7f0f 1963 _("can't read freespace block %u for directory inode %" PRIu64 "\n"),
2bd0ea18 1964 da_bno, ip->i_ino);
33165ec3 1965 return 1;
2bd0ea18 1966 }
a2ceac1f 1967 free = bp->b_addr;
658ac3e3
DC
1968 xfs_dir3_free_hdr_from_disk(&freehdr, free);
1969 bests = xfs_dir3_free_bests_p(mp, free);
5e656dbb 1970 fdb = xfs_dir2_da_to_db(mp, da_bno);
658ac3e3
DC
1971 if (!(freehdr.magic == XFS_DIR2_FREE_MAGIC ||
1972 freehdr.magic == XFS_DIR3_FREE_MAGIC) ||
1973 freehdr.firstdb !=
5e656dbb 1974 (fdb - XFS_DIR2_FREE_FIRSTDB(mp)) *
3303b09f 1975 xfs_dir3_free_max_bests(mp) ||
658ac3e3 1976 freehdr.nvalid < freehdr.nused) {
5d1b7f0f
CH
1977 do_warn(
1978 _("free block %u for directory inode %" PRIu64 " bad header\n"),
2bd0ea18 1979 da_bno, ip->i_ino);
a2ceac1f 1980 libxfs_putbuf(bp);
2bd0ea18
NS
1981 return 1;
1982 }
658ac3e3
DC
1983 for (i = used = 0; i < freehdr.nvalid; i++) {
1984 if (i + freehdr.firstdb >= freetab->nents ||
1985 freetab->ents[i + freehdr.firstdb].v !=
1986 be16_to_cpu(bests[i])) {
507f4e33 1987 do_warn(
5d1b7f0f 1988 _("free block %u entry %i for directory ino %" PRIu64 " bad\n"),
2bd0ea18 1989 da_bno, i, ip->i_ino);
a2ceac1f 1990 libxfs_putbuf(bp);
2bd0ea18
NS
1991 return 1;
1992 }
658ac3e3
DC
1993 used += be16_to_cpu(bests[i]) != NULLDATAOFF;
1994 freetab->ents[i + freehdr.firstdb].s = 1;
2bd0ea18 1995 }
658ac3e3 1996 if (used != freehdr.nused) {
5d1b7f0f
CH
1997 do_warn(
1998 _("free block %u for directory inode %" PRIu64 " bad nused\n"),
2bd0ea18 1999 da_bno, ip->i_ino);
a2ceac1f 2000 libxfs_putbuf(bp);
2bd0ea18
NS
2001 return 1;
2002 }
a2ceac1f 2003 libxfs_putbuf(bp);
2bd0ea18
NS
2004 }
2005 for (i = 0; i < freetab->nents; i++) {
4b6a2d8e
NS
2006 if ((freetab->ents[i].s == 0) &&
2007 (freetab->ents[i].v != NULLDATAOFF)) {
5d1b7f0f
CH
2008 do_warn(
2009 _("missing freetab entry %u for directory inode %" PRIu64 "\n"),
2bd0ea18
NS
2010 i, ip->i_ino);
2011 return 1;
2012 }
2013 }
2014 return 0;
2015}
2016
2017/*
33165ec3
BN
2018 * If a directory is corrupt, we need to read in as many entries as possible,
2019 * destroy the entry and create a new one with recovered name/inode pairs.
2020 * (ie. get libxfs to do all the grunt work)
2bd0ea18 2021 */
2556c98b 2022static void
2bd0ea18
NS
2023longform_dir2_entry_check(xfs_mount_t *mp,
2024 xfs_ino_t ino,
2025 xfs_inode_t *ip,
2026 int *num_illegal,
2027 int *need_dot,
2bd0ea18 2028 ino_tree_node_t *irec,
64c54486 2029 int ino_offset,
33165ec3 2030 dir_hash_tab_t *hashtab)
2bd0ea18
NS
2031{
2032 xfs_dir2_block_t *block;
a2ceac1f 2033 struct xfs_buf **bplist;
2bd0ea18
NS
2034 xfs_dablk_t da_bno;
2035 freetab_t *freetab;
95dff16b 2036 int num_bps;
2bd0ea18
NS
2037 int i;
2038 int isblock;
2039 int isleaf;
2040 xfs_fileoff_t next_da_bno;
2041 int seeval;
2042 int fixit;
95dff16b 2043 xfs_dir2_db_t db;
2bd0ea18
NS
2044
2045 *need_dot = 1;
2046 freetab = malloc(FREETAB_SIZE(ip->i_d.di_size / mp->m_dirblksize));
2047 if (!freetab) {
2048 do_error(
5d1b7f0f 2049 _("malloc failed in longform_dir2_entry_check (%" PRId64 " bytes)\n"),
2bd0ea18
NS
2050 FREETAB_SIZE(ip->i_d.di_size / mp->m_dirblksize));
2051 exit(1);
2052 }
2053 freetab->naents = ip->i_d.di_size / mp->m_dirblksize;
2054 freetab->nents = 0;
2055 for (i = 0; i < freetab->naents; i++) {
2056 freetab->ents[i].v = NULLDATAOFF;
2057 freetab->ents[i].s = 0;
2058 }
95dff16b 2059 num_bps = freetab->naents;
a2ceac1f 2060 bplist = calloc(num_bps, sizeof(struct xfs_buf*));
9d7d6241 2061 /* is this a block, leaf, or node directory? */
2bd0ea18
NS
2062 libxfs_dir2_isblock(NULL, ip, &isblock);
2063 libxfs_dir2_isleaf(NULL, ip, &isleaf);
9d7d6241 2064
33165ec3 2065 /* check directory "data" blocks (ie. name/inode pairs) */
2bd0ea18
NS
2066 for (da_bno = 0, next_da_bno = 0;
2067 next_da_bno != NULLFILEOFF && da_bno < mp->m_dirleafblk;
2068 da_bno = (xfs_dablk_t)next_da_bno) {
2069 next_da_bno = da_bno + mp->m_dirblkfsbs - 1;
5e656dbb 2070 if (bmap_next_offset(NULL, ip, &next_da_bno, XFS_DATA_FORK))
2bd0ea18 2071 break;
5e656dbb 2072 db = xfs_dir2_da_to_db(mp, da_bno);
95dff16b
BN
2073 if (db >= num_bps) {
2074 /* more data blocks than expected */
2075 num_bps = db + 1;
a2ceac1f 2076 bplist = realloc(bplist, num_bps * sizeof(struct xfs_buf*));
0f012a4c 2077 if (!bplist)
95dff16b 2078 do_error(
5d1b7f0f 2079 _("realloc failed in longform_dir2_entry_check (%zu bytes)\n"),
a2ceac1f 2080 num_bps * sizeof(struct xfs_buf*));
95dff16b 2081 }
a2ceac1f 2082 if (libxfs_da_read_buf(NULL, ip, da_bno, -1, &bplist[db],
75c8b434 2083 XFS_DATA_FORK, &xfs_dir3_data_buf_ops)) {
5d1b7f0f
CH
2084 do_warn(
2085 _("can't read data block %u for directory inode %" PRIu64 "\n"),
2bd0ea18 2086 da_bno, ino);
95dff16b 2087 *num_illegal += 1;
33165ec3 2088 continue; /* try and read all "data" blocks */
2bd0ea18
NS
2089 }
2090 longform_dir2_entry_check_data(mp, ip, num_illegal, need_dot,
2556c98b 2091 irec, ino_offset, &bplist[db], hashtab,
33165ec3 2092 &freetab, da_bno, isblock);
2bd0ea18 2093 }
6fa00c33 2094 fixit = (*num_illegal != 0) || dir2_is_badino(ino) || *need_dot;
9d7d6241 2095
575ca697
BN
2096 if (!dotdot_update) {
2097 /* check btree and freespace */
2098 if (isblock) {
2099 xfs_dir2_block_tail_t *btp;
2100 xfs_dir2_leaf_entry_t *blp;
2101
a2ceac1f
DC
2102 block = bplist[0]->b_addr;
2103 btp = xfs_dir2_block_tail_p(mp, &block->hdr);
5e656dbb 2104 blp = xfs_dir2_block_leaf_p(btp);
575ca697
BN
2105 seeval = dir_hash_see_all(hashtab, blp,
2106 be32_to_cpu(btp->count),
2107 be32_to_cpu(btp->stale));
2108 if (dir_hash_check(hashtab, ip, seeval))
2109 fixit |= 1;
2110 } else if (isleaf) {
2111 fixit |= longform_dir2_check_leaf(mp, ip, hashtab,
2112 freetab);
2113 } else {
2114 fixit |= longform_dir2_check_node(mp, ip, hashtab,
2115 freetab);
2116 }
2bd0ea18 2117 }
575ca697 2118 if (!no_modify && (fixit || dotdot_update)) {
33165ec3 2119 dir_hash_dup_names(hashtab);
0f012a4c 2120 for (i = 0; i < freetab->naents; i++)
33165ec3 2121 if (bplist[i])
a2ceac1f 2122 libxfs_putbuf(bplist[i]);
6fa00c33 2123 longform_dir2_rebuild(mp, ino, ip, irec, ino_offset, hashtab);
33165ec3 2124 *num_illegal = 0;
6fa00c33 2125 *need_dot = 0;
33165ec3 2126 } else {
0f012a4c 2127 for (i = 0; i < freetab->naents; i++)
33165ec3 2128 if (bplist[i])
a2ceac1f 2129 libxfs_putbuf(bplist[i]);
33165ec3 2130 }
0f012a4c 2131
95dff16b 2132 free(bplist);
2bd0ea18
NS
2133 free(freetab);
2134}
2135
2bd0ea18
NS
2136/*
2137 * shortform directory v2 processing routines -- entry verification and
2138 * bad entry deletion (pruning).
2139 */
2556c98b 2140static void
2bd0ea18
NS
2141shortform_dir2_entry_check(xfs_mount_t *mp,
2142 xfs_ino_t ino,
2143 xfs_inode_t *ip,
2144 int *ino_dirty,
2bd0ea18 2145 ino_tree_node_t *current_irec,
64c54486 2146 int current_ino_offset,
33165ec3 2147 dir_hash_tab_t *hashtab)
2bd0ea18
NS
2148{
2149 xfs_ino_t lino;
2150 xfs_ino_t parent;
2151 xfs_dir2_sf_t *sfp;
2152 xfs_dir2_sf_entry_t *sfep, *next_sfep, *tmp_sfep;
2153 xfs_ifork_t *ifp;
2154 ino_tree_node_t *irec;
2155 int max_size;
2156 int ino_offset;
2157 int i;
2158 int junkit;
2159 int tmp_len;
2160 int tmp_elen;
2161 int bad_sfnamelen;
2162 int namelen;
2163 int bytes_deleted;
2164 char fname[MAXNAMELEN + 1];
2165 int i8;
2166
2167 ifp = &ip->i_df;
2168 sfp = (xfs_dir2_sf_t *) ifp->if_u1.if_data;
2169 *ino_dirty = 0;
e55d768a 2170 bytes_deleted = 0;
2bd0ea18
NS
2171
2172 max_size = ifp->if_bytes;
2173 ASSERT(ip->i_d.di_size <= ifp->if_bytes);
2174
575ca697
BN
2175 /*
2176 * if just rebuild a directory due to a "..", update and return
2177 */
2178 if (dotdot_update) {
2179 parent = get_inode_parent(current_irec, current_ino_offset);
2180 if (no_modify) {
5d1b7f0f
CH
2181 do_warn(
2182 _("would set .. in sf dir inode %" PRIu64 " to %" PRIu64 "\n"),
575ca697
BN
2183 ino, parent);
2184 } else {
5d1b7f0f
CH
2185 do_warn(
2186 _("setting .. in sf dir inode %" PRIu64 " to %" PRIu64 "\n"),
575ca697 2187 ino, parent);
a2ceac1f 2188 xfs_dir2_sf_put_parent_ino(&sfp->hdr, parent);
575ca697
BN
2189 *ino_dirty = 1;
2190 }
2191 return;
2192 }
2193
2bd0ea18
NS
2194 /*
2195 * no '.' entry in shortform dirs, just bump up ref count by 1
2196 * '..' was already (or will be) accounted for and checked when
2197 * the directory is reached or will be taken care of when the
2198 * directory is moved to orphanage.
2199 */
2200 add_inode_ref(current_irec, current_ino_offset);
2201
e55d768a
NS
2202 /*
2203 * Initialise i8 counter -- the parent inode number counts as well.
2204 */
a2ceac1f 2205 i8 = xfs_dir2_sf_get_parent_ino(&sfp->hdr) > XFS_DIR2_MAX_SHORT_INUM;
e55d768a 2206
2bd0ea18
NS
2207 /*
2208 * now run through entries, stop at first bad entry, don't need
2209 * to skip over '..' since that's encoded in its own field and
2210 * no need to worry about '.' since it doesn't exist.
2211 */
a2ceac1f 2212 sfep = next_sfep = xfs_dir2_sf_firstentry(&sfp->hdr);
2bd0ea18 2213
5e656dbb 2214 for (i = 0; i < sfp->hdr.count && max_size >
2bd0ea18
NS
2215 (__psint_t)next_sfep - (__psint_t)sfp;
2216 sfep = next_sfep, i++) {
2217 junkit = 0;
2218 bad_sfnamelen = 0;
2219 tmp_sfep = NULL;
2220
a2ceac1f 2221 lino = xfs_dir2_sfe_get_ino(&sfp->hdr, sfep);
2bd0ea18
NS
2222
2223 namelen = sfep->namelen;
2224
2225 ASSERT(no_modify || namelen > 0);
2226
2227 if (no_modify && namelen == 0) {
2228 /*
2229 * if we're really lucky, this is
2230 * the last entry in which case we
2231 * can use the dir size to set the
2232 * namelen value. otherwise, forget
2233 * it because we're not going to be
2234 * able to find the next entry.
2235 */
2236 bad_sfnamelen = 1;
2237
5e656dbb 2238 if (i == sfp->hdr.count - 1) {
2bd0ea18
NS
2239 namelen = ip->i_d.di_size -
2240 ((__psint_t) &sfep->name[0] -
2241 (__psint_t) sfp);
2242 } else {
2243 /*
2244 * don't process the rest of the directory,
2245 * break out of processing loop
2246 */
2247 break;
2248 }
2249 } else if (no_modify && (__psint_t) sfep - (__psint_t) sfp +
a2ceac1f 2250 + xfs_dir2_sf_entsize(&sfp->hdr, sfep->namelen)
2bd0ea18
NS
2251 > ip->i_d.di_size) {
2252 bad_sfnamelen = 1;
2253
5e656dbb 2254 if (i == sfp->hdr.count - 1) {
2bd0ea18
NS
2255 namelen = ip->i_d.di_size -
2256 ((__psint_t) &sfep->name[0] -
2257 (__psint_t) sfp);
2258 } else {
2259 /*
2260 * don't process the rest of the directory,
2261 * break out of processing loop
2262 */
2263 break;
2264 }
2265 }
2266
dab9b8d6 2267 memmove(fname, sfep->name, sfep->namelen);
2bd0ea18
NS
2268 fname[sfep->namelen] = '\0';
2269
2270 ASSERT(no_modify || (lino != NULLFSINO && lino != 0));
2271 ASSERT(no_modify || !verify_inum(mp, lino));
2272
e55d768a
NS
2273 /*
2274 * Also skip entries with bogus inode numbers if we're
2275 * in no modify mode.
2276 */
2277
2278 if (no_modify && verify_inum(mp, lino)) {
5e656dbb 2279 next_sfep = (xfs_dir2_sf_entry_t *)((__psint_t)sfep +
a2ceac1f 2280 xfs_dir2_sf_entsize(&sfp->hdr, sfep->namelen));
2bd0ea18
NS
2281 continue;
2282 }
2283
1ae311d5 2284 irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, lino),
2bd0ea18
NS
2285 XFS_INO_TO_AGINO(mp, lino));
2286
6c39a3cb 2287 if (irec == NULL) {
5d1b7f0f
CH
2288 do_warn(
2289 _("entry \"%s\" in shortform directory %" PRIu64 " references non-existent inode %" PRIu64 "\n"),
2bd0ea18 2290 fname, ino, lino);
6c39a3cb 2291 goto do_junkit;
2bd0ea18
NS
2292 }
2293
2bd0ea18
NS
2294 ino_offset = XFS_INO_TO_AGINO(mp, lino) - irec->ino_startnum;
2295
2296 /*
2297 * if it's a free inode, blow out the entry.
2298 * by now, any inode that we think is free
2299 * really is free.
2300 */
2301 if (is_inode_free(irec, ino_offset)) {
5d1b7f0f
CH
2302 do_warn(
2303 _("entry \"%s\" in shortform directory inode %" PRIu64 " points to free inode %" PRIu64 "\n"),
6c39a3cb
BN
2304 fname, ino, lino);
2305 goto do_junkit;
2306 }
2307 /*
2308 * check if this inode is lost+found dir in the root
2309 */
2310 if (ino == mp->m_sb.sb_rootino && strcmp(fname, ORPHANAGE) == 0) {
2bd0ea18 2311 /*
6c39a3cb 2312 * if it's not a directory, trash it
2bd0ea18 2313 */
6c39a3cb 2314 if (!inode_isadir(irec, ino_offset)) {
5d1b7f0f
CH
2315 do_warn(
2316 _("%s (ino %" PRIu64 ") in root (%" PRIu64 ") is not a directory"),
2317 ORPHANAGE, lino, ino);
6c39a3cb 2318 goto do_junkit;
2bd0ea18 2319 }
64c54486 2320 /*
6c39a3cb
BN
2321 * if this is a dup, it will be picked up below,
2322 * otherwise, mark it as the orphanage for later.
0f012a4c 2323 */
6c39a3cb
BN
2324 if (!orphanage_ino)
2325 orphanage_ino = lino;
2326 }
2327 /*
2328 * check for duplicate names in directory.
2329 */
51ca7008 2330 if (!dir_hash_add(mp, hashtab, (xfs_dir2_dataptr_t)
a2ceac1f
DC
2331 (sfep - xfs_dir2_sf_firstentry(&sfp->hdr)),
2332 lino, sfep->namelen, sfep->name)) {
5d1b7f0f
CH
2333 do_warn(
2334_("entry \"%s\" (ino %" PRIu64 ") in dir %" PRIu64 " is a duplicate name"),
2335 fname, lino, ino);
6c39a3cb
BN
2336 goto do_junkit;
2337 }
575ca697 2338
6c39a3cb 2339 if (!inode_isadir(irec, ino_offset)) {
2bd0ea18
NS
2340 /*
2341 * check easy case first, regular inode, just bump
e55d768a 2342 * the link count
2bd0ea18
NS
2343 */
2344 add_inode_reached(irec, ino_offset);
2bd0ea18
NS
2345 } else {
2346 parent = get_inode_parent(irec, ino_offset);
2347
2348 /*
2349 * bump up the link counts in parent and child.
2350 * directory but if the link doesn't agree with
2351 * the .. in the child, blow out the entry
2352 */
2353 if (is_inode_reached(irec, ino_offset)) {
2354 junkit = 1;
5d1b7f0f
CH
2355 do_warn(
2356 _("entry \"%s\" in directory inode %" PRIu64
2357 " references already connected inode %" PRIu64 ".\n"),
2bd0ea18
NS
2358 fname, ino, lino);
2359 } else if (parent == ino) {
2360 add_inode_reached(irec, ino_offset);
2361 add_inode_ref(current_irec, current_ino_offset);
6fa00c33
BN
2362 } else if (parent == NULLFSINO) {
2363 /* ".." was missing, but this entry refers to it,
2364 so, set it as the parent and mark for rebuild */
5d1b7f0f
CH
2365 do_warn(
2366 _("entry \"%s\" in dir ino %" PRIu64 " doesn't have a .. entry, will set it in ino %" PRIu64 ".\n"),
6fa00c33
BN
2367 fname, ino, lino);
2368 set_inode_parent(irec, ino_offset, ino);
2369 add_inode_reached(irec, ino_offset);
2370 add_inode_ref(current_irec, current_ino_offset);
575ca697
BN
2371 add_dotdot_update(XFS_INO_TO_AGNO(mp, lino),
2372 irec, ino_offset);
2bd0ea18
NS
2373 } else {
2374 junkit = 1;
5d1b7f0f
CH
2375 do_warn(
2376 _("entry \"%s\" in directory inode %" PRIu64
2377 " not consistent with .. value (%" PRIu64
2378 ") in inode %" PRIu64 ",\n"),
2bd0ea18
NS
2379 fname, ino, parent, lino);
2380 }
2381 }
2382
2383 if (junkit) {
6c39a3cb
BN
2384do_junkit:
2385 if (lino == orphanage_ino)
2386 orphanage_ino = 0;
2bd0ea18 2387 if (!no_modify) {
a2ceac1f
DC
2388 tmp_elen = xfs_dir2_sf_entsize(&sfp->hdr,
2389 sfep->namelen);
2bd0ea18
NS
2390 tmp_sfep = (xfs_dir2_sf_entry_t *)
2391 ((__psint_t) sfep + tmp_elen);
2392 tmp_len = max_size - ((__psint_t) tmp_sfep
2393 - (__psint_t) sfp);
2394 max_size -= tmp_elen;
2395 bytes_deleted += tmp_elen;
2396
2397 memmove(sfep, tmp_sfep, tmp_len);
2398
5e656dbb
BN
2399 sfp->hdr.count -= 1;
2400 memset((void *)((__psint_t)sfep + tmp_len), 0,
2bd0ea18
NS
2401 tmp_elen);
2402
2403 /*
2404 * set the tmp value to the current
2405 * pointer so we'll process the entry
2406 * we just moved up
2407 */
2408 tmp_sfep = sfep;
2409
2410 /*
2411 * WARNING: drop the index i by one
2412 * so it matches the decremented count for
2413 * accurate comparisons in the loop test
2414 */
2415 i--;
2416
2417 *ino_dirty = 1;
2418
6c39a3cb
BN
2419 if (verbose)
2420 do_warn(_("junking entry\n"));
2421 else
2422 do_warn("\n");
2bd0ea18 2423 } else {
6c39a3cb 2424 do_warn(_("would junk entry\n"));
2bd0ea18
NS
2425 }
2426 } else if (lino > XFS_DIR2_MAX_SHORT_INUM)
2427 i8++;
2428
2429 /*
2430 * go onto next entry unless we've just junked an
2431 * entry in which the current entry pointer points
2432 * to an unprocessed entry. have to take into entries
2433 * with bad namelen into account in no modify mode since we
2434 * calculate size based on next_sfep.
2435 */
2436 ASSERT(no_modify || bad_sfnamelen == 0);
2437
2438 next_sfep = (tmp_sfep == NULL)
2439 ? (xfs_dir2_sf_entry_t *) ((__psint_t) sfep
a2ceac1f
DC
2440 + ((!bad_sfnamelen)
2441 ? xfs_dir2_sf_entsize(&sfp->hdr, sfep->namelen)
2442 : xfs_dir2_sf_entsize(&sfp->hdr, namelen)))
2bd0ea18
NS
2443 : tmp_sfep;
2444 }
2445
2446 if (sfp->hdr.i8count != i8) {
2447 if (no_modify) {
5d1b7f0f
CH
2448 do_warn(_("would fix i8count in inode %" PRIu64 "\n"),
2449 ino);
2bd0ea18
NS
2450 } else {
2451 if (i8 == 0) {
2452 tmp_sfep = next_sfep;
2453 process_sf_dir2_fixi8(sfp, &tmp_sfep);
2454 bytes_deleted +=
2455 (__psint_t)next_sfep -
2456 (__psint_t)tmp_sfep;
2457 next_sfep = tmp_sfep;
2458 } else
2459 sfp->hdr.i8count = i8;
2460 *ino_dirty = 1;
5d1b7f0f
CH
2461 do_warn(_("fixing i8count in inode %" PRIu64 "\n"),
2462 ino);
2bd0ea18
NS
2463 }
2464 }
2465
2466 /*
2467 * sync up sizes if required
2468 */
2469 if (*ino_dirty) {
2470 ASSERT(bytes_deleted > 0);
2471 ASSERT(!no_modify);
2472 libxfs_idata_realloc(ip, -bytes_deleted, XFS_DATA_FORK);
2473 ip->i_d.di_size -= bytes_deleted;
2474 }
2475
2476 if (ip->i_d.di_size != ip->i_df.if_bytes) {
2477 ASSERT(ip->i_df.if_bytes == (xfs_fsize_t)
2478 ((__psint_t) next_sfep - (__psint_t) sfp));
2479 ip->i_d.di_size = (xfs_fsize_t)
2480 ((__psint_t) next_sfep - (__psint_t) sfp);
5d1b7f0f
CH
2481 do_warn(
2482 _("setting size to %" PRId64 " bytes to reflect junked entries\n"),
2bd0ea18
NS
2483 ip->i_d.di_size);
2484 *ino_dirty = 1;
2485 }
2486}
2487
2488/*
2556c98b 2489 * processes all reachable inodes in directories
2bd0ea18 2490 */
2556c98b
BN
2491static void
2492process_dir_inode(
2493 xfs_mount_t *mp,
575ca697 2494 xfs_agnumber_t agno,
2556c98b
BN
2495 ino_tree_node_t *irec,
2496 int ino_offset)
2bd0ea18 2497{
575ca697 2498 xfs_ino_t ino;
2bd0ea18
NS
2499 xfs_bmap_free_t flist;
2500 xfs_fsblock_t first;
2bd0ea18
NS
2501 xfs_inode_t *ip;
2502 xfs_trans_t *tp;
33165ec3 2503 dir_hash_tab_t *hashtab;
2556c98b 2504 int need_dot, committed;
2bd0ea18
NS
2505 int dirty, num_illegal, error, nres;
2506
575ca697
BN
2507 ino = XFS_AGINO_TO_INO(mp, agno, irec->ino_startnum + ino_offset);
2508
2bd0ea18 2509 /*
2bd0ea18
NS
2510 * open up directory inode, check all entries,
2511 * then call prune_dir_entries to remove all
2512 * remaining illegal directory entries.
2513 */
2514
f4ef1178 2515 ASSERT(!is_inode_refchecked(irec, ino_offset) || dotdot_update);
2bd0ea18 2516
2556c98b
BN
2517 error = libxfs_iget(mp, NULL, ino, 0, &ip, 0);
2518 if (error) {
2519 if (!no_modify)
5d1b7f0f
CH
2520 do_error(
2521 _("couldn't map inode %" PRIu64 ", err = %d\n"),
2556c98b
BN
2522 ino, error);
2523 else {
5d1b7f0f
CH
2524 do_warn(
2525 _("couldn't map inode %" PRIu64 ", err = %d\n"),
2556c98b 2526 ino, error);
2bd0ea18 2527 /*
2556c98b
BN
2528 * see below for what we're doing if this
2529 * is root. Why do we need to do this here?
2530 * to ensure that the root doesn't show up
2531 * as being disconnected in the no_modify case.
2bd0ea18 2532 */
2556c98b
BN
2533 if (mp->m_sb.sb_rootino == ino) {
2534 add_inode_reached(irec, 0);
2535 add_inode_ref(irec, 0);
2536 }
2bd0ea18
NS
2537 }
2538
f4ef1178 2539 add_inode_refchecked(irec, 0);
2556c98b
BN
2540 return;
2541 }
2bd0ea18 2542
2556c98b 2543 need_dot = dirty = num_illegal = 0;
64c54486 2544
2556c98b 2545 if (mp->m_sb.sb_rootino == ino) {
2bd0ea18 2546 /*
2556c98b
BN
2547 * mark root inode reached and bump up
2548 * link count for root inode to account
2549 * for '..' entry since the root inode is
2550 * never reached by a parent. we know
2551 * that root's '..' is always good --
2552 * guaranteed by phase 3 and/or below.
2bd0ea18 2553 */
2556c98b
BN
2554 add_inode_reached(irec, ino_offset);
2555 }
2556
f4ef1178 2557 add_inode_refchecked(irec, ino_offset);
2556c98b
BN
2558
2559 hashtab = dir_hash_init(ip->i_d.di_size);
2560
2561 /*
2562 * look for bogus entries
2563 */
2564 switch (ip->i_d.di_format) {
2bd0ea18
NS
2565 case XFS_DINODE_FMT_EXTENTS:
2566 case XFS_DINODE_FMT_BTREE:
2567 /*
2568 * also check for missing '.' in longform dirs.
2569 * missing .. entries are added if required when
2570 * the directory is connected to lost+found. but
2571 * we need to create '.' entries here.
2572 */
9a048535
DC
2573 longform_dir2_entry_check(mp, ino, ip,
2574 &num_illegal, &need_dot,
2575 irec, ino_offset,
2576 hashtab);
2bd0ea18 2577 break;
2556c98b 2578
2bd0ea18
NS
2579 case XFS_DINODE_FMT_LOCAL:
2580 tp = libxfs_trans_alloc(mp, 0);
2581 /*
2582 * using the remove reservation is overkill
2583 * since at most we'll only need to log the
2584 * inode but it's easier than wedging a
2585 * new define in ourselves.
2586 */
2587 nres = no_modify ? 0 : XFS_REMOVE_SPACE_RES(mp);
2588 error = libxfs_trans_reserve(tp, nres,
2589 XFS_REMOVE_LOG_RES(mp), 0,
2590 XFS_TRANS_PERM_LOG_RES,
2591 XFS_REMOVE_LOG_COUNT);
2592 if (error)
2593 res_failed(error);
2594
2595 libxfs_trans_ijoin(tp, ip, 0);
2596 libxfs_trans_ihold(tp, ip);
2597
9a048535
DC
2598 shortform_dir2_entry_check(mp, ino, ip, &dirty,
2599 irec, ino_offset,
2600 hashtab);
2bd0ea18 2601
27527004 2602 ASSERT(dirty == 0 || (dirty && !no_modify));
2bd0ea18
NS
2603 if (dirty) {
2604 libxfs_trans_log_inode(tp, ip,
2605 XFS_ILOG_CORE | XFS_ILOG_DDATA);
2556c98b
BN
2606 libxfs_trans_commit(tp,
2607 XFS_TRANS_RELEASE_LOG_RES |
5e656dbb 2608 XFS_TRANS_SYNC);
2bd0ea18 2609 } else {
2556c98b
BN
2610 libxfs_trans_cancel(tp,
2611 XFS_TRANS_RELEASE_LOG_RES);
2bd0ea18
NS
2612 }
2613 break;
2556c98b 2614
2bd0ea18
NS
2615 default:
2616 break;
2556c98b
BN
2617 }
2618 dir_hash_done(hashtab);
2bd0ea18 2619
2556c98b
BN
2620 /*
2621 * if we have to create a .. for /, do it now *before*
2622 * we delete the bogus entries, otherwise the directory
2623 * could transform into a shortform dir which would
2624 * probably cause the simulation to choke. Even
2625 * if the illegal entries get shifted around, it's ok
2626 * because the entries are structurally intact and in
2627 * in hash-value order so the simulation won't get confused
2628 * if it has to move them around.
2629 */
2630 if (!no_modify && need_root_dotdot && ino == mp->m_sb.sb_rootino) {
2631 ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_LOCAL);
2bd0ea18 2632
2556c98b 2633 do_warn(_("recreating root directory .. entry\n"));
2bd0ea18 2634
2556c98b
BN
2635 tp = libxfs_trans_alloc(mp, 0);
2636 ASSERT(tp != NULL);
2bd0ea18 2637
2556c98b
BN
2638 nres = XFS_MKDIR_SPACE_RES(mp, 2);
2639 error = libxfs_trans_reserve(tp, nres, XFS_MKDIR_LOG_RES(mp),
2640 0, XFS_TRANS_PERM_LOG_RES, XFS_MKDIR_LOG_COUNT);
2641 if (error)
2642 res_failed(error);
2bd0ea18 2643
2556c98b
BN
2644 libxfs_trans_ijoin(tp, ip, 0);
2645 libxfs_trans_ihold(tp, ip);
2bd0ea18 2646
56b2de80 2647 xfs_bmap_init(&flist, &first);
2bd0ea18 2648
5e656dbb
BN
2649 error = libxfs_dir_createname(tp, ip, &xfs_name_dotdot,
2650 ip->i_ino, &first, &flist, nres);
2556c98b 2651 if (error)
5d1b7f0f
CH
2652 do_error(
2653 _("can't make \"..\" entry in root inode %" PRIu64 ", createname error %d\n"), ino, error);
2bd0ea18 2654
2556c98b 2655 libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
2bd0ea18 2656
5e656dbb 2657 error = libxfs_bmap_finish(&tp, &flist, &committed);
2556c98b
BN
2658 ASSERT(error == 0);
2659 libxfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES |
5e656dbb 2660 XFS_TRANS_SYNC);
2bd0ea18 2661
2556c98b
BN
2662 need_root_dotdot = 0;
2663 } else if (need_root_dotdot && ino == mp->m_sb.sb_rootino) {
2664 do_warn(_("would recreate root directory .. entry\n"));
2665 }
2bd0ea18 2666
2556c98b
BN
2667 /*
2668 * if we need to create the '.' entry, do so only if
ff1f79a7 2669 * the directory is a longform dir. if it's been
2556c98b
BN
2670 * turned into a shortform dir, then the inode is ok
2671 * since shortform dirs have no '.' entry and the inode
2672 * has already been committed by prune_lf_dir_entry().
2673 */
2674 if (need_dot) {
2bd0ea18 2675 /*
2556c98b
BN
2676 * bump up our link count but don't
2677 * bump up the inode link count. chances
2678 * are good that even though we lost '.'
2679 * the inode link counts reflect '.' so
2680 * leave the inode link count alone and if
2681 * it turns out to be wrong, we'll catch
2682 * that in phase 7.
2bd0ea18 2683 */
2556c98b
BN
2684 add_inode_ref(irec, ino_offset);
2685
2686 if (no_modify) {
5d1b7f0f
CH
2687 do_warn(
2688 _("would create missing \".\" entry in dir ino %" PRIu64 "\n"),
2556c98b
BN
2689 ino);
2690 } else if (ip->i_d.di_format != XFS_DINODE_FMT_LOCAL) {
2bd0ea18 2691 /*
2556c98b 2692 * need to create . entry in longform dir.
2bd0ea18 2693 */
5d1b7f0f
CH
2694 do_warn(
2695 _("creating missing \".\" entry in dir ino %" PRIu64 "\n"), ino);
2bd0ea18 2696
2556c98b
BN
2697 tp = libxfs_trans_alloc(mp, 0);
2698 ASSERT(tp != NULL);
2bd0ea18 2699
2556c98b
BN
2700 nres = XFS_MKDIR_SPACE_RES(mp, 1);
2701 error = libxfs_trans_reserve(tp, nres,
2702 XFS_MKDIR_LOG_RES(mp),
2703 0,
2704 XFS_TRANS_PERM_LOG_RES,
2705 XFS_MKDIR_LOG_COUNT);
2bd0ea18 2706
2556c98b
BN
2707 if (error)
2708 res_failed(error);
2bd0ea18 2709
2556c98b
BN
2710 libxfs_trans_ijoin(tp, ip, 0);
2711 libxfs_trans_ihold(tp, ip);
2bd0ea18 2712
56b2de80 2713 xfs_bmap_init(&flist, &first);
2bd0ea18 2714
5e656dbb
BN
2715 error = libxfs_dir_createname(tp, ip, &xfs_name_dot,
2716 ip->i_ino, &first, &flist, nres);
2717 if (error)
5d1b7f0f
CH
2718 do_error(
2719 _("can't make \".\" entry in dir ino %" PRIu64 ", createname error %d\n"),
2556c98b 2720 ino, error);
2bd0ea18 2721
2556c98b 2722 libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
2bd0ea18 2723
5e656dbb 2724 error = libxfs_bmap_finish(&tp, &flist, &committed);
2556c98b
BN
2725 ASSERT(error == 0);
2726 libxfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES
5e656dbb 2727 |XFS_TRANS_SYNC);
2bd0ea18 2728 }
2bd0ea18 2729 }
2556c98b 2730 libxfs_iput(ip, 0);
2bd0ea18
NS
2731}
2732
2733/*
2734 * mark realtime bitmap and summary inodes as reached.
2735 * quota inode will be marked here as well
2736 */
8b8a6b02 2737static void
2bd0ea18
NS
2738mark_standalone_inodes(xfs_mount_t *mp)
2739{
2740 ino_tree_node_t *irec;
2741 int offset;
2742
1ae311d5 2743 irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, mp->m_sb.sb_rbmino),
2bd0ea18
NS
2744 XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rbmino));
2745
2746 ASSERT(irec != NULL);
2747
2748 offset = XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rbmino) -
2749 irec->ino_startnum;
2750
2751 add_inode_reached(irec, offset);
2752
1ae311d5 2753 irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, mp->m_sb.sb_rsumino),
2bd0ea18
NS
2754 XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rsumino));
2755
dfc130f3 2756 offset = XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rsumino) -
2bd0ea18
NS
2757 irec->ino_startnum;
2758
2759 ASSERT(irec != NULL);
2760
2761 add_inode_reached(irec, offset);
2762
2763 if (fs_quotas) {
2764 if (mp->m_sb.sb_uquotino
2765 && mp->m_sb.sb_uquotino != NULLFSINO) {
1ae311d5 2766 irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp,
2bd0ea18
NS
2767 mp->m_sb.sb_uquotino),
2768 XFS_INO_TO_AGINO(mp, mp->m_sb.sb_uquotino));
2769 offset = XFS_INO_TO_AGINO(mp, mp->m_sb.sb_uquotino)
2770 - irec->ino_startnum;
2771 add_inode_reached(irec, offset);
2772 }
b36eef04
NS
2773 if (mp->m_sb.sb_gquotino
2774 && mp->m_sb.sb_gquotino != NULLFSINO) {
1ae311d5 2775 irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp,
b36eef04
NS
2776 mp->m_sb.sb_gquotino),
2777 XFS_INO_TO_AGINO(mp, mp->m_sb.sb_gquotino));
2778 offset = XFS_INO_TO_AGINO(mp, mp->m_sb.sb_gquotino)
2bd0ea18
NS
2779 - irec->ino_startnum;
2780 add_inode_reached(irec, offset);
2781 }
2782 }
2783}
2784
6c39a3cb
BN
2785static void
2786check_for_orphaned_inodes(
2787 xfs_mount_t *mp,
2556c98b 2788 xfs_agnumber_t agno,
6c39a3cb
BN
2789 ino_tree_node_t *irec)
2790{
2791 int i;
6c39a3cb
BN
2792 xfs_ino_t ino;
2793
2794 for (i = 0; i < XFS_INODES_PER_CHUNK; i++) {
2795 ASSERT(is_inode_confirmed(irec, i));
2796 if (is_inode_free(irec, i))
2797 continue;
2798
2556c98b
BN
2799 if (is_inode_reached(irec, i))
2800 continue;
2801
2802 ASSERT(inode_isadir(irec, i) ||
2803 num_inode_references(irec, i) == 0);
2804
2805 ino = XFS_AGINO_TO_INO(mp, agno, i + irec->ino_startnum);
2806 if (inode_isadir(irec, i))
5d1b7f0f 2807 do_warn(_("disconnected dir inode %" PRIu64 ", "), ino);
2556c98b 2808 else
5d1b7f0f 2809 do_warn(_("disconnected inode %" PRIu64 ", "), ino);
9a048535
DC
2810 if (!no_modify) {
2811 if (!orphanage_ino)
2556c98b
BN
2812 orphanage_ino = mk_orphanage(mp);
2813 do_warn(_("moving to %s\n"), ORPHANAGE);
2814 mv_orphanage(mp, ino, inode_isadir(irec, i));
2815 } else {
2816 do_warn(_("would move to %s\n"), ORPHANAGE);
6c39a3cb 2817 }
2556c98b
BN
2818 /*
2819 * for read-only case, even though the inode isn't
2820 * really reachable, set the flag (and bump our link
2821 * count) anyway to fool phase 7
2822 */
2823 add_inode_reached(irec, i);
6c39a3cb
BN
2824 }
2825}
2826
a1d54891 2827static void
2556c98b
BN
2828traverse_function(
2829 work_queue_t *wq,
2830 xfs_agnumber_t agno,
2831 void *arg)
a1d54891 2832{
2556c98b
BN
2833 ino_tree_node_t *irec;
2834 int i;
2835 prefetch_args_t *pf_args = arg;
2836
2837 wait_for_inode_prefetch(pf_args);
a1d54891
MV
2838
2839 if (verbose)
2840 do_log(_(" - agno = %d\n"), agno);
2841
2556c98b
BN
2842 for (irec = findfirst_inode_rec(agno); irec; irec = next_ino_rec(irec)) {
2843 if (irec->ino_isa_dir == 0)
2844 continue;
a1d54891 2845
2556c98b
BN
2846 if (pf_args)
2847 sem_post(&pf_args->ra_count);
a1d54891 2848
2556c98b
BN
2849 for (i = 0; i < XFS_INODES_PER_CHUNK; i++) {
2850 if (inode_isadir(irec, i))
575ca697 2851 process_dir_inode(wq->mp, agno, irec, i);
a1d54891 2852 }
a1d54891 2853 }
2556c98b 2854 cleanup_inode_prefetch(pf_args);
a1d54891
MV
2855}
2856
575ca697
BN
2857static void
2858update_missing_dotdot_entries(
2859 xfs_mount_t *mp)
2860{
2861 dotdot_update_t *dir;
2862
2863 /*
2864 * these entries parents were updated, rebuild them again
2865 * set dotdot_update flag so processing routines do not count links
2866 */
2867 dotdot_update = 1;
2868 while (dotdot_update_list) {
2869 dir = dotdot_update_list;
2870 dotdot_update_list = dir->next;
2871 process_dir_inode(mp, dir->agno, dir->irec, dir->ino_offset);
2872 free(dir);
2873 }
2874}
2875
a1d54891 2876static void
2556c98b
BN
2877traverse_ags(
2878 xfs_mount_t *mp)
a1d54891
MV
2879{
2880 int i;
69ec88b5 2881 work_queue_t queue;
2556c98b
BN
2882 prefetch_args_t *pf_args[2];
2883
69ec88b5
BN
2884 /*
2885 * we always do prefetch for phase 6 as it will fill in the gaps
2886 * not read during phase 3 prefetch.
2887 */
2888 queue.mp = mp;
2889 pf_args[0] = start_inode_prefetch(0, 1, NULL);
2890 for (i = 0; i < glob_agcount; i++) {
2891 pf_args[(~i) & 1] = start_inode_prefetch(i + 1, 1,
2892 pf_args[i & 1]);
2893 traverse_function(&queue, i, pf_args[i & 1]);
a1d54891
MV
2894 }
2895}
2896
2bd0ea18
NS
2897void
2898phase6(xfs_mount_t *mp)
2899{
2bd0ea18 2900 ino_tree_node_t *irec;
2bd0ea18 2901 int i;
2bd0ea18 2902
dab9b8d6
BN
2903 memset(&zerocr, 0, sizeof(struct cred));
2904 memset(&zerofsx, 0, sizeof(struct fsxattr));
6c39a3cb 2905 orphanage_ino = 0;
2bd0ea18 2906
507f4e33 2907 do_log(_("Phase 6 - check inode connectivity...\n"));
2bd0ea18 2908
2bd0ea18
NS
2909 incore_ext_teardown(mp);
2910
0f012a4c 2911 add_ino_ex_data(mp);
2bd0ea18
NS
2912
2913 /*
2914 * verify existence of root directory - if we have to
2915 * make one, it's ok for the incore data structs not to
2916 * know about it since everything about it (and the other
2917 * inodes in its chunk if a new chunk was created) are ok
2918 */
2919 if (need_root_inode) {
9a048535 2920 if (!no_modify) {
507f4e33 2921 do_warn(_("reinitializing root directory\n"));
2bd0ea18
NS
2922 mk_root_dir(mp);
2923 need_root_inode = 0;
2924 need_root_dotdot = 0;
2925 } else {
507f4e33 2926 do_warn(_("would reinitialize root directory\n"));
2bd0ea18
NS
2927 }
2928 }
2929
2930 if (need_rbmino) {
2931 if (!no_modify) {
507f4e33 2932 do_warn(_("reinitializing realtime bitmap inode\n"));
2bd0ea18
NS
2933 mk_rbmino(mp);
2934 need_rbmino = 0;
2935 } else {
507f4e33 2936 do_warn(_("would reinitialize realtime bitmap inode\n"));
2bd0ea18
NS
2937 }
2938 }
2939
2940 if (need_rsumino) {
2941 if (!no_modify) {
507f4e33 2942 do_warn(_("reinitializing realtime summary inode\n"));
2bd0ea18
NS
2943 mk_rsumino(mp);
2944 need_rsumino = 0;
2945 } else {
507f4e33 2946 do_warn(_("would reinitialize realtime summary inode\n"));
2bd0ea18
NS
2947 }
2948 }
2949
2950 if (!no_modify) {
2951 do_log(
507f4e33 2952_(" - resetting contents of realtime bitmap and summary inodes\n"));
2bd0ea18
NS
2953 if (fill_rbmino(mp)) {
2954 do_warn(
507f4e33 2955 _("Warning: realtime bitmap may be inconsistent\n"));
2bd0ea18
NS
2956 }
2957
2958 if (fill_rsumino(mp)) {
2959 do_warn(
507f4e33 2960 _("Warning: realtime bitmap may be inconsistent\n"));
2bd0ea18
NS
2961 }
2962 }
2963
2bd0ea18
NS
2964 mark_standalone_inodes(mp);
2965
69ec88b5 2966 do_log(_(" - traversing filesystem ...\n"));
2bd0ea18 2967
1ae311d5 2968 irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, mp->m_sb.sb_rootino),
2bd0ea18
NS
2969 XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rootino));
2970
2971 /*
2972 * we always have a root inode, even if it's free...
2973 * if the root is free, forget it, lost+found is already gone
2974 */
2975 if (is_inode_free(irec, 0) || !inode_isadir(irec, 0)) {
2976 need_root_inode = 1;
2977 }
2978
2979 /*
2556c98b 2980 * then process all inodes by walking incore inode tree
2bd0ea18 2981 */
2556c98b 2982 traverse_ags(mp);
2bd0ea18 2983
575ca697
BN
2984 /*
2985 * any directories that had updated ".." entries, rebuild them now
2986 */
2987 update_missing_dotdot_entries(mp);
2988
69ec88b5
BN
2989 do_log(_(" - traversal finished ...\n"));
2990 do_log(_(" - moving disconnected inodes to %s ...\n"),
6c39a3cb 2991 ORPHANAGE);
2bd0ea18
NS
2992
2993 /*
2994 * move all disconnected inodes to the orphanage
2995 */
2996 for (i = 0; i < glob_agcount; i++) {
2997 irec = findfirst_inode_rec(i);
2bd0ea18 2998 while (irec != NULL) {
2556c98b 2999 check_for_orphaned_inodes(mp, i, irec);
2bd0ea18
NS
3000 irec = next_ino_rec(irec);
3001 }
3002 }
3003}