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