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