2 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like. Any license provided herein, whether implied or
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc., 59
21 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
28 * For further information regarding this notice, see:
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
41 #include "dir_stack.h"
43 #include "err_protos.h"
48 static int orphanage_entered
;
51 * Data structures and routines to keep track of directory entries
52 * and whether their leaf entry has been seen
54 typedef struct dir_hash_ent
{
55 struct dir_hash_ent
*next
; /* pointer to next entry */
56 xfs_dir2_leaf_entry_t ent
; /* address and hash value */
57 short junkit
; /* name starts with / */
58 short seen
; /* have seen leaf entry */
61 typedef struct dir_hash_tab
{
62 int size
; /* size of hash table */
63 dir_hash_ent_t
*tab
[1];/* actual hash table, variable size */
65 #define DIR_HASH_TAB_SIZE(n) \
66 (offsetof(dir_hash_tab_t, tab) + (sizeof(dir_hash_ent_t *) * (n)))
67 #define DIR_HASH_FUNC(t,a) ((a) % (t)->size)
70 * Track the contents of the freespace table in a directory.
72 typedef struct freetab
{
76 xfs_dir2_data_off_t v
;
80 #define FREETAB_SIZE(n) \
81 (offsetof(freetab_t, ents) + (sizeof(struct freetab_ent) * (n)))
83 #define DIR_HASH_CK_OK 0
84 #define DIR_HASH_CK_DUPLEAF 1
85 #define DIR_HASH_CK_BADHASH 2
86 #define DIR_HASH_CK_NODATA 3
87 #define DIR_HASH_CK_NOLEAF 4
88 #define DIR_HASH_CK_BADSTALE 5
92 dir_hash_tab_t
*hashtab
,
94 xfs_dir2_dataptr_t addr
,
100 i
= DIR_HASH_FUNC(hashtab
, addr
);
101 if ((p
= malloc(sizeof(*p
))) == NULL
) {
102 do_error("malloc failed in dir_hash_add (%u bytes)\n",
106 p
->next
= hashtab
->tab
[i
];
108 if (!(p
->junkit
= junk
))
109 p
->ent
.hashval
= hash
;
110 p
->ent
.address
= addr
;
116 dir_hash_tab_t
*hashtab
)
121 for (i
= 0; i
< hashtab
->size
; i
++) {
122 for (p
= hashtab
->tab
[i
]; p
; p
= p
->next
) {
132 dir_hash_tab_t
*hashtab
,
136 static char *seevalstr
[] = {
139 "hash value mismatch",
145 if (seeval
== DIR_HASH_CK_OK
&& dir_hash_unseen(hashtab
))
146 seeval
= DIR_HASH_CK_NOLEAF
;
147 if (seeval
== DIR_HASH_CK_OK
)
149 do_warn("bad hash table for directory inode %llu (%s): ", ip
->i_ino
,
152 do_warn("rebuilding\n");
154 do_warn("would rebuild\n");
160 dir_hash_tab_t
*hashtab
)
166 for (i
= 0; i
< hashtab
->size
; i
++) {
167 for (p
= hashtab
->tab
[i
]; p
; p
= n
) {
175 static dir_hash_tab_t
*
179 dir_hash_tab_t
*hashtab
;
182 hsize
= size
/ (16 * 4);
187 if ((hashtab
= calloc(DIR_HASH_TAB_SIZE(hsize
), 1)) == NULL
) {
188 do_error("calloc failed in dir_hash_init\n");
191 hashtab
->size
= hsize
;
197 dir_hash_tab_t
*hashtab
,
199 xfs_dir2_dataptr_t addr
)
204 i
= DIR_HASH_FUNC(hashtab
, addr
);
205 for (p
= hashtab
->tab
[i
]; p
; p
= p
->next
) {
206 if (p
->ent
.address
!= addr
)
209 return DIR_HASH_CK_DUPLEAF
;
210 if (p
->junkit
== 0 && p
->ent
.hashval
!= hash
)
211 return DIR_HASH_CK_BADHASH
;
213 return DIR_HASH_CK_OK
;
215 return DIR_HASH_CK_NODATA
;
220 dir_hash_tab_t
*hashtab
,
221 xfs_dir2_leaf_entry_t
*ents
,
229 for (i
= j
= 0; i
< count
; i
++) {
230 if (INT_GET(ents
[i
].address
, ARCH_CONVERT
) == XFS_DIR2_NULL_DATAPTR
) {
234 rval
= dir_hash_see(hashtab
, INT_GET(ents
[i
].hashval
, ARCH_CONVERT
), INT_GET(ents
[i
].address
, ARCH_CONVERT
));
235 if (rval
!= DIR_HASH_CK_OK
)
238 return j
== stale
? DIR_HASH_CK_OK
: DIR_HASH_CK_BADSTALE
;
243 * Version 1 or 2 directory routine wrappers
246 dir_init(xfs_mount_t
*mp
, xfs_trans_t
*tp
, xfs_inode_t
*dp
, xfs_inode_t
*pdp
)
248 if (XFS_SB_VERSION_HASDIRV2(&mp
->m_sb
))
249 libxfs_dir2_init(tp
, dp
, pdp
);
251 libxfs_dir_init(tp
, dp
, pdp
);
255 dir_createname(xfs_mount_t
*mp
, xfs_trans_t
*tp
, xfs_inode_t
*pip
,
256 char *name
, int namelen
, xfs_ino_t inum
, xfs_fsblock_t
*first
,
257 xfs_bmap_free_t
*flist
, xfs_extlen_t total
)
259 if (XFS_SB_VERSION_HASDIRV2(&mp
->m_sb
))
260 return libxfs_dir2_createname(tp
, pip
, name
, namelen
,
261 inum
, first
, flist
, total
);
263 return libxfs_dir_createname(tp
, pip
, name
, namelen
,
264 inum
, first
, flist
, total
);
268 dir_lookup(xfs_mount_t
*mp
, xfs_trans_t
*tp
, xfs_inode_t
*dp
, char *name
,
269 int namelen
, xfs_ino_t
*inum
)
271 if (XFS_SB_VERSION_HASDIRV2(&mp
->m_sb
))
272 return libxfs_dir2_lookup(tp
, dp
, name
, namelen
, inum
);
274 return libxfs_dir_lookup(tp
, dp
, name
, namelen
, inum
);
278 dir_replace(xfs_mount_t
*mp
, xfs_trans_t
*tp
, xfs_inode_t
*dp
, char *name
,
279 int namelen
, xfs_ino_t inum
, xfs_fsblock_t
*firstblock
,
280 xfs_bmap_free_t
*flist
, xfs_extlen_t total
)
282 if (XFS_SB_VERSION_HASDIRV2(&mp
->m_sb
))
283 return libxfs_dir2_replace(tp
, dp
, name
, namelen
, inum
,
284 firstblock
, flist
, total
);
286 return libxfs_dir_replace(tp
, dp
, name
, namelen
, inum
,
287 firstblock
, flist
, total
);
291 dir_removename(xfs_mount_t
*mp
, xfs_trans_t
*tp
, xfs_inode_t
*dp
, char *name
,
292 int namelen
, xfs_ino_t inum
, xfs_fsblock_t
*firstblock
,
293 xfs_bmap_free_t
*flist
, xfs_extlen_t total
)
295 if (XFS_SB_VERSION_HASDIRV2(&mp
->m_sb
))
296 return libxfs_dir2_removename(tp
, dp
, name
, namelen
, inum
,
297 firstblock
, flist
, total
);
299 return libxfs_dir_removename(tp
, dp
, name
, namelen
, inum
,
300 firstblock
, flist
, total
);
304 dir_bogus_removename(xfs_mount_t
*mp
, xfs_trans_t
*tp
, xfs_inode_t
*dp
,
305 char *name
, xfs_fsblock_t
*firstblock
, xfs_bmap_free_t
*flist
,
306 xfs_extlen_t total
, xfs_dahash_t hashval
, int namelen
)
308 if (XFS_SB_VERSION_HASDIRV2(&mp
->m_sb
))
309 return libxfs_dir2_bogus_removename(tp
, dp
, name
, firstblock
,
310 flist
, total
, hashval
, namelen
);
312 return libxfs_dir_bogus_removename(tp
, dp
, name
, firstblock
,
313 flist
, total
, hashval
, namelen
);
322 do_error("ran out of disk space!\n");
324 do_error("xfs_trans_reserve returned %d\n", err
);
328 mk_rbmino(xfs_mount_t
*mp
)
338 xfs_bmap_free_t flist
;
340 xfs_bmbt_irec_t map
[XFS_BMAP_MAX_NMAP
];
345 tp
= libxfs_trans_alloc(mp
, 0);
347 if (i
= libxfs_trans_reserve(tp
, 10, 0, 0, 0, 0))
350 error
= libxfs_trans_iget(mp
, tp
, mp
->m_sb
.sb_rbmino
, 0, &ip
);
352 do_error("couldn't iget realtime bitmap inode -- error - %d\n",
356 bzero(&ip
->i_d
, sizeof(xfs_dinode_core_t
));
358 ip
->i_d
.di_magic
= XFS_DINODE_MAGIC
;
359 ip
->i_d
.di_mode
= IFREG
;
360 ip
->i_d
.di_version
= XFS_DINODE_VERSION_1
;
361 ip
->i_d
.di_format
= XFS_DINODE_FMT_EXTENTS
;
362 ip
->i_d
.di_aformat
= XFS_DINODE_FMT_EXTENTS
;
364 ip
->i_d
.di_nlink
= 1; /* account for sb ptr */
369 ip
->i_df
.if_flags
= XFS_IFEXTENTS
;
370 ip
->i_df
.if_bytes
= ip
->i_df
.if_real_bytes
= 0;
371 ip
->i_df
.if_u1
.if_extents
= NULL
;
373 ip
->i_d
.di_size
= mp
->m_sb
.sb_rbmblocks
* mp
->m_sb
.sb_blocksize
;
378 libxfs_trans_log_inode(tp
, ip
, XFS_ILOG_CORE
);
379 libxfs_trans_ihold(tp
, ip
);
380 libxfs_trans_commit(tp
, XFS_TRANS_RELEASE_LOG_RES
|XFS_TRANS_SYNC
, NULL
);
383 * then allocate blocks for file and fill with zeroes (stolen
386 tp
= libxfs_trans_alloc(mp
, 0);
387 if (error
= libxfs_trans_reserve(tp
, mp
->m_sb
.sb_rbmblocks
+
388 (XFS_BM_MAXLEVELS(mp
, XFS_DATA_FORK
) - 1), 0, 0, 0, 0))
391 libxfs_trans_ijoin(tp
, ip
, 0);
393 XFS_BMAP_INIT(&flist
, &first
);
394 while (bno
< mp
->m_sb
.sb_rbmblocks
) {
395 nmap
= XFS_BMAP_MAX_NMAP
;
396 error
= libxfs_bmapi(tp
, ip
, bno
,
397 (xfs_extlen_t
)(mp
->m_sb
.sb_rbmblocks
- bno
),
398 XFS_BMAPI_WRITE
, &first
, mp
->m_sb
.sb_rbmblocks
,
401 do_error("couldn't allocate realtime bitmap - err %d\n",
404 for (i
= 0, ep
= map
; i
< nmap
; i
++, ep
++) {
405 libxfs_device_zero(mp
->m_dev
,
406 XFS_FSB_TO_DADDR(mp
, ep
->br_startblock
),
407 XFS_FSB_TO_BB(mp
, ep
->br_blockcount
));
408 bno
+= ep
->br_blockcount
;
411 error
= libxfs_bmap_finish(&tp
, &flist
, first
, &committed
);
414 "allocation of the realtime bitmap failed, error = %d\n",
417 libxfs_trans_commit(tp
, XFS_TRANS_RELEASE_LOG_RES
|XFS_TRANS_SYNC
, 0);
421 fill_rbmino(xfs_mount_t
*mp
)
436 tp
= libxfs_trans_alloc(mp
, 0);
438 if (error
= libxfs_trans_reserve(tp
, 10, 0, 0, 0, 0))
441 error
= libxfs_trans_iget(mp
, tp
, mp
->m_sb
.sb_rbmino
, 0, &ip
);
443 do_error("couldn't iget realtime bitmap inode -- error - %d\n",
447 while (bno
< mp
->m_sb
.sb_rbmblocks
) {
449 * fill the file one block at a time
452 error
= libxfs_bmapi(tp
, ip
, bno
, 1, XFS_BMAPI_WRITE
,
453 &first
, 1, &map
, &nmap
, NULL
);
454 if (error
|| nmap
!= 1) {
456 "couldn't map realtime bitmap block %llu - err %d\n",
460 ASSERT(map
.br_startblock
!= HOLESTARTBLOCK
);
462 error
= libxfs_trans_read_buf(
464 XFS_FSB_TO_DADDR(mp
, map
.br_startblock
),
465 XFS_FSB_TO_BB(mp
, 1), 1, &bp
);
469 "can't access block %llu (fsbno %llu) of realtime bitmap inode %llu\n",
470 bno
, map
.br_startblock
, mp
->m_sb
.sb_rbmino
);
474 bcopy(bmp
, XFS_BUF_PTR(bp
), mp
->m_sb
.sb_blocksize
);
476 libxfs_trans_log_buf(tp
, bp
, 0, mp
->m_sb
.sb_blocksize
- 1);
478 bmp
= (xfs_rtword_t
*)((__psint_t
) bmp
+ mp
->m_sb
.sb_blocksize
);
482 libxfs_trans_commit(tp
, XFS_TRANS_RELEASE_LOG_RES
|XFS_TRANS_SYNC
, 0);
488 fill_rsumino(xfs_mount_t
*mp
)
498 xfs_dfiloff_t end_bno
;
503 end_bno
= mp
->m_rsumsize
>> mp
->m_sb
.sb_blocklog
;
505 tp
= libxfs_trans_alloc(mp
, 0);
507 if (error
= libxfs_trans_reserve(tp
, 10, 0, 0, 0, 0))
510 error
= libxfs_trans_iget(mp
, tp
, mp
->m_sb
.sb_rsumino
, 0, &ip
);
512 do_error("couldn't iget realtime summary inode -- error - %d\n",
516 while (bno
< end_bno
) {
518 * fill the file one block at a time
521 error
= libxfs_bmapi(tp
, ip
, bno
, 1, XFS_BMAPI_WRITE
,
522 &first
, 1, &map
, &nmap
, NULL
);
523 if (error
|| nmap
!= 1) {
525 "couldn't map realtime summary inode block %llu - err %d\n",
529 ASSERT(map
.br_startblock
!= HOLESTARTBLOCK
);
531 error
= libxfs_trans_read_buf(
533 XFS_FSB_TO_DADDR(mp
, map
.br_startblock
),
534 XFS_FSB_TO_BB(mp
, 1), 1, &bp
);
538 "can't access block %llu (fsbno %llu) of realtime summary inode %llu\n",
539 bno
, map
.br_startblock
, mp
->m_sb
.sb_rsumino
);
543 bcopy(smp
, XFS_BUF_PTR(bp
), mp
->m_sb
.sb_blocksize
);
545 libxfs_trans_log_buf(tp
, bp
, 0, mp
->m_sb
.sb_blocksize
- 1);
547 smp
= (xfs_suminfo_t
*)((__psint_t
)smp
+ mp
->m_sb
.sb_blocksize
);
551 libxfs_trans_commit(tp
, XFS_TRANS_RELEASE_LOG_RES
|XFS_TRANS_SYNC
, 0);
557 mk_rsumino(xfs_mount_t
*mp
)
568 xfs_bmap_free_t flist
;
570 xfs_bmbt_irec_t map
[XFS_BMAP_MAX_NMAP
];
575 tp
= libxfs_trans_alloc(mp
, 0);
577 if (i
= libxfs_trans_reserve(tp
, 10, XFS_ICHANGE_LOG_RES(mp
), 0,
578 XFS_TRANS_PERM_LOG_RES
, XFS_MKDIR_LOG_COUNT
))
581 error
= libxfs_trans_iget(mp
, tp
, mp
->m_sb
.sb_rsumino
, 0, &ip
);
583 do_error("couldn't iget realtime summary inode -- error - %d\n",
587 bzero(&ip
->i_d
, sizeof(xfs_dinode_core_t
));
589 ip
->i_d
.di_magic
= XFS_DINODE_MAGIC
;
590 ip
->i_d
.di_mode
= IFREG
;
591 ip
->i_d
.di_version
= XFS_DINODE_VERSION_1
;
592 ip
->i_d
.di_format
= XFS_DINODE_FMT_EXTENTS
;
593 ip
->i_d
.di_aformat
= XFS_DINODE_FMT_EXTENTS
;
595 ip
->i_d
.di_nlink
= 1; /* account for sb ptr */
600 ip
->i_df
.if_flags
= XFS_IFEXTENTS
;
601 ip
->i_df
.if_bytes
= ip
->i_df
.if_real_bytes
= 0;
602 ip
->i_df
.if_u1
.if_extents
= NULL
;
604 ip
->i_d
.di_size
= mp
->m_rsumsize
;
609 libxfs_trans_log_inode(tp
, ip
, XFS_ILOG_CORE
);
610 libxfs_trans_ihold(tp
, ip
);
611 libxfs_trans_commit(tp
, XFS_TRANS_RELEASE_LOG_RES
|XFS_TRANS_SYNC
, 0);
614 * then allocate blocks for file and fill with zeroes (stolen
617 tp
= libxfs_trans_alloc(mp
, 0);
618 XFS_BMAP_INIT(&flist
, &first
);
620 nsumblocks
= mp
->m_rsumsize
>> mp
->m_sb
.sb_blocklog
;
621 if (error
= libxfs_trans_reserve(tp
,
622 mp
->m_sb
.sb_rbmblocks
+
623 (XFS_BM_MAXLEVELS(mp
, XFS_DATA_FORK
) - 1),
624 BBTOB(128), 0, XFS_TRANS_PERM_LOG_RES
,
625 XFS_DEFAULT_PERM_LOG_COUNT
))
628 libxfs_trans_ijoin(tp
, ip
, 0);
630 XFS_BMAP_INIT(&flist
, &first
);
631 while (bno
< nsumblocks
) {
632 nmap
= XFS_BMAP_MAX_NMAP
;
633 error
= libxfs_bmapi(tp
, ip
, bno
,
634 (xfs_extlen_t
)(nsumblocks
- bno
),
635 XFS_BMAPI_WRITE
, &first
, nsumblocks
,
639 "couldn't allocate realtime summary inode - err %d\n",
642 for (i
= 0, ep
= map
; i
< nmap
; i
++, ep
++) {
643 libxfs_device_zero(mp
->m_dev
,
644 XFS_FSB_TO_DADDR(mp
, ep
->br_startblock
),
645 XFS_FSB_TO_BB(mp
, ep
->br_blockcount
));
646 do_error("dev_zero of rtbitmap failed\n");
647 bno
+= ep
->br_blockcount
;
650 error
= libxfs_bmap_finish(&tp
, &flist
, first
, &committed
);
653 "allocation of the realtime summary ino failed, err = %d\n",
656 libxfs_trans_commit(tp
, XFS_TRANS_RELEASE_LOG_RES
|XFS_TRANS_SYNC
, 0);
660 * makes a new root directory.
663 mk_root_dir(xfs_mount_t
*mp
)
669 const mode_t mode
= 0755;
671 tp
= libxfs_trans_alloc(mp
, 0);
674 if (i
= libxfs_trans_reserve(tp
, 10, XFS_ICHANGE_LOG_RES(mp
), 0,
675 XFS_TRANS_PERM_LOG_RES
, XFS_MKDIR_LOG_COUNT
))
678 error
= libxfs_trans_iget(mp
, tp
, mp
->m_sb
.sb_rootino
, 0, &ip
);
680 do_error("could not iget root inode -- error - %d\n", error
);
684 * take care of the core -- initialization from xfs_ialloc()
686 bzero(&ip
->i_d
, sizeof(xfs_dinode_core_t
));
688 ip
->i_d
.di_magic
= XFS_DINODE_MAGIC
;
689 ip
->i_d
.di_mode
= (__uint16_t
) mode
|IFDIR
;
690 ip
->i_d
.di_version
= XFS_DINODE_VERSION_1
;
691 ip
->i_d
.di_format
= XFS_DINODE_FMT_EXTENTS
;
692 ip
->i_d
.di_aformat
= XFS_DINODE_FMT_EXTENTS
;
694 ip
->i_d
.di_nlink
= 1; /* account for . */
696 libxfs_trans_log_inode(tp
, ip
, XFS_ILOG_CORE
);
701 ip
->i_df
.if_flags
= XFS_IFEXTENTS
;
702 ip
->i_df
.if_bytes
= ip
->i_df
.if_real_bytes
= 0;
703 ip
->i_df
.if_u1
.if_extents
= NULL
;
708 * initialize the directory
710 dir_init(mp
, tp
, ip
, ip
);
712 libxfs_trans_commit(tp
, XFS_TRANS_RELEASE_LOG_RES
|XFS_TRANS_SYNC
, 0);
716 * orphanage name == lost+found
719 mk_orphanage(xfs_mount_t
*mp
)
729 xfs_bmap_free_t flist
;
730 const int mode
= 0755;
735 tp
= libxfs_trans_alloc(mp
, 0);
736 XFS_BMAP_INIT(&flist
, &first
);
738 nres
= XFS_MKDIR_SPACE_RES(mp
, strlen(ORPHANAGE
));
739 if (i
= libxfs_trans_reserve(tp
, nres
, XFS_MKDIR_LOG_RES(mp
), 0,
740 XFS_TRANS_PERM_LOG_RES
, XFS_MKDIR_LOG_COUNT
))
744 * use iget/ijoin instead of trans_iget because the ialloc
745 * wrapper can commit the transaction and start a new one
747 if (i
= libxfs_iget(mp
, NULL
, mp
->m_sb
.sb_rootino
, 0, &pip
, 0))
748 do_error("%d - couldn't iget root inode to make %s\n",
751 error
= libxfs_inode_alloc(&tp
, pip
, mode
|IFDIR
,
752 1, mp
->m_dev
, &zerocr
, &ip
);
755 do_error("%s inode allocation failed %d\n",
759 ip
->i_d
.di_uid
= uid
;
760 ip
->i_d
.di_gid
= gid
;
761 ip
->i_d
.di_nlink
++; /* account for . */
764 * now that we know the transaction will stay around,
765 * add the root inode to it
767 libxfs_trans_ijoin(tp
, pip
, 0);
770 * create the actual entry
772 if (error
= dir_createname(mp
, tp
, pip
, ORPHANAGE
,
773 strlen(ORPHANAGE
), ip
->i_ino
, &first
, &flist
, nres
)) {
774 do_warn("can't make %s, createname error %d, will try later\n",
776 orphanage_entered
= 0;
778 orphanage_entered
= 1;
781 * bump up the link count in the root directory to account
782 * for .. in the new directory
786 libxfs_trans_log_inode(tp
, pip
, XFS_ILOG_CORE
);
787 dir_init(mp
, tp
, ip
, pip
);
788 libxfs_trans_log_inode(tp
, ip
, XFS_ILOG_CORE
);
790 error
= libxfs_bmap_finish(&tp
, &flist
, first
, &committed
);
792 do_error("%s directory creation failed -- bmapf error %d\n",
798 libxfs_trans_commit(tp
, XFS_TRANS_RELEASE_LOG_RES
|XFS_TRANS_SYNC
, 0);
800 /* need libxfs_iput here? - nathans TODO - possible memory leak? */
806 * move a file to the orphange. the orphanage is guaranteed
807 * at this point to only have file in it whose name == file inode #
810 mv_orphanage(xfs_mount_t
*mp
,
811 xfs_ino_t dir_ino
, /* orphange inode # */
812 xfs_ino_t ino
, /* inode # to be moved */
813 int isa_dir
) /* 1 if inode is a directory */
815 xfs_ino_t entry_ino_num
;
816 xfs_inode_t
*dir_ino_p
;
820 xfs_bmap_free_t flist
;
823 char fname
[MAXPATHLEN
+ 1];
826 sprintf(fname
, "%llu", (unsigned long long)ino
);
828 if (err
= libxfs_iget(mp
, NULL
, dir_ino
, 0, &dir_ino_p
, 0))
829 do_error("%d - couldn't iget orphanage inode\n", err
);
831 tp
= libxfs_trans_alloc(mp
, 0);
833 if (err
= libxfs_iget(mp
, NULL
, ino
, 0, &ino_p
, 0))
834 do_error("%d - couldn't iget disconnected inode\n", err
);
837 nres
= XFS_DIRENTER_SPACE_RES(mp
, strlen(fname
)) +
838 XFS_DIRENTER_SPACE_RES(mp
, 2);
839 if (err
= dir_lookup(mp
, tp
, ino_p
, "..", 2,
841 ASSERT(err
== ENOENT
);
843 if (err
= libxfs_trans_reserve(tp
, nres
,
844 XFS_RENAME_LOG_RES(mp
), 0,
845 XFS_TRANS_PERM_LOG_RES
,
846 XFS_RENAME_LOG_COUNT
))
848 "space reservation failed (%d), filesystem may be out of space\n",
851 libxfs_trans_ijoin(tp
, dir_ino_p
, 0);
852 libxfs_trans_ijoin(tp
, ino_p
, 0);
854 XFS_BMAP_INIT(&flist
, &first
);
855 if (err
= dir_createname(mp
, tp
, dir_ino_p
, fname
,
856 strlen(fname
), ino
, &first
,
859 "name create failed in %s (%d), filesystem may be out of space\n",
862 dir_ino_p
->i_d
.di_nlink
++;
863 libxfs_trans_log_inode(tp
, dir_ino_p
, XFS_ILOG_CORE
);
865 if (err
= dir_createname(mp
, tp
, ino_p
, "..", 2,
866 dir_ino
, &first
, &flist
, nres
))
868 "creation of .. entry failed (%d), filesystem may be out of space\n",
871 ino_p
->i_d
.di_nlink
++;
872 libxfs_trans_log_inode(tp
, ino_p
, XFS_ILOG_CORE
);
874 if (err
= libxfs_bmap_finish(&tp
, &flist
, first
, &committed
))
876 "bmap finish failed (err - %d), filesystem may be out of space\n",
879 libxfs_trans_commit(tp
,
880 XFS_TRANS_RELEASE_LOG_RES
|XFS_TRANS_SYNC
, 0);
882 if (err
= libxfs_trans_reserve(tp
, nres
,
883 XFS_RENAME_LOG_RES(mp
), 0,
884 XFS_TRANS_PERM_LOG_RES
,
885 XFS_RENAME_LOG_COUNT
))
887 "space reservation failed (%d), filesystem may be out of space\n",
890 libxfs_trans_ijoin(tp
, dir_ino_p
, 0);
891 libxfs_trans_ijoin(tp
, ino_p
, 0);
893 XFS_BMAP_INIT(&flist
, &first
);
895 if (err
= dir_createname(mp
, tp
, dir_ino_p
, fname
,
896 strlen(fname
), ino
, &first
,
899 "name create failed in %s (%d), filesystem may be out of space\n",
902 dir_ino_p
->i_d
.di_nlink
++;
903 libxfs_trans_log_inode(tp
, dir_ino_p
, XFS_ILOG_CORE
);
906 * don't replace .. value if it already points
907 * to us. that'll pop a libxfs/kernel ASSERT.
909 if (entry_ino_num
!= dir_ino
) {
910 if (err
= dir_replace(mp
, tp
, ino_p
, "..",
914 "name replace op failed (%d), filesystem may be out of space\n",
918 if (err
= libxfs_bmap_finish(&tp
, &flist
, first
,
921 "bmap finish failed (%d), filesystem may be out of space\n",
924 libxfs_trans_commit(tp
,
925 XFS_TRANS_RELEASE_LOG_RES
|XFS_TRANS_SYNC
, 0);
929 * use the remove log reservation as that's
930 * more accurate. we're only creating the
931 * links, we're not doing the inode allocation
932 * also accounted for in the create
934 nres
= XFS_DIRENTER_SPACE_RES(mp
, strlen(fname
));
935 if (err
= libxfs_trans_reserve(tp
, nres
, XFS_REMOVE_LOG_RES(mp
), 0,
936 XFS_TRANS_PERM_LOG_RES
, XFS_REMOVE_LOG_COUNT
))
938 "space reservation failed (%d), filesystem may be out of space\n",
941 libxfs_trans_ijoin(tp
, dir_ino_p
, 0);
942 libxfs_trans_ijoin(tp
, ino_p
, 0);
944 XFS_BMAP_INIT(&flist
, &first
);
945 if (err
= dir_createname(mp
, tp
, dir_ino_p
, fname
,
946 strlen(fname
), ino
, &first
, &flist
, nres
))
948 "name create failed in %s (%d), filesystem may be out of space\n",
952 ino_p
->i_d
.di_nlink
= 1;
953 libxfs_trans_log_inode(tp
, ino_p
, XFS_ILOG_CORE
);
955 if (err
= libxfs_bmap_finish(&tp
, &flist
, first
, &committed
))
957 "bmap finish failed (%d), filesystem may be out of space\n",
960 libxfs_trans_commit(tp
, XFS_TRANS_RELEASE_LOG_RES
|XFS_TRANS_SYNC
, 0);
965 * like get_first_dblock_fsbno only it uses the simulation code instead
968 * Returns the fsbno of the first (leftmost) block in the directory leaf.
969 * sets *bno to the directory block # corresponding to the returned fsbno.
972 map_first_dblock_fsbno(xfs_mount_t
*mp
,
977 xfs_fsblock_t fblock
;
978 xfs_da_intnode_t
*node
;
989 * traverse down left-side of tree until we hit the
990 * left-most leaf block setting up the btree cursor along
997 fblock
= NULLFSBLOCK
;
1001 error
= libxfs_bmapi(NULL
, ip
, (xfs_fileoff_t
) da_bno
, 1,
1002 XFS_BMAPI_METADATA
, &fblock
, 0,
1004 if (error
|| nmap
!= 1) {
1007 "can't map block %d in %s inode %llu, xfs_bmapi returns %d, nmap = %d\n",
1008 da_bno
, ftype
, ino
, error
, nmap
);
1011 "can't map block %d in %s inode %llu, xfs_bmapi returns %d, nmap = %d\n",
1012 da_bno
, ftype
, ino
, error
, nmap
);
1017 if ((fsbno
= map
.br_startblock
) == HOLESTARTBLOCK
) {
1019 do_error("block %d in %s ino %llu doesn't exist\n",
1020 da_bno
, ftype
, ino
);
1022 do_warn("block %d in %s ino %llu doesn't exist\n",
1023 da_bno
, ftype
, ino
);
1028 if (ip
->i_d
.di_size
<= XFS_LBSIZE(mp
))
1031 if (XFS_SB_VERSION_HASDIRV2(&mp
->m_sb
))
1036 * walk down left side of btree, release buffers as you
1037 * go. if the root block is a leaf (single-level btree),
1042 bp
= libxfs_readbuf(mp
->m_dev
, XFS_FSB_TO_DADDR(mp
, fsbno
),
1043 XFS_FSB_TO_BB(mp
, 1), 0);
1047 "can't read block %u (fsbno %llu) for directory inode %llu\n",
1048 da_bno
, fsbno
, ino
);
1052 node
= (xfs_da_intnode_t
*)XFS_BUF_PTR(bp
);
1054 if (INT_GET(node
->hdr
.info
.magic
, ARCH_CONVERT
) != XFS_DA_NODE_MAGIC
) {
1057 "bad dir/attr magic number in inode %llu, file bno = %u, fsbno = %llu\n",
1058 ino
, da_bno
, fsbno
);
1063 i
= INT_GET(node
->hdr
.level
, ARCH_CONVERT
);
1065 da_bno
= INT_GET(node
->btree
[0].before
, ARCH_CONVERT
);
1071 error
= libxfs_bmapi(NULL
, ip
, (xfs_fileoff_t
) da_bno
, 1,
1072 XFS_BMAPI_METADATA
, &fblock
, 0,
1074 if (error
|| nmap
!= 1) {
1077 "can't map block %d in %s ino %llu, xfs_bmapi returns %d, nmap = %d\n",
1078 da_bno
, ftype
, ino
, error
, nmap
);
1081 "can't map block %d in %s ino %llu, xfs_bmapi returns %d, nmap = %d\n",
1082 da_bno
, ftype
, ino
, error
, nmap
);
1086 if ((fsbno
= map
.br_startblock
) == HOLESTARTBLOCK
) {
1089 "block %d in %s inode %llu doesn't exist\n",
1090 da_bno
, ftype
, ino
);
1093 "block %d in %s inode %llu doesn't exist\n",
1094 da_bno
, ftype
, ino
);
1107 * scan longform directory and prune first bad entry. returns 1 if
1108 * it had to remove something, 0 if it made it all the way through
1109 * the directory. prune_lf_dir_entry does all the necessary bmap calls.
1111 * hashval is an in/out -- starting hashvalue in, hashvalue of the
1112 * deleted entry (if there was one) out
1114 * this routine can NOT be called if running in no modify mode
1117 prune_lf_dir_entry(xfs_mount_t
*mp
, xfs_ino_t ino
, xfs_inode_t
*ip
,
1118 xfs_dahash_t
*hashval
)
1125 xfs_bmap_free_t free_list
;
1126 xfs_fsblock_t first_block
;
1128 xfs_dir_leaf_name_t
*namest
;
1129 xfs_dir_leafblock_t
*leaf
;
1130 xfs_dir_leaf_entry_t
*entry
;
1133 xfs_fsblock_t fblock
;
1136 xfs_bmbt_irec_t map
;
1137 char fname
[MAXNAMELEN
+ 1];
1142 * ok, this is kind of a schizoid routine. we use our
1143 * internal bmapi routines to walk the directory. when
1144 * we find a bogus entry, we release the buffer so
1145 * the simulation code doesn't deadlock and use the
1146 * sim code to remove the entry. That will cause an
1147 * extra bmap traversal to map the block but I think
1148 * that's preferable to hacking the bogus removename
1149 * function to be really different and then trying to
1150 * maintain both versions as time goes on.
1152 * first, grab the dinode and find the right leaf block.
1159 fblock
= NULLFSBLOCK
;
1161 fsbno
= map_first_dblock_fsbno(mp
, ino
, ip
, &da_bno
);
1164 * now go foward along the leaves of the btree looking
1165 * for an entry beginning with '/'
1168 bp
= libxfs_readbuf(mp
->m_dev
, XFS_FSB_TO_DADDR(mp
, fsbno
),
1169 XFS_FSB_TO_BB(mp
, 1), 0);
1173 "can't read directory inode %llu (leaf) block %u (fsbno %llu)\n",
1174 ino
, da_bno
, fsbno
);
1178 leaf
= (xfs_dir_leafblock_t
*)XFS_BUF_PTR(bp
);
1179 ASSERT(INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
) == XFS_DIR_LEAF_MAGIC
);
1180 entry
= &leaf
->entries
[0];
1182 for (index
= -1, i
= 0;
1183 i
< INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
) && index
== -1;
1185 namest
= XFS_DIR_LEAF_NAMESTRUCT(leaf
, INT_GET(entry
->nameidx
, ARCH_CONVERT
));
1186 if (namest
->name
[0] != '/')
1193 * if we got a bogus entry, exit loop with a pointer to
1194 * the leaf block buffer. otherwise, keep trying blocks
1196 da_bno
= INT_GET(leaf
->hdr
.info
.forw
, ARCH_CONVERT
);
1205 * map next leaf block unless we've run out
1209 error
= libxfs_bmapi(NULL
, ip
,
1210 (xfs_fileoff_t
) da_bno
, 1,
1211 XFS_BMAPI_METADATA
, &fblock
, 0,
1213 if (error
|| nmap
!= 1)
1215 "can't map block %d in directory %llu, xfs_bmapi returns %d, nmap = %d\n",
1216 da_bno
, ino
, error
, nmap
);
1217 if ((fsbno
= map
.br_startblock
)
1218 == HOLESTARTBLOCK
) {
1220 "%s ino %llu block %d doesn't exist\n",
1221 ftype
, ino
, da_bno
);
1225 } while (da_bno
!= 0 && index
== -1);
1228 * if we hit the edge of the tree with no bad entries, we're done
1229 * and the buffer was released.
1231 if (da_bno
== 0 && index
== -1)
1235 ASSERT(entry
== &leaf
->entries
[index
]);
1236 ASSERT(namest
== XFS_DIR_LEAF_NAMESTRUCT(leaf
, INT_GET(entry
->nameidx
, ARCH_CONVERT
)));
1239 * snag the info we need out of the directory then release all buffers
1241 bcopy(namest
->name
, fname
, entry
->namelen
);
1242 fname
[entry
->namelen
] = '\0';
1243 *hashval
= INT_GET(entry
->hashval
, ARCH_CONVERT
);
1244 namelen
= entry
->namelen
;
1249 * ok, now the hard part, blow away the index'th entry in this block
1251 * allocate a remove transaction for it. that's not quite true since
1252 * we're only messing with one inode, not two but...
1255 tp
= libxfs_trans_alloc(mp
, XFS_TRANS_REMOVE
);
1257 nres
= XFS_REMOVE_SPACE_RES(mp
);
1258 error
= libxfs_trans_reserve(tp
, nres
, XFS_REMOVE_LOG_RES(mp
),
1259 0, XFS_TRANS_PERM_LOG_RES
,
1260 XFS_REMOVE_LOG_COUNT
);
1264 libxfs_trans_ijoin(tp
, ip
, 0);
1265 libxfs_trans_ihold(tp
, ip
);
1267 XFS_BMAP_INIT(&free_list
, &first_block
);
1269 error
= dir_bogus_removename(mp
, tp
, ip
, fname
,
1270 &first_block
, &free_list
, nres
, *hashval
, namelen
);
1274 "couldn't remove bogus entry \"%s\" in\n\tdirectory inode %llu, errno = %d\n",
1279 error
= libxfs_bmap_finish(&tp
, &free_list
, first_block
, &committed
);
1283 libxfs_trans_commit(tp
, XFS_TRANS_RELEASE_LOG_RES
|XFS_TRANS_SYNC
, 0);
1289 * process a leaf block, also checks for .. entry
1290 * and corrects it to match what we think .. should be
1293 lf_block_dir_entry_check(xfs_mount_t
*mp
,
1295 xfs_dir_leafblock_t
*leaf
,
1300 ino_tree_node_t
*current_irec
,
1301 int current_ino_offset
)
1303 xfs_dir_leaf_entry_t
*entry
;
1304 ino_tree_node_t
*irec
;
1307 xfs_dir_leaf_name_t
*namest
;
1312 char fname
[MAXNAMELEN
+ 1];
1314 entry
= &leaf
->entries
[0];
1319 * look at each entry. reference inode pointed to by each
1320 * entry in the incore inode tree.
1321 * if not a directory, set reached flag, increment link count
1322 * if a directory and reached, mark entry as to be deleted.
1323 * if a directory, check to see if recorded parent
1324 * matches current inode #,
1325 * if so, then set reached flag, increment link count
1326 * of current and child dir inodes, push the child
1327 * directory inode onto the directory stack.
1328 * if current inode != parent, then mark entry to be deleted.
1332 for (i
= 0; i
< INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
); entry
++, i
++) {
1334 * snag inode #, update link counts, and make sure
1335 * this isn't a loop if the child is a directory
1337 namest
= XFS_DIR_LEAF_NAMESTRUCT(leaf
, INT_GET(entry
->nameidx
, ARCH_CONVERT
));
1340 * skip bogus entries (leading '/'). they'll be deleted
1343 if (namest
->name
[0] == '/') {
1350 XFS_DIR_SF_GET_DIRINO_ARCH(&namest
->inumber
, &lino
, ARCH_CONVERT
);
1351 bcopy(namest
->name
, fname
, entry
->namelen
);
1352 fname
[entry
->namelen
] = '\0';
1354 ASSERT(lino
!= NULLFSINO
);
1357 * skip the '..' entry since it's checked when the
1358 * directory is reached by something else. if it never
1359 * gets reached, it'll be moved to the orphanage and we'll
1360 * take care of it then.
1362 if (entry
->namelen
== 2 && namest
->name
[0] == '.' &&
1363 namest
->name
[1] == '.') {
1366 ASSERT(no_modify
|| !verify_inum(mp
, lino
));
1369 * special case the . entry. we know there's only one
1370 * '.' and only '.' points to itself because bogus entries
1371 * got trashed in phase 3 if there were > 1.
1372 * bump up link count for '.' but don't set reached
1373 * until we're actually reached by another directory
1374 * '..' is already accounted for or will be taken care
1375 * of when directory is moved to orphanage.
1378 ASSERT(namest
->name
[0] == '.' && entry
->namelen
== 1);
1379 add_inode_ref(current_irec
, current_ino_offset
);
1385 * special case the "lost+found" entry if pointing
1386 * to where we think lost+found should be. if that's
1387 * the case, that's the one we created in phase 6.
1388 * just skip it. no need to process it and it's ..
1389 * link is already accounted for.
1392 if (lino
== orphanage_ino
&& strcmp(fname
, ORPHANAGE
) == 0)
1396 * skip entries with bogus inumbers if we're in no modify mode
1398 if (no_modify
&& verify_inum(mp
, lino
))
1402 * ok, now handle the rest of the cases besides '.' and '..'
1404 irec
= find_inode_rec(XFS_INO_TO_AGNO(mp
, lino
),
1405 XFS_INO_TO_AGINO(mp
, lino
));
1410 "entry \"%s\" in dir inode %llu points to non-existent inode, ",
1414 namest
->name
[0] = '/';
1416 do_warn("marking entry to be junked\n");
1418 do_warn("would junk entry\n");
1424 ino_offset
= XFS_INO_TO_AGINO(mp
, lino
) - irec
->ino_startnum
;
1427 * if it's a free inode, blow out the entry.
1428 * by now, any inode that we think is free
1431 if (is_inode_free(irec
, ino_offset
)) {
1433 * don't complain if this entry points to the old
1434 * and now-free lost+found inode
1436 if (verbose
|| no_modify
|| lino
!= old_orphanage_ino
)
1438 "entry \"%s\" in dir inode %llu points to free inode %llu",
1443 if (verbose
|| lino
!= old_orphanage_ino
)
1444 do_warn(", marking entry to be junked\n");
1448 namest
->name
[0] = '/';
1451 do_warn(", would junk entry\n");
1458 * check easy case first, regular inode, just bump
1459 * the link count and continue
1461 if (!inode_isadir(irec
, ino_offset
)) {
1462 add_inode_reached(irec
, ino_offset
);
1466 parent
= get_inode_parent(irec
, ino_offset
);
1467 ASSERT(parent
!= 0);
1470 * bump up the link counts in parent and child
1471 * directory but if the link doesn't agree with
1472 * the .. in the child, blow out the entry.
1473 * if the directory has already been reached,
1474 * blow away the entry also.
1476 if (is_inode_reached(irec
, ino_offset
)) {
1479 "entry \"%s\" in dir %llu points to an already connected dir inode %llu,\n",
1481 } else if (parent
== ino
) {
1482 add_inode_reached(irec
, ino_offset
);
1483 add_inode_ref(current_irec
, current_ino_offset
);
1485 if (!is_inode_refchecked(lino
, irec
, ino_offset
))
1486 push_dir(stack
, lino
);
1490 "entry \"%s\" in dir ino %llu not consistent with .. value (%llu) in ino %llu,\n",
1491 fname
, ino
, parent
, lino
);
1499 namest
->name
[0] = '/';
1501 if (verbose
|| lino
!= old_orphanage_ino
)
1502 do_warn("\twill clear entry \"%s\"\n",
1505 do_warn("\twould clear entry \"%s\"\n", fname
);
1510 *num_illegal
+= nbad
;
1514 * succeeds or dies, inode never gets dirtied since all changes
1515 * happen in file blocks. the inode size and other core info
1516 * is already correct, it's just the leaf entries that get altered.
1519 longform_dir_entry_check(xfs_mount_t
*mp
,
1525 ino_tree_node_t
*irec
,
1528 xfs_dir_leafblock_t
*leaf
;
1531 xfs_fsblock_t fblock
;
1537 xfs_bmbt_irec_t map
;
1541 fblock
= NULLFSBLOCK
;
1545 fsbno
= map_first_dblock_fsbno(mp
, ino
, ip
, &da_bno
);
1547 if (fsbno
== NULLDFSBNO
&& no_modify
) {
1548 do_warn("cannot map block 0 of directory inode %llu\n", ino
);
1553 ASSERT(fsbno
!= NULLDFSBNO
);
1556 bp
= libxfs_readbuf(mp
->m_dev
, XFS_FSB_TO_DADDR(mp
, fsbno
),
1557 XFS_FSB_TO_BB(mp
, 1), 0);
1561 "can't read block %u (fsbno %llu) for directory inode %llu\n",
1562 da_bno
, fsbno
, ino
);
1566 leaf
= (xfs_dir_leafblock_t
*)XFS_BUF_PTR(bp
);
1568 da_bno
= INT_GET(leaf
->hdr
.info
.forw
, ARCH_CONVERT
);
1570 if (INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
) != XFS_DIR_LEAF_MAGIC
) {
1573 "bad magic # (0x%x) for dir ino %llu leaf block (bno %u fsbno %llu)\n",
1574 INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
),
1575 ino
, da_bno
, fsbno
);
1579 * this block's bad but maybe the
1580 * forward pointer is good...
1588 lf_block_dir_entry_check(mp
, ino
, leaf
, &dirty
,
1589 num_illegal
, need_dot
, stack
,
1592 ASSERT(dirty
== 0 || dirty
&& !no_modify
);
1594 if (dirty
&& !no_modify
)
1595 libxfs_writebuf(bp
, 0);
1602 error
= libxfs_bmapi(NULL
, ip
, (xfs_fileoff_t
)da_bno
, 1,
1603 XFS_BMAPI_METADATA
, &fblock
, 0,
1605 if (error
|| nmap
!= 1) {
1608 "can't map leaf block %d in dir %llu, xfs_bmapi returns %d, nmap = %d\n",
1609 da_bno
, ino
, error
, nmap
);
1612 "can't map leaf block %d in dir %llu, xfs_bmapi returns %d, nmap = %d\n",
1613 da_bno
, ino
, error
, nmap
);
1617 if ((fsbno
= map
.br_startblock
) == HOLESTARTBLOCK
) {
1620 "block %d in %s ino %llu doesn't exist\n",
1621 da_bno
, ftype
, ino
);
1624 "block %d in %s ino %llu doesn't exist\n",
1625 da_bno
, ftype
, ino
);
1630 } while (da_bno
!= 0);
1634 * Kill a block in a version 2 inode.
1635 * Makes its own transaction.
1647 xfs_fsblock_t firstblock
;
1648 xfs_bmap_free_t flist
;
1652 tp
= libxfs_trans_alloc(mp
, 0);
1653 nres
= XFS_REMOVE_SPACE_RES(mp
);
1654 error
= libxfs_trans_reserve(tp
, nres
, XFS_REMOVE_LOG_RES(mp
), 0,
1655 XFS_TRANS_PERM_LOG_RES
, XFS_REMOVE_LOG_COUNT
);
1658 libxfs_trans_ijoin(tp
, ip
, 0);
1659 libxfs_trans_ihold(tp
, ip
);
1660 libxfs_da_bjoin(tp
, bp
);
1661 bzero(&args
, sizeof(args
));
1662 XFS_BMAP_INIT(&flist
, &firstblock
);
1665 args
.firstblock
= &firstblock
;
1666 args
.flist
= &flist
;
1667 args
.whichfork
= XFS_DATA_FORK
;
1668 if (da_bno
>= mp
->m_dirleafblk
&& da_bno
< mp
->m_dirfreeblk
)
1669 error
= libxfs_da_shrink_inode(&args
, da_bno
, bp
);
1671 error
= libxfs_dir2_shrink_inode(&args
,
1672 XFS_DIR2_DA_TO_DB(mp
, da_bno
), bp
);
1674 do_error("shrink_inode failed inode %llu block %u\n",
1676 libxfs_bmap_finish(&tp
, &flist
, firstblock
, &committed
);
1677 libxfs_trans_commit(tp
, 0, 0);
1681 * process a data block, also checks for .. entry
1682 * and corrects it to match what we think .. should be
1685 longform_dir2_entry_check_data(
1691 ino_tree_node_t
*current_irec
,
1692 int current_ino_offset
,
1694 dir_hash_tab_t
*hashtab
,
1695 freetab_t
**freetabp
,
1699 xfs_dir2_dataptr_t addr
;
1700 xfs_dir2_leaf_entry_t
*blp
;
1702 xfs_dir2_block_tail_t
*btp
;
1706 xfs_dir2_data_entry_t
*dep
;
1707 xfs_dir2_data_unused_t
*dup
;
1710 xfs_fsblock_t firstblock
;
1711 xfs_bmap_free_t flist
;
1712 char fname
[MAXNAMELEN
+ 1];
1716 ino_tree_node_t
*irec
;
1732 needscan
= needlog
= 0;
1733 freetab
= *freetabp
;
1735 btp
= XFS_DIR2_BLOCK_TAIL_P(mp
, d
);
1736 blp
= XFS_DIR2_BLOCK_LEAF_P_ARCH(btp
, ARCH_CONVERT
);
1737 endptr
= (char *)blp
;
1738 if (endptr
> (char *)btp
)
1739 endptr
= (char *)btp
;
1740 wantmagic
= XFS_DIR2_BLOCK_MAGIC
;
1742 endptr
= (char *)d
+ mp
->m_dirblksize
;
1743 wantmagic
= XFS_DIR2_DATA_MAGIC
;
1745 db
= XFS_DIR2_DA_TO_DB(mp
, da_bno
);
1746 if (freetab
->naents
<= db
) {
1747 struct freetab_ent e
;
1749 *freetabp
= freetab
= realloc(freetab
, FREETAB_SIZE(db
+ 1));
1752 "realloc failed in longform_dir2_entry_check_data (%u bytes)\n",
1753 FREETAB_SIZE(db
+ 1));
1758 for (i
= freetab
->naents
; i
< db
; i
++)
1759 freetab
->ents
[i
] = e
;
1760 freetab
->naents
= db
+ 1;
1762 if (freetab
->nents
< db
+ 1)
1763 freetab
->nents
= db
+ 1;
1764 while (ptr
< endptr
) {
1765 dup
= (xfs_dir2_data_unused_t
*)ptr
;
1766 if (INT_GET(dup
->freetag
, ARCH_CONVERT
) == XFS_DIR2_DATA_FREE_TAG
) {
1767 if (ptr
+ INT_GET(dup
->length
, ARCH_CONVERT
) > endptr
|| INT_GET(dup
->length
, ARCH_CONVERT
) == 0 ||
1768 (INT_GET(dup
->length
, ARCH_CONVERT
) & (XFS_DIR2_DATA_ALIGN
- 1)))
1770 if (INT_GET(*XFS_DIR2_DATA_UNUSED_TAG_P_ARCH(dup
, ARCH_CONVERT
), ARCH_CONVERT
) !=
1771 (char *)dup
- (char *)d
)
1773 ptr
+= INT_GET(dup
->length
, ARCH_CONVERT
);
1777 dep
= (xfs_dir2_data_entry_t
*)ptr
;
1778 if (ptr
+ XFS_DIR2_DATA_ENTSIZE(dep
->namelen
) > endptr
)
1780 if (INT_GET(*XFS_DIR2_DATA_ENTRY_TAG_P(dep
), ARCH_CONVERT
) != (char *)dep
- (char *)d
)
1782 ptr
+= XFS_DIR2_DATA_ENTSIZE(dep
->namelen
);
1784 if (ptr
!= endptr
) {
1785 do_warn("corrupt block %u in directory inode %llu: ",
1788 do_warn("junking block\n");
1789 dir2_kill_block(mp
, ip
, da_bno
, bp
);
1791 do_warn("would junk block\n");
1792 libxfs_da_brelse(NULL
, bp
);
1794 freetab
->ents
[db
].v
= NULLDATAOFF
;
1798 tp
= libxfs_trans_alloc(mp
, 0);
1799 error
= libxfs_trans_reserve(tp
, 0, XFS_REMOVE_LOG_RES(mp
), 0,
1800 XFS_TRANS_PERM_LOG_RES
, XFS_REMOVE_LOG_COUNT
);
1803 libxfs_trans_ijoin(tp
, ip
, 0);
1804 libxfs_trans_ihold(tp
, ip
);
1805 libxfs_da_bjoin(tp
, bp
);
1807 libxfs_da_bhold(tp
, bp
);
1808 XFS_BMAP_INIT(&flist
, &firstblock
);
1809 if (INT_GET(d
->hdr
.magic
, ARCH_CONVERT
) != wantmagic
) {
1810 do_warn("bad directory block magic # %#x for directory inode "
1812 INT_GET(d
->hdr
.magic
, ARCH_CONVERT
), ip
->i_ino
, da_bno
);
1814 do_warn("fixing magic # to %#x\n", wantmagic
);
1815 INT_SET(d
->hdr
.magic
, ARCH_CONVERT
, wantmagic
);
1818 do_warn("would fix magic # to %#x\n", wantmagic
);
1823 * look at each entry. reference inode pointed to by each
1824 * entry in the incore inode tree.
1825 * if not a directory, set reached flag, increment link count
1826 * if a directory and reached, mark entry as to be deleted.
1827 * if a directory, check to see if recorded parent
1828 * matches current inode #,
1829 * if so, then set reached flag, increment link count
1830 * of current and child dir inodes, push the child
1831 * directory inode onto the directory stack.
1832 * if current inode != parent, then mark entry to be deleted.
1834 while (ptr
< endptr
) {
1835 dup
= (xfs_dir2_data_unused_t
*)ptr
;
1836 if (INT_GET(dup
->freetag
, ARCH_CONVERT
) == XFS_DIR2_DATA_FREE_TAG
) {
1838 do_warn("directory inode %llu block %u has "
1839 "consecutive free entries: ",
1842 do_warn("joining together\n");
1843 len
= INT_GET(dup
->length
, ARCH_CONVERT
);
1844 libxfs_dir2_data_use_free(tp
, bp
, dup
,
1845 ptr
- (char *)d
, len
, &needlog
,
1847 libxfs_dir2_data_make_free(tp
, bp
,
1848 ptr
- (char *)d
, len
, &needlog
,
1851 do_warn("would join together\n");
1853 ptr
+= INT_GET(dup
->length
, ARCH_CONVERT
);
1857 addr
= XFS_DIR2_DB_OFF_TO_DATAPTR(mp
, db
, ptr
- (char *)d
);
1858 dep
= (xfs_dir2_data_entry_t
*)ptr
;
1859 ptr
+= XFS_DIR2_DATA_ENTSIZE(dep
->namelen
);
1861 dir_hash_add(hashtab
,
1862 libxfs_da_hashname((char *)dep
->name
, dep
->namelen
),
1863 addr
, dep
->name
[0] == '/');
1865 * skip bogus entries (leading '/'). they'll be deleted
1868 if (dep
->name
[0] == '/') {
1873 bcopy(dep
->name
, fname
, dep
->namelen
);
1874 fname
[dep
->namelen
] = '\0';
1875 ASSERT(INT_GET(dep
->inumber
, ARCH_CONVERT
) != NULLFSINO
);
1877 * skip the '..' entry since it's checked when the
1878 * directory is reached by something else. if it never
1879 * gets reached, it'll be moved to the orphanage and we'll
1880 * take care of it then.
1882 if (dep
->namelen
== 2 && dep
->name
[0] == '.' &&
1883 dep
->name
[1] == '.')
1885 ASSERT(no_modify
|| !verify_inum(mp
, INT_GET(dep
->inumber
, ARCH_CONVERT
)));
1887 * special case the . entry. we know there's only one
1888 * '.' and only '.' points to itself because bogus entries
1889 * got trashed in phase 3 if there were > 1.
1890 * bump up link count for '.' but don't set reached
1891 * until we're actually reached by another directory
1892 * '..' is already accounted for or will be taken care
1893 * of when directory is moved to orphanage.
1895 if (ip
->i_ino
== INT_GET(dep
->inumber
, ARCH_CONVERT
)) {
1896 ASSERT(dep
->name
[0] == '.' && dep
->namelen
== 1);
1897 add_inode_ref(current_irec
, current_ino_offset
);
1902 * special case the "lost+found" entry if pointing
1903 * to where we think lost+found should be. if that's
1904 * the case, that's the one we created in phase 6.
1905 * just skip it. no need to process it and it's ..
1906 * link is already accounted for.
1908 if (INT_GET(dep
->inumber
, ARCH_CONVERT
) == orphanage_ino
&&
1909 strcmp(fname
, ORPHANAGE
) == 0)
1912 * skip entries with bogus inumbers if we're in no modify mode
1914 if (no_modify
&& verify_inum(mp
, INT_GET(dep
->inumber
, ARCH_CONVERT
)))
1917 * ok, now handle the rest of the cases besides '.' and '..'
1919 irec
= find_inode_rec(XFS_INO_TO_AGNO(mp
, INT_GET(dep
->inumber
, ARCH_CONVERT
)),
1920 XFS_INO_TO_AGINO(mp
, INT_GET(dep
->inumber
, ARCH_CONVERT
)));
1923 do_warn("entry \"%s\" in directory inode %llu points "
1924 "to non-existent inode, ",
1928 libxfs_dir2_data_log_entry(tp
, bp
, dep
);
1929 do_warn("marking entry to be junked\n");
1931 do_warn("would junk entry\n");
1936 XFS_INO_TO_AGINO(mp
, INT_GET(dep
->inumber
, ARCH_CONVERT
)) - irec
->ino_startnum
;
1938 * if it's a free inode, blow out the entry.
1939 * by now, any inode that we think is free
1942 if (is_inode_free(irec
, ino_offset
)) {
1944 * don't complain if this entry points to the old
1945 * and now-free lost+found inode
1947 if (verbose
|| no_modify
||
1948 INT_GET(dep
->inumber
, ARCH_CONVERT
) != old_orphanage_ino
)
1949 do_warn("entry \"%s\" in directory inode %llu "
1950 "points to free inode %llu",
1951 fname
, ip
->i_ino
, INT_GET(dep
->inumber
, ARCH_CONVERT
));
1955 INT_GET(dep
->inumber
, ARCH_CONVERT
) != old_orphanage_ino
)
1956 do_warn(", marking entry to be "
1961 libxfs_dir2_data_log_entry(tp
, bp
, dep
);
1963 do_warn(", would junk entry\n");
1968 * check easy case first, regular inode, just bump
1969 * the link count and continue
1971 if (!inode_isadir(irec
, ino_offset
)) {
1972 add_inode_reached(irec
, ino_offset
);
1975 parent
= get_inode_parent(irec
, ino_offset
);
1976 ASSERT(parent
!= 0);
1978 * bump up the link counts in parent and child
1979 * directory but if the link doesn't agree with
1980 * the .. in the child, blow out the entry.
1981 * if the directory has already been reached,
1982 * blow away the entry also.
1984 if (is_inode_reached(irec
, ino_offset
)) {
1986 do_warn("entry \"%s\" in dir %llu points to an already "
1987 "connected directory inode %llu,\n", fname
,
1988 ip
->i_ino
, INT_GET(dep
->inumber
, ARCH_CONVERT
));
1989 } else if (parent
== ip
->i_ino
) {
1990 add_inode_reached(irec
, ino_offset
);
1991 add_inode_ref(current_irec
, current_ino_offset
);
1992 if (!is_inode_refchecked(INT_GET(dep
->inumber
, ARCH_CONVERT
), irec
,
1994 push_dir(stack
, INT_GET(dep
->inumber
, ARCH_CONVERT
));
1997 do_warn("entry \"%s\" in directory inode %llu not "
1998 "consistent with .. value (%llu) in ino "
2000 fname
, ip
->i_ino
, parent
, INT_GET(dep
->inumber
, ARCH_CONVERT
));
2007 libxfs_dir2_data_log_entry(tp
, bp
, dep
);
2009 INT_GET(dep
->inumber
, ARCH_CONVERT
) != old_orphanage_ino
)
2010 do_warn("\twill clear entry \"%s\"\n",
2013 do_warn("\twould clear entry \"%s\"\n", fname
);
2017 *num_illegal
+= nbad
;
2019 libxfs_dir2_data_freescan(mp
, d
, &needlog
, NULL
);
2021 libxfs_dir2_data_log_header(tp
, bp
);
2022 libxfs_bmap_finish(&tp
, &flist
, firstblock
, &committed
);
2023 libxfs_trans_commit(tp
, 0, 0);
2024 freetab
->ents
[db
].v
= INT_GET(d
->hdr
.bestfree
[0].length
, ARCH_CONVERT
);
2025 freetab
->ents
[db
].s
= 0;
2029 * Check contents of leaf-form block.
2032 longform_dir2_check_leaf(
2035 dir_hash_tab_t
*hashtab
,
2039 xfs_dir2_data_off_t
*bestsp
;
2043 xfs_dir2_leaf_t
*leaf
;
2044 xfs_dir2_leaf_tail_t
*ltp
;
2047 da_bno
= mp
->m_dirleafblk
;
2048 if (libxfs_da_read_bufr(NULL
, ip
, da_bno
, -1, &bp
, XFS_DATA_FORK
)) {
2049 do_error("can't read block %u for directory inode %llu\n",
2054 ltp
= XFS_DIR2_LEAF_TAIL_P(mp
, leaf
);
2055 bestsp
= XFS_DIR2_LEAF_BESTS_P_ARCH(ltp
, ARCH_CONVERT
);
2056 if (INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
) != XFS_DIR2_LEAF1_MAGIC
||
2057 INT_GET(leaf
->hdr
.info
.forw
, ARCH_CONVERT
) || INT_GET(leaf
->hdr
.info
.back
, ARCH_CONVERT
) ||
2058 INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
) < INT_GET(leaf
->hdr
.stale
, ARCH_CONVERT
) ||
2059 INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
) > XFS_DIR2_MAX_LEAF_ENTS(mp
) ||
2060 (char *)&leaf
->ents
[INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
)] > (char *)bestsp
) {
2061 do_warn("leaf block %u for directory inode %llu bad header\n",
2063 libxfs_da_brelse(NULL
, bp
);
2066 seeval
= dir_hash_see_all(hashtab
, leaf
->ents
, INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
),
2067 INT_GET(leaf
->hdr
.stale
, ARCH_CONVERT
));
2068 if (dir_hash_check(hashtab
, ip
, seeval
)) {
2069 libxfs_da_brelse(NULL
, bp
);
2072 badtail
= freetab
->nents
!= INT_GET(ltp
->bestcount
, ARCH_CONVERT
);
2073 for (i
= 0; !badtail
&& i
< INT_GET(ltp
->bestcount
, ARCH_CONVERT
); i
++) {
2074 freetab
->ents
[i
].s
= 1;
2075 badtail
= freetab
->ents
[i
].v
!= INT_GET(bestsp
[i
], ARCH_CONVERT
);
2078 do_warn("leaf block %u for directory inode %llu bad tail\n",
2080 libxfs_da_brelse(NULL
, bp
);
2083 libxfs_da_brelse(NULL
, bp
);
2088 * Check contents of the node blocks (leaves)
2089 * Looks for matching hash values for the data entries.
2092 longform_dir2_check_node(
2095 dir_hash_tab_t
*hashtab
,
2101 xfs_dir2_free_t
*free
;
2103 xfs_dir2_leaf_t
*leaf
;
2104 xfs_fileoff_t next_da_bno
;
2108 for (da_bno
= mp
->m_dirleafblk
, next_da_bno
= 0;
2109 next_da_bno
!= NULLFILEOFF
&& da_bno
< mp
->m_dirfreeblk
;
2110 da_bno
= (xfs_dablk_t
)next_da_bno
) {
2111 next_da_bno
= da_bno
+ mp
->m_dirblkfsbs
- 1;
2112 if (libxfs_bmap_next_offset(NULL
, ip
, &next_da_bno
, XFS_DATA_FORK
))
2114 if (libxfs_da_read_bufr(NULL
, ip
, da_bno
, -1, &bp
,
2116 do_error("can't read block %u for directory inode "
2122 if (INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
) != XFS_DIR2_LEAFN_MAGIC
) {
2123 if (INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
) == XFS_DA_NODE_MAGIC
) {
2124 libxfs_da_brelse(NULL
, bp
);
2127 do_warn("unknown magic number %#x for block %u in "
2128 "directory inode %llu\n",
2129 INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
), da_bno
, ip
->i_ino
);
2130 libxfs_da_brelse(NULL
, bp
);
2133 if (INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
) < INT_GET(leaf
->hdr
.stale
, ARCH_CONVERT
) ||
2134 INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
) > XFS_DIR2_MAX_LEAF_ENTS(mp
)) {
2135 do_warn("leaf block %u for directory inode %llu bad "
2138 libxfs_da_brelse(NULL
, bp
);
2141 seeval
= dir_hash_see_all(hashtab
, leaf
->ents
, INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
),
2142 INT_GET(leaf
->hdr
.stale
, ARCH_CONVERT
));
2143 libxfs_da_brelse(NULL
, bp
);
2144 if (seeval
!= DIR_HASH_CK_OK
)
2147 if (dir_hash_check(hashtab
, ip
, seeval
))
2149 for (da_bno
= mp
->m_dirfreeblk
, next_da_bno
= 0;
2150 next_da_bno
!= NULLFILEOFF
;
2151 da_bno
= (xfs_dablk_t
)next_da_bno
) {
2152 next_da_bno
= da_bno
+ mp
->m_dirblkfsbs
- 1;
2153 if (libxfs_bmap_next_offset(NULL
, ip
, &next_da_bno
, XFS_DATA_FORK
))
2155 if (libxfs_da_read_bufr(NULL
, ip
, da_bno
, -1, &bp
,
2157 do_error("can't read block %u for directory inode "
2163 fdb
= XFS_DIR2_DA_TO_DB(mp
, da_bno
);
2164 if (INT_GET(free
->hdr
.magic
, ARCH_CONVERT
) != XFS_DIR2_FREE_MAGIC
||
2165 INT_GET(free
->hdr
.firstdb
, ARCH_CONVERT
) !=
2166 (fdb
- XFS_DIR2_FREE_FIRSTDB(mp
)) *
2167 XFS_DIR2_MAX_FREE_BESTS(mp
) ||
2168 INT_GET(free
->hdr
.nvalid
, ARCH_CONVERT
) < INT_GET(free
->hdr
.nused
, ARCH_CONVERT
)) {
2169 do_warn("free block %u for directory inode %llu bad "
2172 libxfs_da_brelse(NULL
, bp
);
2175 for (i
= used
= 0; i
< INT_GET(free
->hdr
.nvalid
, ARCH_CONVERT
); i
++) {
2176 if (i
+ INT_GET(free
->hdr
.firstdb
, ARCH_CONVERT
) >= freetab
->nents
||
2177 freetab
->ents
[i
+ INT_GET(free
->hdr
.firstdb
, ARCH_CONVERT
)].v
!=
2178 INT_GET(free
->bests
[i
], ARCH_CONVERT
)) {
2179 do_warn("free block %u entry %i for directory "
2181 da_bno
, i
, ip
->i_ino
);
2182 libxfs_da_brelse(NULL
, bp
);
2185 used
+= INT_GET(free
->bests
[i
], ARCH_CONVERT
) != NULLDATAOFF
;
2186 freetab
->ents
[i
+ INT_GET(free
->hdr
.firstdb
, ARCH_CONVERT
)].s
= 1;
2188 if (used
!= INT_GET(free
->hdr
.nused
, ARCH_CONVERT
)) {
2189 do_warn("free block %u for directory inode %llu bad "
2192 libxfs_da_brelse(NULL
, bp
);
2195 libxfs_da_brelse(NULL
, bp
);
2197 for (i
= 0; i
< freetab
->nents
; i
++) {
2198 if (freetab
->ents
[i
].s
== 0) {
2199 do_warn("missing freetab entry %u for directory inode "
2209 * Rebuild a directory: set up.
2210 * Turn it into a node-format directory with no contents in the
2211 * upper area. Also has correct freespace blocks.
2214 longform_dir2_rebuild_setup(
2222 xfs_dir2_data_t
*data
;
2227 xfs_fsblock_t firstblock
;
2228 xfs_bmap_free_t flist
;
2229 xfs_dir2_free_t
*free
;
2234 xfs_dir2_leaf_t
*leaf
;
2238 tp
= libxfs_trans_alloc(mp
, 0);
2239 nres
= XFS_DAENTER_SPACE_RES(mp
, XFS_DATA_FORK
);
2240 error
= libxfs_trans_reserve(tp
,
2241 nres
, XFS_CREATE_LOG_RES(mp
), 0, XFS_TRANS_PERM_LOG_RES
,
2242 XFS_CREATE_LOG_COUNT
);
2245 libxfs_trans_ijoin(tp
, ip
, 0);
2246 libxfs_trans_ihold(tp
, ip
);
2247 XFS_BMAP_INIT(&flist
, &firstblock
);
2248 if (libxfs_da_read_buf(tp
, ip
, mp
->m_dirdatablk
, -2, &dbp
,
2250 do_error("can't read block %u for directory inode %llu\n",
2251 mp
->m_dirdatablk
, ino
);
2254 if (dbp
&& (data
= dbp
->data
)->hdr
.magic
== XFS_DIR2_BLOCK_MAGIC
) {
2255 xfs_dir2_block_t
*block
;
2256 xfs_dir2_leaf_entry_t
*blp
;
2257 xfs_dir2_block_tail_t
*btp
;
2261 INT_SET(data
->hdr
.magic
, ARCH_CONVERT
, XFS_DIR2_DATA_MAGIC
);
2262 block
= (xfs_dir2_block_t
*)data
;
2263 btp
= XFS_DIR2_BLOCK_TAIL_P(mp
, block
);
2264 blp
= XFS_DIR2_BLOCK_LEAF_P_ARCH(btp
, ARCH_CONVERT
);
2265 needlog
= needscan
= 0;
2266 libxfs_dir2_data_make_free(tp
, dbp
, (char *)blp
- (char *)block
,
2267 (char *)block
+ mp
->m_dirblksize
- (char *)blp
,
2268 &needlog
, &needscan
);
2270 libxfs_dir2_data_freescan(mp
, data
, &needlog
, NULL
);
2271 libxfs_da_log_buf(tp
, dbp
, 0, mp
->m_dirblksize
- 1);
2273 bzero(&args
, sizeof(args
));
2276 args
.whichfork
= XFS_DATA_FORK
;
2277 args
.firstblock
= &firstblock
;
2278 args
.flist
= &flist
;
2280 if ((error
= libxfs_da_grow_inode(&args
, &lblkno
)) ||
2281 (error
= libxfs_da_get_buf(tp
, ip
, lblkno
, -1, &lbp
, XFS_DATA_FORK
))) {
2282 do_error("can't add btree block to directory inode %llu\n",
2287 bzero(leaf
, mp
->m_dirblksize
);
2288 INT_SET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
, XFS_DIR2_LEAFN_MAGIC
);
2289 libxfs_da_log_buf(tp
, lbp
, 0, mp
->m_dirblksize
- 1);
2290 libxfs_bmap_finish(&tp
, &flist
, firstblock
, &committed
);
2291 libxfs_trans_commit(tp
, 0, 0);
2293 for (i
= 0; i
< freetab
->nents
; i
+= XFS_DIR2_MAX_FREE_BESTS(mp
)) {
2294 tp
= libxfs_trans_alloc(mp
, 0);
2295 nres
= XFS_DAENTER_SPACE_RES(mp
, XFS_DATA_FORK
);
2296 error
= libxfs_trans_reserve(tp
,
2297 nres
, XFS_CREATE_LOG_RES(mp
), 0, XFS_TRANS_PERM_LOG_RES
,
2298 XFS_CREATE_LOG_COUNT
);
2301 libxfs_trans_ijoin(tp
, ip
, 0);
2302 libxfs_trans_ihold(tp
, ip
);
2303 XFS_BMAP_INIT(&flist
, &firstblock
);
2304 bzero(&args
, sizeof(args
));
2307 args
.whichfork
= XFS_DATA_FORK
;
2308 args
.firstblock
= &firstblock
;
2309 args
.flist
= &flist
;
2311 if ((error
= libxfs_dir2_grow_inode(&args
, XFS_DIR2_FREE_SPACE
,
2313 (error
= libxfs_da_get_buf(tp
, ip
, XFS_DIR2_DB_TO_DA(mp
, fbno
),
2314 -1, &fbp
, XFS_DATA_FORK
))) {
2315 do_error("can't add free block to directory inode "
2321 bzero(free
, mp
->m_dirblksize
);
2322 INT_SET(free
->hdr
.magic
, ARCH_CONVERT
, XFS_DIR2_FREE_MAGIC
);
2323 INT_SET(free
->hdr
.firstdb
, ARCH_CONVERT
, i
);
2324 INT_SET(free
->hdr
.nvalid
, ARCH_CONVERT
, XFS_DIR2_MAX_FREE_BESTS(mp
));
2325 if (i
+ INT_GET(free
->hdr
.nvalid
, ARCH_CONVERT
) > freetab
->nents
)
2326 INT_SET(free
->hdr
.nvalid
, ARCH_CONVERT
, freetab
->nents
- i
);
2327 for (j
= 0; j
< INT_GET(free
->hdr
.nvalid
, ARCH_CONVERT
); j
++) {
2328 INT_SET(free
->bests
[j
], ARCH_CONVERT
, freetab
->ents
[i
+ j
].v
);
2329 if (INT_GET(free
->bests
[j
], ARCH_CONVERT
) != NULLDATAOFF
)
2330 INT_MOD(free
->hdr
.nused
, ARCH_CONVERT
, +1);
2332 libxfs_da_log_buf(tp
, fbp
, 0, mp
->m_dirblksize
- 1);
2333 libxfs_bmap_finish(&tp
, &flist
, firstblock
, &committed
);
2334 libxfs_trans_commit(tp
, 0, 0);
2339 * Rebuild the entries from a single data block.
2342 longform_dir2_rebuild_data(
2349 xfs_dir2_block_tail_t
*btp
;
2351 xfs_dir2_data_t
*data
;
2353 xfs_dir2_data_entry_t
*dep
;
2354 xfs_dir2_data_unused_t
*dup
;
2357 xfs_dir2_free_t
*fblock
;
2361 xfs_fsblock_t firstblock
;
2362 xfs_bmap_free_t flist
;
2369 if (libxfs_da_read_buf(NULL
, ip
, da_bno
, da_bno
== 0 ? -2 : -1, &bp
,
2371 do_error("can't read block %u for directory inode %llu\n",
2375 if (da_bno
== 0 && bp
== NULL
)
2377 * The block was punched out.
2381 dbno
= XFS_DIR2_DA_TO_DB(mp
, da_bno
);
2382 fdb
= XFS_DIR2_DB_TO_FDB(mp
, dbno
);
2383 if (libxfs_da_read_buf(NULL
, ip
, XFS_DIR2_DB_TO_DA(mp
, fdb
), -1, &fbp
,
2385 do_error("can't read block %u for directory inode %llu\n",
2386 XFS_DIR2_DB_TO_DA(mp
, fdb
), ino
);
2389 data
= malloc(mp
->m_dirblksize
);
2392 "malloc failed in longform_dir2_rebuild_data (%u bytes)\n",
2396 bcopy(bp
->data
, data
, mp
->m_dirblksize
);
2397 ptr
= (char *)data
->u
;
2398 if (INT_GET(data
->hdr
.magic
, ARCH_CONVERT
) == XFS_DIR2_BLOCK_MAGIC
) {
2399 btp
= XFS_DIR2_BLOCK_TAIL_P(mp
, (xfs_dir2_block_t
*)data
);
2400 endptr
= (char *)XFS_DIR2_BLOCK_LEAF_P_ARCH(btp
, ARCH_CONVERT
);
2402 endptr
= (char *)data
+ mp
->m_dirblksize
;
2404 fi
= XFS_DIR2_DB_TO_FDINDEX(mp
, dbno
);
2405 tp
= libxfs_trans_alloc(mp
, 0);
2406 error
= libxfs_trans_reserve(tp
, 0, XFS_CREATE_LOG_RES(mp
), 0,
2407 XFS_TRANS_PERM_LOG_RES
, XFS_CREATE_LOG_COUNT
);
2410 libxfs_trans_ijoin(tp
, ip
, 0);
2411 libxfs_trans_ihold(tp
, ip
);
2412 libxfs_da_bjoin(tp
, bp
);
2413 libxfs_da_bhold(tp
, bp
);
2414 libxfs_da_bjoin(tp
, fbp
);
2415 libxfs_da_bhold(tp
, fbp
);
2416 XFS_BMAP_INIT(&flist
, &firstblock
);
2417 needlog
= needscan
= 0;
2418 bzero(((xfs_dir2_data_t
*)(bp
->data
))->hdr
.bestfree
,
2419 sizeof(data
->hdr
.bestfree
));
2420 libxfs_dir2_data_make_free(tp
, bp
, (xfs_dir2_data_aoff_t
)sizeof(data
->hdr
),
2421 mp
->m_dirblksize
- sizeof(data
->hdr
), &needlog
, &needscan
);
2422 ASSERT(needscan
== 0);
2423 libxfs_dir2_data_log_header(tp
, bp
);
2424 INT_SET(fblock
->bests
[fi
], ARCH_CONVERT
,
2425 INT_GET(((xfs_dir2_data_t
*)(bp
->data
))->hdr
.bestfree
[0].length
, ARCH_CONVERT
));
2426 libxfs_dir2_free_log_bests(tp
, fbp
, fi
, fi
);
2427 libxfs_bmap_finish(&tp
, &flist
, firstblock
, &committed
);
2428 libxfs_trans_commit(tp
, 0, 0);
2430 while (ptr
< endptr
) {
2431 dup
= (xfs_dir2_data_unused_t
*)ptr
;
2432 if (INT_GET(dup
->freetag
, ARCH_CONVERT
) == XFS_DIR2_DATA_FREE_TAG
) {
2433 ptr
+= INT_GET(dup
->length
, ARCH_CONVERT
);
2436 dep
= (xfs_dir2_data_entry_t
*)ptr
;
2437 ptr
+= XFS_DIR2_DATA_ENTSIZE(dep
->namelen
);
2438 if (dep
->name
[0] == '/')
2440 tp
= libxfs_trans_alloc(mp
, 0);
2441 nres
= XFS_CREATE_SPACE_RES(mp
, dep
->namelen
);
2442 error
= libxfs_trans_reserve(tp
, nres
, XFS_CREATE_LOG_RES(mp
), 0,
2443 XFS_TRANS_PERM_LOG_RES
, XFS_CREATE_LOG_COUNT
);
2446 libxfs_trans_ijoin(tp
, ip
, 0);
2447 libxfs_trans_ihold(tp
, ip
);
2448 libxfs_da_bjoin(tp
, bp
);
2449 libxfs_da_bhold(tp
, bp
);
2450 libxfs_da_bjoin(tp
, fbp
);
2451 libxfs_da_bhold(tp
, fbp
);
2452 XFS_BMAP_INIT(&flist
, &firstblock
);
2453 error
= dir_createname(mp
, tp
, ip
, (char *)dep
->name
,
2454 dep
->namelen
, INT_GET(dep
->inumber
, ARCH_CONVERT
),
2455 &firstblock
, &flist
, nres
);
2457 libxfs_bmap_finish(&tp
, &flist
, firstblock
, &committed
);
2458 libxfs_trans_commit(tp
, 0, 0);
2460 libxfs_da_brelse(NULL
, bp
);
2461 libxfs_da_brelse(NULL
, fbp
);
2466 * Finish the rebuild of a directory.
2467 * Stuff / in and then remove it, this forces the directory to end
2468 * up in the right format.
2471 longform_dir2_rebuild_finish(
2478 xfs_fsblock_t firstblock
;
2479 xfs_bmap_free_t flist
;
2483 tp
= libxfs_trans_alloc(mp
, 0);
2484 nres
= XFS_CREATE_SPACE_RES(mp
, 1);
2485 error
= libxfs_trans_reserve(tp
, nres
, XFS_CREATE_LOG_RES(mp
), 0,
2486 XFS_TRANS_PERM_LOG_RES
, XFS_CREATE_LOG_COUNT
);
2489 libxfs_trans_ijoin(tp
, ip
, 0);
2490 libxfs_trans_ihold(tp
, ip
);
2491 XFS_BMAP_INIT(&flist
, &firstblock
);
2492 error
= dir_createname(mp
, tp
, ip
, "/", 1, ino
,
2493 &firstblock
, &flist
, nres
);
2495 libxfs_bmap_finish(&tp
, &flist
, firstblock
, &committed
);
2496 libxfs_trans_commit(tp
, 0, 0);
2498 /* could kill trailing empty data blocks here */
2500 tp
= libxfs_trans_alloc(mp
, 0);
2501 nres
= XFS_REMOVE_SPACE_RES(mp
);
2502 error
= libxfs_trans_reserve(tp
, nres
, XFS_REMOVE_LOG_RES(mp
), 0,
2503 XFS_TRANS_PERM_LOG_RES
, XFS_REMOVE_LOG_COUNT
);
2506 libxfs_trans_ijoin(tp
, ip
, 0);
2507 libxfs_trans_ihold(tp
, ip
);
2508 XFS_BMAP_INIT(&flist
, &firstblock
);
2509 error
= dir_removename(mp
, tp
, ip
, "/", 1, ino
,
2510 &firstblock
, &flist
, nres
);
2512 libxfs_bmap_finish(&tp
, &flist
, firstblock
, &committed
);
2513 libxfs_trans_commit(tp
, 0, 0);
2517 * Rebuild a directory.
2518 * Remove all the non-data blocks.
2519 * Re-initialize to (empty) node form.
2520 * Loop over the data blocks reinserting each entry.
2521 * Force the directory into the right format.
2524 longform_dir2_rebuild(
2534 xfs_fileoff_t next_da_bno
;
2536 do_warn("rebuilding directory inode %llu\n", ino
);
2537 for (da_bno
= mp
->m_dirleafblk
, next_da_bno
= isblock
? NULLFILEOFF
: 0;
2538 next_da_bno
!= NULLFILEOFF
;
2539 da_bno
= (xfs_dablk_t
)next_da_bno
) {
2540 next_da_bno
= da_bno
+ mp
->m_dirblkfsbs
- 1;
2541 if (libxfs_bmap_next_offset(NULL
, ip
, &next_da_bno
, XFS_DATA_FORK
))
2543 if (libxfs_da_get_buf(NULL
, ip
, da_bno
, -1, &bp
, XFS_DATA_FORK
)) {
2544 do_error("can't get block %u for directory inode "
2549 dir2_kill_block(mp
, ip
, da_bno
, bp
);
2551 longform_dir2_rebuild_setup(mp
, ino
, ip
, freetab
);
2552 for (da_bno
= mp
->m_dirdatablk
, next_da_bno
= 0;
2553 da_bno
< mp
->m_dirleafblk
&& next_da_bno
!= NULLFILEOFF
;
2554 da_bno
= (xfs_dablk_t
)next_da_bno
) {
2555 next_da_bno
= da_bno
+ mp
->m_dirblkfsbs
- 1;
2556 if (libxfs_bmap_next_offset(NULL
, ip
, &next_da_bno
, XFS_DATA_FORK
))
2558 longform_dir2_rebuild_data(mp
, ino
, ip
, da_bno
);
2560 longform_dir2_rebuild_finish(mp
, ino
, ip
);
2565 * succeeds or dies, inode never gets dirtied since all changes
2566 * happen in file blocks. the inode size and other core info
2567 * is already correct, it's just the leaf entries that get altered.
2568 * XXX above comment is wrong for v2 - need to see why it matters
2571 longform_dir2_entry_check(xfs_mount_t
*mp
,
2577 ino_tree_node_t
*irec
,
2580 xfs_dir2_block_t
*block
;
2581 xfs_dir2_leaf_entry_t
*blp
;
2583 xfs_dir2_block_tail_t
*btp
;
2586 dir_hash_tab_t
*hashtab
;
2590 xfs_fileoff_t next_da_bno
;
2595 freetab
= malloc(FREETAB_SIZE(ip
->i_d
.di_size
/ mp
->m_dirblksize
));
2598 "malloc failed in longform_dir2_entry_check (%u bytes)\n",
2599 FREETAB_SIZE(ip
->i_d
.di_size
/ mp
->m_dirblksize
));
2602 freetab
->naents
= ip
->i_d
.di_size
/ mp
->m_dirblksize
;
2604 for (i
= 0; i
< freetab
->naents
; i
++) {
2605 freetab
->ents
[i
].v
= NULLDATAOFF
;
2606 freetab
->ents
[i
].s
= 0;
2608 libxfs_dir2_isblock(NULL
, ip
, &isblock
);
2609 libxfs_dir2_isleaf(NULL
, ip
, &isleaf
);
2610 hashtab
= dir_hash_init(ip
->i_d
.di_size
);
2611 for (da_bno
= 0, next_da_bno
= 0;
2612 next_da_bno
!= NULLFILEOFF
&& da_bno
< mp
->m_dirleafblk
;
2613 da_bno
= (xfs_dablk_t
)next_da_bno
) {
2614 next_da_bno
= da_bno
+ mp
->m_dirblkfsbs
- 1;
2615 if (libxfs_bmap_next_offset(NULL
, ip
, &next_da_bno
, XFS_DATA_FORK
))
2617 if (libxfs_da_read_bufr(NULL
, ip
, da_bno
, -1, &bp
,
2619 do_error("can't read block %u for directory inode "
2624 longform_dir2_entry_check_data(mp
, ip
, num_illegal
, need_dot
,
2625 stack
, irec
, ino_offset
, &bp
, hashtab
, &freetab
, da_bno
,
2627 /* it releases the buffer unless isblock is set */
2629 fixit
= (*num_illegal
!= 0) || dir2_is_badino(ino
);
2633 btp
= XFS_DIR2_BLOCK_TAIL_P(mp
, block
);
2634 blp
= XFS_DIR2_BLOCK_LEAF_P_ARCH(btp
, ARCH_CONVERT
);
2635 seeval
= dir_hash_see_all(hashtab
, blp
, INT_GET(btp
->count
, ARCH_CONVERT
), INT_GET(btp
->stale
, ARCH_CONVERT
));
2636 if (dir_hash_check(hashtab
, ip
, seeval
))
2638 libxfs_da_brelse(NULL
, bp
);
2639 } else if (isleaf
) {
2640 fixit
|= longform_dir2_check_leaf(mp
, ip
, hashtab
, freetab
);
2642 fixit
|= longform_dir2_check_node(mp
, ip
, hashtab
, freetab
);
2644 dir_hash_done(hashtab
);
2645 if (!no_modify
&& fixit
)
2646 longform_dir2_rebuild(mp
, ino
, ip
, num_illegal
, freetab
,
2652 * shortform directory processing routines -- entry verification and
2653 * bad entry deletion (pruning).
2656 shortform_dir_entry_check(xfs_mount_t
*mp
,
2661 ino_tree_node_t
*current_irec
,
2662 int current_ino_offset
)
2666 xfs_dir_shortform_t
*sf
;
2667 xfs_dir_sf_entry_t
*sf_entry
, *next_sfe
, *tmp_sfe
;
2669 ino_tree_node_t
*irec
;
2679 char fname
[MAXNAMELEN
+ 1];
2682 sf
= (xfs_dir_shortform_t
*) ifp
->if_u1
.if_data
;
2686 max_size
= ifp
->if_bytes
;
2687 ASSERT(ip
->i_d
.di_size
<= ifp
->if_bytes
);
2690 * no '.' entry in shortform dirs, just bump up ref count by 1
2691 * '..' was already (or will be) accounted for and checked when
2692 * the directory is reached or will be taken care of when the
2693 * directory is moved to orphanage.
2695 add_inode_ref(current_irec
, current_ino_offset
);
2698 * now run through entries, stop at first bad entry, don't need
2699 * to skip over '..' since that's encoded in its own field and
2700 * no need to worry about '.' since it doesn't exist.
2702 sf_entry
= next_sfe
= &sf
->list
[0];
2705 do_warn("shortform dir inode %llu has null data entries \n", ino
);
2709 for (i
= 0; i
< INT_GET(sf
->hdr
.count
, ARCH_CONVERT
) && max_size
>
2710 (__psint_t
)next_sfe
- (__psint_t
)sf
;
2711 sf_entry
= next_sfe
, i
++) {
2716 XFS_DIR_SF_GET_DIRINO_ARCH(&sf_entry
->inumber
, &lino
, ARCH_CONVERT
);
2718 namelen
= sf_entry
->namelen
;
2720 ASSERT(no_modify
|| namelen
> 0);
2722 if (no_modify
&& namelen
== 0) {
2724 * if we're really lucky, this is
2725 * the last entry in which case we
2726 * can use the dir size to set the
2727 * namelen value. otherwise, forget
2728 * it because we're not going to be
2729 * able to find the next entry.
2733 if (i
== INT_GET(sf
->hdr
.count
, ARCH_CONVERT
) - 1) {
2734 namelen
= ip
->i_d
.di_size
-
2735 ((__psint_t
) &sf_entry
->name
[0] -
2739 * don't process the rest of the directory,
2740 * break out of processing looop
2744 } else if (no_modify
&& (__psint_t
) sf_entry
- (__psint_t
) sf
+
2745 + XFS_DIR_SF_ENTSIZE_BYENTRY(sf_entry
)
2746 > ip
->i_d
.di_size
) {
2749 if (i
== INT_GET(sf
->hdr
.count
, ARCH_CONVERT
) - 1) {
2750 namelen
= ip
->i_d
.di_size
-
2751 ((__psint_t
) &sf_entry
->name
[0] -
2755 * don't process the rest of the directory,
2756 * break out of processing looop
2762 bcopy(sf_entry
->name
, fname
, sf_entry
->namelen
);
2763 fname
[sf_entry
->namelen
] = '\0';
2765 ASSERT(no_modify
|| lino
!= NULLFSINO
);
2766 ASSERT(no_modify
|| !verify_inum(mp
, lino
));
2769 * special case the "lost+found" entry if it's pointing
2770 * to where we think lost+found should be. if that's
2771 * the case, that's the one we created in phase 6.
2772 * just skip it. no need to process it and its ..
2773 * link is already accounted for. Also skip entries
2774 * with bogus inode numbers if we're in no modify mode.
2777 if (lino
== orphanage_ino
&& strcmp(fname
, ORPHANAGE
) == 0
2778 || no_modify
&& verify_inum(mp
, lino
)) {
2779 next_sfe
= (xfs_dir_sf_entry_t
*)
2780 ((__psint_t
) sf_entry
+
2781 XFS_DIR_SF_ENTSIZE_BYENTRY(sf_entry
));
2785 irec
= find_inode_rec(XFS_INO_TO_AGNO(mp
, lino
),
2786 XFS_INO_TO_AGINO(mp
, lino
));
2788 if (irec
== NULL
&& no_modify
) {
2790 "entry \"%s\" in shortform dir %llu references non-existent ino %llu\n",
2792 do_warn("would junk entry\n");
2796 ASSERT(irec
!= NULL
);
2798 ino_offset
= XFS_INO_TO_AGINO(mp
, lino
) - irec
->ino_startnum
;
2801 * if it's a free inode, blow out the entry.
2802 * by now, any inode that we think is free
2805 if (is_inode_free(irec
, ino_offset
)) {
2807 * don't complain if this entry points to the old
2808 * and now-free lost+found inode
2810 if (verbose
|| no_modify
|| lino
!= old_orphanage_ino
)
2812 "entry \"%s\" in shortform dir inode %llu points to free inode %llu\n",
2818 do_warn("would junk entry \"%s\"\n",
2821 } else if (!inode_isadir(irec
, ino_offset
)) {
2823 * check easy case first, regular inode, just bump
2824 * the link count and continue
2826 add_inode_reached(irec
, ino_offset
);
2828 next_sfe
= (xfs_dir_sf_entry_t
*)
2829 ((__psint_t
) sf_entry
+
2830 XFS_DIR_SF_ENTSIZE_BYENTRY(sf_entry
));
2833 parent
= get_inode_parent(irec
, ino_offset
);
2836 * bump up the link counts in parent and child.
2837 * directory but if the link doesn't agree with
2838 * the .. in the child, blow out the entry
2840 if (is_inode_reached(irec
, ino_offset
)) {
2843 "entry \"%s\" in dir %llu references already connected dir ino %llu,\n",
2845 } else if (parent
== ino
) {
2846 add_inode_reached(irec
, ino_offset
);
2847 add_inode_ref(current_irec
, current_ino_offset
);
2849 if (!is_inode_refchecked(lino
, irec
,
2851 push_dir(stack
, lino
);
2855 "entry \"%s\" in dir %llu not consistent with .. value (%llu) in dir ino %llu,\n",
2856 fname
, ino
, parent
, lino
);
2862 tmp_elen
= XFS_DIR_SF_ENTSIZE_BYENTRY(sf_entry
);
2863 tmp_sfe
= (xfs_dir_sf_entry_t
*)
2864 ((__psint_t
) sf_entry
+ tmp_elen
);
2865 tmp_len
= max_size
- ((__psint_t
) tmp_sfe
2867 max_size
-= tmp_elen
;
2868 bytes_deleted
+= tmp_elen
;
2870 memmove(sf_entry
, tmp_sfe
, tmp_len
);
2872 INT_MOD(sf
->hdr
.count
, ARCH_CONVERT
, -1);
2873 bzero((void *) ((__psint_t
) sf_entry
+ tmp_len
),
2877 * set the tmp value to the current
2878 * pointer so we'll process the entry
2884 * WARNING: drop the index i by one
2885 * so it matches the decremented count for
2886 * accurate comparisons in the loop test
2892 if (verbose
|| lino
!= old_orphanage_ino
)
2894 "junking entry \"%s\" in directory inode %llu\n",
2897 do_warn("would junk entry \"%s\"\n", fname
);
2902 * go onto next entry unless we've just junked an
2903 * entry in which the current entry pointer points
2904 * to an unprocessed entry. have to take into entries
2905 * with bad namelen into account in no modify mode since we
2906 * calculate size based on next_sfe.
2908 ASSERT(no_modify
|| bad_sfnamelen
== 0);
2910 next_sfe
= (tmp_sfe
== NULL
)
2911 ? (xfs_dir_sf_entry_t
*) ((__psint_t
) sf_entry
2913 ? XFS_DIR_SF_ENTSIZE_BYENTRY(sf_entry
)
2914 : sizeof(xfs_dir_sf_entry_t
) - 1
2921 * sync up sizes if required
2924 ASSERT(bytes_deleted
> 0);
2926 libxfs_idata_realloc(ip
, -bytes_deleted
, XFS_DATA_FORK
);
2927 ip
->i_d
.di_size
-= bytes_deleted
;
2930 if (ip
->i_d
.di_size
!= ip
->i_df
.if_bytes
) {
2931 ASSERT(ip
->i_df
.if_bytes
== (xfs_fsize_t
)
2932 ((__psint_t
) next_sfe
- (__psint_t
) sf
));
2933 ip
->i_d
.di_size
= (xfs_fsize_t
)
2934 ((__psint_t
) next_sfe
- (__psint_t
) sf
);
2936 "setting size to %lld bytes to reflect junked entries\n",
2944 prune_sf_dir_entry(xfs_mount_t
*mp
, xfs_ino_t ino
, xfs_inode_t
*ip
)
2948 xfs_dir_shortform_t
*sf
;
2949 xfs_dir_sf_entry_t
*sf_entry
, *next_sfe
, *tmp_sfe
;
2956 char fname
[MAXNAMELEN
+ 1];
2959 sf
= (xfs_dir_shortform_t
*) ifp
->if_u1
.if_data
;
2962 max_size
= ifp
->if_bytes
;
2963 ASSERT(ip
->i_d
.di_size
<= ifp
->if_bytes
);
2966 * now run through entries and delete every bad entry
2968 sf_entry
= next_sfe
= &sf
->list
[0];
2970 for (i
= 0; i
< INT_GET(sf
->hdr
.count
, ARCH_CONVERT
) && max_size
>
2971 (__psint_t
)next_sfe
- (__psint_t
)sf
;
2972 sf_entry
= next_sfe
, i
++) {
2975 XFS_DIR_SF_GET_DIRINO_ARCH(&sf_entry
->inumber
, &lino
, ARCH_CONVERT
);
2977 bcopy(sf_entry
->name
, fname
, sf_entry
->namelen
);
2978 fname
[sf_entry
->namelen
] = '\0';
2980 if (sf_entry
->name
[0] == '/') {
2982 tmp_elen
= XFS_DIR_SF_ENTSIZE_BYENTRY(sf_entry
);
2983 tmp_sfe
= (xfs_dir_sf_entry_t
*)
2984 ((__psint_t
) sf_entry
+ tmp_elen
);
2985 tmp_len
= max_size
- ((__psint_t
) tmp_sfe
2987 max_size
-= tmp_elen
;
2988 bytes_deleted
+= tmp_elen
;
2990 memmove(sf_entry
, tmp_sfe
, tmp_len
);
2992 INT_MOD(sf
->hdr
.count
, ARCH_CONVERT
, -1);
2993 bzero((void *) ((__psint_t
) sf_entry
+ tmp_len
),
2997 * set the tmp value to the current
2998 * pointer so we'll process the entry
3004 * WARNING: drop the index i by one
3005 * so it matches the decremented count for
3006 * accurate comparisons in the loop test
3011 next_sfe
= (tmp_sfe
== NULL
)
3012 ? (xfs_dir_sf_entry_t
*) ((__psint_t
) sf_entry
+
3013 XFS_DIR_SF_ENTSIZE_BYENTRY(sf_entry
))
3018 * sync up sizes if required
3020 if (bytes_deleted
> 0) {
3021 libxfs_idata_realloc(ip
, -bytes_deleted
, XFS_DATA_FORK
);
3022 ip
->i_d
.di_size
-= bytes_deleted
;
3025 if (ip
->i_d
.di_size
!= ip
->i_df
.if_bytes
) {
3026 ASSERT(ip
->i_df
.if_bytes
== (xfs_fsize_t
)
3027 ((__psint_t
) next_sfe
- (__psint_t
) sf
));
3028 ip
->i_d
.di_size
= (xfs_fsize_t
)
3029 ((__psint_t
) next_sfe
- (__psint_t
) sf
);
3031 "setting size to %lld bytes to reflect junked entries\n",
3037 * shortform directory v2 processing routines -- entry verification and
3038 * bad entry deletion (pruning).
3041 shortform_dir2_entry_check(xfs_mount_t
*mp
,
3046 ino_tree_node_t
*current_irec
,
3047 int current_ino_offset
)
3052 xfs_dir2_sf_entry_t
*sfep
, *next_sfep
, *tmp_sfep
;
3054 ino_tree_node_t
*irec
;
3064 char fname
[MAXNAMELEN
+ 1];
3068 sfp
= (xfs_dir2_sf_t
*) ifp
->if_u1
.if_data
;
3070 bytes_deleted
= i8
= 0;
3072 max_size
= ifp
->if_bytes
;
3073 ASSERT(ip
->i_d
.di_size
<= ifp
->if_bytes
);
3076 * no '.' entry in shortform dirs, just bump up ref count by 1
3077 * '..' was already (or will be) accounted for and checked when
3078 * the directory is reached or will be taken care of when the
3079 * directory is moved to orphanage.
3081 add_inode_ref(current_irec
, current_ino_offset
);
3084 * now run through entries, stop at first bad entry, don't need
3085 * to skip over '..' since that's encoded in its own field and
3086 * no need to worry about '.' since it doesn't exist.
3088 sfep
= next_sfep
= XFS_DIR2_SF_FIRSTENTRY(sfp
);
3090 for (i
= 0; i
< INT_GET(sfp
->hdr
.count
, ARCH_CONVERT
) && max_size
>
3091 (__psint_t
)next_sfep
- (__psint_t
)sfp
;
3092 sfep
= next_sfep
, i
++) {
3097 lino
= XFS_DIR2_SF_GET_INUMBER_ARCH(sfp
, XFS_DIR2_SF_INUMBERP(sfep
), ARCH_CONVERT
);
3099 namelen
= sfep
->namelen
;
3101 ASSERT(no_modify
|| namelen
> 0);
3103 if (no_modify
&& namelen
== 0) {
3105 * if we're really lucky, this is
3106 * the last entry in which case we
3107 * can use the dir size to set the
3108 * namelen value. otherwise, forget
3109 * it because we're not going to be
3110 * able to find the next entry.
3114 if (i
== INT_GET(sfp
->hdr
.count
, ARCH_CONVERT
) - 1) {
3115 namelen
= ip
->i_d
.di_size
-
3116 ((__psint_t
) &sfep
->name
[0] -
3120 * don't process the rest of the directory,
3121 * break out of processing loop
3125 } else if (no_modify
&& (__psint_t
) sfep
- (__psint_t
) sfp
+
3126 + XFS_DIR2_SF_ENTSIZE_BYENTRY(sfp
, sfep
)
3127 > ip
->i_d
.di_size
) {
3130 if (i
== INT_GET(sfp
->hdr
.count
, ARCH_CONVERT
) - 1) {
3131 namelen
= ip
->i_d
.di_size
-
3132 ((__psint_t
) &sfep
->name
[0] -
3136 * don't process the rest of the directory,
3137 * break out of processing loop
3143 bcopy(sfep
->name
, fname
, sfep
->namelen
);
3144 fname
[sfep
->namelen
] = '\0';
3146 ASSERT(no_modify
|| (lino
!= NULLFSINO
&& lino
!= 0));
3147 ASSERT(no_modify
|| !verify_inum(mp
, lino
));
3150 * special case the "lost+found" entry if it's pointing
3151 * to where we think lost+found should be. if that's
3152 * the case, that's the one we created in phase 6.
3153 * just skip it. no need to process it and its ..
3154 * link is already accounted for. Also skip entries
3155 * with bogus inode numbers if we're in no modify mode.
3158 if (lino
== orphanage_ino
&& strcmp(fname
, ORPHANAGE
) == 0
3159 || no_modify
&& verify_inum(mp
, lino
)) {
3160 next_sfep
= (xfs_dir2_sf_entry_t
*)
3162 XFS_DIR2_SF_ENTSIZE_BYENTRY(sfp
, sfep
));
3166 irec
= find_inode_rec(XFS_INO_TO_AGNO(mp
, lino
),
3167 XFS_INO_TO_AGINO(mp
, lino
));
3169 if (irec
== NULL
&& no_modify
) {
3170 do_warn("entry \"%s\" in shortform directory %llu "
3171 "references non-existent inode %llu\n",
3173 do_warn("would junk entry\n");
3177 ASSERT(irec
!= NULL
);
3179 ino_offset
= XFS_INO_TO_AGINO(mp
, lino
) - irec
->ino_startnum
;
3182 * if it's a free inode, blow out the entry.
3183 * by now, any inode that we think is free
3186 if (is_inode_free(irec
, ino_offset
)) {
3188 * don't complain if this entry points to the old
3189 * and now-free lost+found inode
3191 if (verbose
|| no_modify
|| lino
!= old_orphanage_ino
)
3192 do_warn("entry \"%s\" in shortform directory "
3193 "inode %llu points to free inode "
3200 do_warn("would junk entry \"%s\"\n",
3203 } else if (!inode_isadir(irec
, ino_offset
)) {
3205 * check easy case first, regular inode, just bump
3206 * the link count and continue
3208 add_inode_reached(irec
, ino_offset
);
3210 next_sfep
= (xfs_dir2_sf_entry_t
*)
3212 XFS_DIR2_SF_ENTSIZE_BYENTRY(sfp
, sfep
));
3215 parent
= get_inode_parent(irec
, ino_offset
);
3218 * bump up the link counts in parent and child.
3219 * directory but if the link doesn't agree with
3220 * the .. in the child, blow out the entry
3222 if (is_inode_reached(irec
, ino_offset
)) {
3224 do_warn("entry \"%s\" in directory inode %llu "
3225 "references already connected inode "
3228 } else if (parent
== ino
) {
3229 add_inode_reached(irec
, ino_offset
);
3230 add_inode_ref(current_irec
, current_ino_offset
);
3232 if (!is_inode_refchecked(lino
, irec
,
3234 push_dir(stack
, lino
);
3237 do_warn("entry \"%s\" in directory inode %llu "
3238 "not consistent with .. value (%llu) "
3240 fname
, ino
, parent
, lino
);
3246 tmp_elen
= XFS_DIR2_SF_ENTSIZE_BYENTRY(sfp
, sfep
);
3247 tmp_sfep
= (xfs_dir2_sf_entry_t
*)
3248 ((__psint_t
) sfep
+ tmp_elen
);
3249 tmp_len
= max_size
- ((__psint_t
) tmp_sfep
3251 max_size
-= tmp_elen
;
3252 bytes_deleted
+= tmp_elen
;
3254 memmove(sfep
, tmp_sfep
, tmp_len
);
3256 INT_MOD(sfp
->hdr
.count
, ARCH_CONVERT
, -1);
3257 bzero((void *) ((__psint_t
) sfep
+ tmp_len
),
3261 * set the tmp value to the current
3262 * pointer so we'll process the entry
3268 * WARNING: drop the index i by one
3269 * so it matches the decremented count for
3270 * accurate comparisons in the loop test
3276 if (verbose
|| lino
!= old_orphanage_ino
)
3277 do_warn("junking entry \"%s\" in "
3278 "directory inode %llu\n",
3281 do_warn("would junk entry \"%s\"\n", fname
);
3283 } else if (lino
> XFS_DIR2_MAX_SHORT_INUM
)
3287 * go onto next entry unless we've just junked an
3288 * entry in which the current entry pointer points
3289 * to an unprocessed entry. have to take into entries
3290 * with bad namelen into account in no modify mode since we
3291 * calculate size based on next_sfep.
3293 ASSERT(no_modify
|| bad_sfnamelen
== 0);
3295 next_sfep
= (tmp_sfep
== NULL
)
3296 ? (xfs_dir2_sf_entry_t
*) ((__psint_t
) sfep
3298 ? XFS_DIR2_SF_ENTSIZE_BYENTRY(sfp
, sfep
)
3299 : XFS_DIR2_SF_ENTSIZE_BYNAME(sfp
, namelen
)))
3303 if (sfp
->hdr
.i8count
!= i8
) {
3305 do_warn("would fix i8count in inode %llu\n", ino
);
3308 tmp_sfep
= next_sfep
;
3309 process_sf_dir2_fixi8(sfp
, &tmp_sfep
);
3311 (__psint_t
)next_sfep
-
3312 (__psint_t
)tmp_sfep
;
3313 next_sfep
= tmp_sfep
;
3315 sfp
->hdr
.i8count
= i8
;
3317 do_warn("fixing i8count in inode %llu\n", ino
);
3322 * sync up sizes if required
3325 ASSERT(bytes_deleted
> 0);
3327 libxfs_idata_realloc(ip
, -bytes_deleted
, XFS_DATA_FORK
);
3328 ip
->i_d
.di_size
-= bytes_deleted
;
3331 if (ip
->i_d
.di_size
!= ip
->i_df
.if_bytes
) {
3332 ASSERT(ip
->i_df
.if_bytes
== (xfs_fsize_t
)
3333 ((__psint_t
) next_sfep
- (__psint_t
) sfp
));
3334 ip
->i_d
.di_size
= (xfs_fsize_t
)
3335 ((__psint_t
) next_sfep
- (__psint_t
) sfp
);
3336 do_warn("setting size to %lld bytes to reflect junked "
3344 * processes all directories reachable via the inodes on the stack
3345 * returns 0 if things are good, 1 if there's a problem
3348 process_dirstack(xfs_mount_t
*mp
, dir_stack_t
*stack
)
3350 xfs_bmap_free_t flist
;
3351 xfs_fsblock_t first
;
3355 xfs_dahash_t hashval
;
3356 ino_tree_node_t
*irec
;
3357 int ino_offset
, need_dot
, committed
;
3358 int dirty
, num_illegal
, error
, nres
;
3361 * pull directory inode # off directory stack
3363 * open up directory inode, check all entries,
3364 * then call prune_dir_entries to remove all
3365 * remaining illegal directory entries.
3368 while ((ino
= pop_dir(stack
)) != NULLFSINO
) {
3369 irec
= find_inode_rec(XFS_INO_TO_AGNO(mp
, ino
),
3370 XFS_INO_TO_AGINO(mp
, ino
));
3371 ASSERT(irec
!= NULL
);
3373 ino_offset
= XFS_INO_TO_AGINO(mp
, ino
) - irec
->ino_startnum
;
3375 ASSERT(!is_inode_refchecked(ino
, irec
, ino_offset
));
3377 if (error
= libxfs_iget(mp
, NULL
, ino
, 0, &ip
, 0)) {
3379 do_error("couldn't map inode %llu, err = %d\n",
3382 do_warn("couldn't map inode %llu, err = %d\n",
3385 * see below for what we're doing if this
3386 * is root. Why do we need to do this here?
3387 * to ensure that the root doesn't show up
3388 * as being disconnected in the no_modify case.
3390 if (mp
->m_sb
.sb_rootino
== ino
) {
3391 add_inode_reached(irec
, 0);
3392 add_inode_ref(irec
, 0);
3396 add_inode_refchecked(ino
, irec
, 0);
3400 need_dot
= dirty
= num_illegal
= 0;
3402 if (mp
->m_sb
.sb_rootino
== ino
) {
3404 * mark root inode reached and bump up
3405 * link count for root inode to account
3406 * for '..' entry since the root inode is
3407 * never reached by a parent. we know
3408 * that root's '..' is always good --
3409 * guaranteed by phase 3 and/or below.
3411 add_inode_reached(irec
, ino_offset
);
3413 * account for link for the orphanage
3414 * "lost+found". if we're running in
3415 * modify mode and it already existed,
3416 * we deleted it so it's '..' reference
3417 * never got counted. so add it here if
3418 * we're going to create lost+found.
3420 * if we're running in no_modify mode,
3421 * we never deleted lost+found and we're
3422 * not going to create it so do nothing.
3424 * either way, the counts will match when
3425 * we look at the root inode's nlinks
3426 * field and compare that to our incore
3430 add_inode_ref(irec
, ino_offset
);
3433 add_inode_refchecked(ino
, irec
, ino_offset
);
3436 * look for bogus entries
3438 switch (ip
->i_d
.di_format
) {
3439 case XFS_DINODE_FMT_EXTENTS
:
3440 case XFS_DINODE_FMT_BTREE
:
3442 * also check for missing '.' in longform dirs.
3443 * missing .. entries are added if required when
3444 * the directory is connected to lost+found. but
3445 * we need to create '.' entries here.
3447 if (XFS_SB_VERSION_HASDIRV2(&mp
->m_sb
))
3448 longform_dir2_entry_check(mp
, ino
, ip
,
3449 &num_illegal
, &need_dot
,
3453 longform_dir_entry_check(mp
, ino
, ip
,
3454 &num_illegal
, &need_dot
,
3458 case XFS_DINODE_FMT_LOCAL
:
3459 tp
= libxfs_trans_alloc(mp
, 0);
3461 * using the remove reservation is overkill
3462 * since at most we'll only need to log the
3463 * inode but it's easier than wedging a
3464 * new define in ourselves.
3466 nres
= no_modify
? 0 : XFS_REMOVE_SPACE_RES(mp
);
3467 error
= libxfs_trans_reserve(tp
, nres
,
3468 XFS_REMOVE_LOG_RES(mp
), 0,
3469 XFS_TRANS_PERM_LOG_RES
,
3470 XFS_REMOVE_LOG_COUNT
);
3474 libxfs_trans_ijoin(tp
, ip
, 0);
3475 libxfs_trans_ihold(tp
, ip
);
3477 if (XFS_SB_VERSION_HASDIRV2(&mp
->m_sb
))
3478 shortform_dir2_entry_check(mp
, ino
, ip
, &dirty
,
3482 shortform_dir_entry_check(mp
, ino
, ip
, &dirty
,
3486 ASSERT(dirty
== 0 || dirty
&& !no_modify
);
3488 libxfs_trans_log_inode(tp
, ip
,
3489 XFS_ILOG_CORE
| XFS_ILOG_DDATA
);
3490 libxfs_trans_commit(tp
, XFS_TRANS_RELEASE_LOG_RES
3491 |XFS_TRANS_SYNC
, 0);
3493 libxfs_trans_cancel(tp
, XFS_TRANS_RELEASE_LOG_RES
);
3502 if (!no_modify
&& !orphanage_entered
&&
3503 ino
== mp
->m_sb
.sb_rootino
) {
3504 do_warn("re-entering %s into root directory\n",
3506 tp
= libxfs_trans_alloc(mp
, 0);
3507 nres
= XFS_MKDIR_SPACE_RES(mp
, strlen(ORPHANAGE
));
3508 error
= libxfs_trans_reserve(tp
, nres
,
3509 XFS_MKDIR_LOG_RES(mp
), 0,
3510 XFS_TRANS_PERM_LOG_RES
,
3511 XFS_MKDIR_LOG_COUNT
);
3514 libxfs_trans_ijoin(tp
, ip
, 0);
3515 libxfs_trans_ihold(tp
, ip
);
3516 XFS_BMAP_INIT(&flist
, &first
);
3517 if (error
= dir_createname(mp
, tp
, ip
, ORPHANAGE
,
3519 orphanage_ino
, &first
, &flist
,
3521 do_error("can't make %s entry in root inode "
3522 "%llu, createname error %d\n",
3523 ORPHANAGE
, ino
, error
);
3524 libxfs_trans_log_inode(tp
, ip
, XFS_ILOG_CORE
);
3525 error
= libxfs_bmap_finish(&tp
, &flist
, first
, &committed
);
3527 libxfs_trans_commit(tp
,
3528 XFS_TRANS_RELEASE_LOG_RES
| XFS_TRANS_SYNC
, 0);
3529 orphanage_entered
= 1;
3533 * if we have to create a .. for /, do it now *before*
3534 * we delete the bogus entries, otherwise the directory
3535 * could transform into a shortform dir which would
3536 * probably cause the simulation to choke. Even
3537 * if the illegal entries get shifted around, it's ok
3538 * because the entries are structurally intact and in
3539 * in hash-value order so the simulation won't get confused
3540 * if it has to move them around.
3542 if (!no_modify
&& need_root_dotdot
&&
3543 ino
== mp
->m_sb
.sb_rootino
) {
3544 ASSERT(ip
->i_d
.di_format
!= XFS_DINODE_FMT_LOCAL
);
3546 do_warn("recreating root directory .. entry\n");
3548 tp
= libxfs_trans_alloc(mp
, 0);
3551 nres
= XFS_MKDIR_SPACE_RES(mp
, 2);
3552 error
= libxfs_trans_reserve(tp
, nres
,
3553 XFS_MKDIR_LOG_RES(mp
),
3555 XFS_TRANS_PERM_LOG_RES
,
3556 XFS_MKDIR_LOG_COUNT
);
3561 libxfs_trans_ijoin(tp
, ip
, 0);
3562 libxfs_trans_ihold(tp
, ip
);
3564 XFS_BMAP_INIT(&flist
, &first
);
3566 if (error
= dir_createname(mp
, tp
, ip
, "..", 2,
3567 ip
->i_ino
, &first
, &flist
, nres
))
3569 "can't make \"..\" entry in root inode %llu, createname error %d\n",
3572 libxfs_trans_log_inode(tp
, ip
, XFS_ILOG_CORE
);
3574 error
= libxfs_bmap_finish(&tp
, &flist
, first
,
3577 libxfs_trans_commit(tp
, XFS_TRANS_RELEASE_LOG_RES
3578 |XFS_TRANS_SYNC
, 0);
3580 need_root_dotdot
= 0;
3581 } else if (need_root_dotdot
&& ino
== mp
->m_sb
.sb_rootino
) {
3582 do_warn("would recreate root directory .. entry\n");
3586 * delete any illegal entries -- which should only exist
3587 * if the directory is a longform directory. bogus
3588 * shortform directory entries were deleted in phase 4.
3590 if (!no_modify
&& num_illegal
> 0) {
3591 ASSERT(ip
->i_d
.di_format
!= XFS_DINODE_FMT_LOCAL
);
3592 ASSERT(!XFS_SB_VERSION_HASDIRV2(&mp
->m_sb
));
3594 while (num_illegal
> 0 && ip
->i_d
.di_format
!=
3595 XFS_DINODE_FMT_LOCAL
) {
3596 prune_lf_dir_entry(mp
, ino
, ip
, &hashval
);
3601 * handle case where we've deleted so many
3602 * entries that the directory has changed from
3603 * a longform to a shortform directory. have
3604 * to allocate a transaction since we're working
3605 * with the incore data fork.
3607 if (num_illegal
> 0) {
3608 ASSERT(ip
->i_d
.di_format
==
3609 XFS_DINODE_FMT_LOCAL
);
3610 tp
= libxfs_trans_alloc(mp
, 0);
3612 * using the remove reservation is overkill
3613 * since at most we'll only need to log the
3614 * inode but it's easier than wedging a
3615 * new define in ourselves. 10 block fs
3616 * space reservation is also overkill but
3619 nres
= XFS_REMOVE_SPACE_RES(mp
);
3620 error
= libxfs_trans_reserve(tp
, nres
,
3621 XFS_REMOVE_LOG_RES(mp
), 0,
3622 XFS_TRANS_PERM_LOG_RES
,
3623 XFS_REMOVE_LOG_COUNT
);
3627 libxfs_trans_ijoin(tp
, ip
, 0);
3628 libxfs_trans_ihold(tp
, ip
);
3630 prune_sf_dir_entry(mp
, ino
, ip
);
3632 libxfs_trans_log_inode(tp
, ip
,
3633 XFS_ILOG_CORE
| XFS_ILOG_DDATA
);
3635 libxfs_trans_commit(tp
, XFS_TRANS_RELEASE_LOG_RES
3636 |XFS_TRANS_SYNC
, 0);
3641 * if we need to create the '.' entry, do so only if
3642 * the directory is a longform dir. it it's been
3643 * turned into a shortform dir, then the inode is ok
3644 * since shortform dirs have no '.' entry and the inode
3645 * has already been committed by prune_lf_dir_entry().
3649 * bump up our link count but don't
3650 * bump up the inode link count. chances
3651 * are good that even though we lost '.'
3652 * the inode link counts reflect '.' so
3653 * leave the inode link count alone and if
3654 * it turns out to be wrong, we'll catch
3657 add_inode_ref(irec
, ino_offset
);
3661 "would create missing \".\" entry in dir ino %llu\n",
3663 } else if (ip
->i_d
.di_format
!= XFS_DINODE_FMT_LOCAL
) {
3665 * need to create . entry in longform dir.
3668 "creating missing \".\" entry in dir ino %llu\n",
3671 tp
= libxfs_trans_alloc(mp
, 0);
3674 nres
= XFS_MKDIR_SPACE_RES(mp
, 1);
3675 error
= libxfs_trans_reserve(tp
, nres
,
3676 XFS_MKDIR_LOG_RES(mp
),
3678 XFS_TRANS_PERM_LOG_RES
,
3679 XFS_MKDIR_LOG_COUNT
);
3684 libxfs_trans_ijoin(tp
, ip
, 0);
3685 libxfs_trans_ihold(tp
, ip
);
3687 XFS_BMAP_INIT(&flist
, &first
);
3689 if (error
= dir_createname(mp
, tp
, ip
, ".",
3690 1, ip
->i_ino
, &first
, &flist
,
3693 "can't make \".\" entry in dir ino %llu, createname error %d\n",
3696 libxfs_trans_log_inode(tp
, ip
, XFS_ILOG_CORE
);
3698 error
= libxfs_bmap_finish(&tp
, &flist
, first
,
3701 libxfs_trans_commit(tp
, XFS_TRANS_RELEASE_LOG_RES
3702 |XFS_TRANS_SYNC
, 0);
3711 * mark realtime bitmap and summary inodes as reached.
3712 * quota inode will be marked here as well
3715 mark_standalone_inodes(xfs_mount_t
*mp
)
3717 ino_tree_node_t
*irec
;
3720 irec
= find_inode_rec(XFS_INO_TO_AGNO(mp
, mp
->m_sb
.sb_rbmino
),
3721 XFS_INO_TO_AGINO(mp
, mp
->m_sb
.sb_rbmino
));
3723 ASSERT(irec
!= NULL
);
3725 offset
= XFS_INO_TO_AGINO(mp
, mp
->m_sb
.sb_rbmino
) -
3728 add_inode_reached(irec
, offset
);
3730 irec
= find_inode_rec(XFS_INO_TO_AGNO(mp
, mp
->m_sb
.sb_rsumino
),
3731 XFS_INO_TO_AGINO(mp
, mp
->m_sb
.sb_rsumino
));
3733 offset
= XFS_INO_TO_AGINO(mp
, mp
->m_sb
.sb_rsumino
) -
3736 ASSERT(irec
!= NULL
);
3738 add_inode_reached(irec
, offset
);
3741 if (mp
->m_sb
.sb_uquotino
3742 && mp
->m_sb
.sb_uquotino
!= NULLFSINO
) {
3743 irec
= find_inode_rec(XFS_INO_TO_AGNO(mp
,
3744 mp
->m_sb
.sb_uquotino
),
3745 XFS_INO_TO_AGINO(mp
, mp
->m_sb
.sb_uquotino
));
3746 offset
= XFS_INO_TO_AGINO(mp
, mp
->m_sb
.sb_uquotino
)
3747 - irec
->ino_startnum
;
3748 add_inode_reached(irec
, offset
);
3750 if (mp
->m_sb
.sb_gquotino
3751 && mp
->m_sb
.sb_gquotino
!= NULLFSINO
) {
3752 irec
= find_inode_rec(XFS_INO_TO_AGNO(mp
,
3753 mp
->m_sb
.sb_gquotino
),
3754 XFS_INO_TO_AGINO(mp
, mp
->m_sb
.sb_gquotino
));
3755 offset
= XFS_INO_TO_AGINO(mp
, mp
->m_sb
.sb_gquotino
)
3756 - irec
->ino_startnum
;
3757 add_inode_reached(irec
, offset
);
3763 phase6(xfs_mount_t
*mp
)
3766 ino_tree_node_t
*irec
;
3771 bzero(&zerocr
, sizeof(cred_t
));
3773 do_log("Phase 6 - check inode connectivity...\n");
3776 teardown_bmap_finish(mp
);
3780 incore_ext_teardown(mp
);
3782 add_ino_backptrs(mp
);
3785 * verify existence of root directory - if we have to
3786 * make one, it's ok for the incore data structs not to
3787 * know about it since everything about it (and the other
3788 * inodes in its chunk if a new chunk was created) are ok
3790 if (need_root_inode
) {
3792 do_warn("reinitializing root directory\n");
3794 need_root_inode
= 0;
3795 need_root_dotdot
= 0;
3797 do_warn("would reinitialize root directory\n");
3803 do_warn("reinitializing realtime bitmap inode\n");
3807 do_warn("would reinitialize realtime bitmap inode\n");
3813 do_warn("reinitializing realtime summary inode\n");
3817 do_warn("would reinitialize realtime summary inode\n");
3823 " - resetting contents of realtime bitmap and summary inodes\n");
3824 if (fill_rbmino(mp
)) {
3826 "Warning: realtime bitmap may be inconsistent\n");
3829 if (fill_rsumino(mp
)) {
3831 "Warning: realtime bitmap may be inconsistent\n");
3836 * make orphanage (it's guaranteed to not exist now)
3839 do_log(" - ensuring existence of %s directory\n",
3841 orphanage_ino
= mk_orphanage(mp
);
3844 dir_stack_init(&stack
);
3846 mark_standalone_inodes(mp
);
3849 * push root dir on stack, then go
3851 if (!need_root_inode
) {
3852 do_log(" - traversing filesystem starting at / ... \n");
3854 push_dir(&stack
, mp
->m_sb
.sb_rootino
);
3855 process_dirstack(mp
, &stack
);
3857 do_log(" - traversal finished ... \n");
3859 ASSERT(no_modify
!= 0);
3862 " - root inode lost, cannot make new one in no modify mode ... \n");
3864 " - skipping filesystem traversal from / ... \n");
3867 do_log(" - traversing all unattached subtrees ... \n");
3869 irec
= find_inode_rec(XFS_INO_TO_AGNO(mp
, mp
->m_sb
.sb_rootino
),
3870 XFS_INO_TO_AGINO(mp
, mp
->m_sb
.sb_rootino
));
3873 * we always have a root inode, even if it's free...
3874 * if the root is free, forget it, lost+found is already gone
3876 if (is_inode_free(irec
, 0) || !inode_isadir(irec
, 0)) {
3877 need_root_inode
= 1;
3881 * then process all unreached inodes
3882 * by walking incore inode tree
3884 * get next unreached directory inode # from
3886 * push inode on dir stack
3887 * call process_dirstack
3889 for (i
= 0; i
< glob_agcount
; i
++) {
3890 irec
= findfirst_inode_rec(i
);
3895 while (irec
!= NULL
) {
3896 for (j
= 0; j
< XFS_INODES_PER_CHUNK
; j
++) {
3897 if (!is_inode_confirmed(irec
, j
))
3900 * skip directories that have already been
3901 * processed, even if they haven't been
3902 * reached. If they are reachable, we'll
3903 * pick them up when we process their parent.
3905 ino
= XFS_AGINO_TO_INO(mp
, i
,
3906 j
+ irec
->ino_startnum
);
3907 if (inode_isadir(irec
, j
) &&
3908 !is_inode_refchecked(ino
,
3910 push_dir(&stack
, ino
);
3911 process_dirstack(mp
, &stack
);
3914 irec
= next_ino_rec(irec
);
3918 do_log(" - traversals finished ... \n");
3919 do_log(" - moving disconnected inodes to lost+found ... \n");
3922 * move all disconnected inodes to the orphanage
3924 for (i
= 0; i
< glob_agcount
; i
++) {
3925 irec
= findfirst_inode_rec(i
);
3930 while (irec
!= NULL
) {
3931 for (j
= 0; j
< XFS_INODES_PER_CHUNK
; j
++) {
3932 ASSERT(is_inode_confirmed(irec
, j
));
3933 if (is_inode_free(irec
, j
))
3935 if (!is_inode_reached(irec
, j
)) {
3936 ASSERT(inode_isadir(irec
, j
) ||
3937 num_inode_references(irec
, j
)
3939 ino
= XFS_AGINO_TO_INO(mp
, i
,
3940 j
+ irec
->ino_startnum
);
3941 if (inode_isadir(irec
, j
))
3943 "disconnected dir inode %llu, ",
3947 "disconnected inode %llu, ",
3950 do_warn("moving to %s\n",
3952 mv_orphanage(mp
, orphanage_ino
,
3954 inode_isadir(irec
, j
));
3956 do_warn("would move to %s\n",
3960 * for read-only case, even though
3961 * the inode isn't really reachable,
3962 * set the flag (and bump our link
3963 * count) anyway to fool phase 7
3965 add_inode_reached(irec
, j
);
3968 irec
= next_ino_rec(irec
);