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