2 * Copyright (c) 2000-2002 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/
40 #include "dir_stack.h"
42 #include "err_protos.h"
47 static int orphanage_entered
;
50 * Data structures and routines to keep track of directory entries
51 * and whether their leaf entry has been seen
53 typedef struct dir_hash_ent
{
54 struct dir_hash_ent
*next
; /* pointer to next entry */
55 xfs_dir2_leaf_entry_t ent
; /* address and hash value */
56 short junkit
; /* name starts with / */
57 short seen
; /* have seen leaf entry */
60 typedef struct dir_hash_tab
{
61 int size
; /* size of hash table */
62 dir_hash_ent_t
*tab
[1];/* actual hash table, variable size */
64 #define DIR_HASH_TAB_SIZE(n) \
65 (offsetof(dir_hash_tab_t, tab) + (sizeof(dir_hash_ent_t *) * (n)))
66 #define DIR_HASH_FUNC(t,a) ((a) % (t)->size)
69 * Track the contents of the freespace table in a directory.
71 typedef struct freetab
{
72 int naents
; /* expected number of data blocks */
73 int nents
; /* number of data blocks processed */
75 xfs_dir2_data_off_t v
;
79 #define FREETAB_SIZE(n) \
80 (offsetof(freetab_t, ents) + (sizeof(struct freetab_ent) * (n)))
82 #define DIR_HASH_CK_OK 0
83 #define DIR_HASH_CK_DUPLEAF 1
84 #define DIR_HASH_CK_BADHASH 2
85 #define DIR_HASH_CK_NODATA 3
86 #define DIR_HASH_CK_NOLEAF 4
87 #define DIR_HASH_CK_BADSTALE 5
91 dir_hash_tab_t
*hashtab
,
93 xfs_dir2_dataptr_t addr
,
99 i
= DIR_HASH_FUNC(hashtab
, addr
);
100 if ((p
= malloc(sizeof(*p
))) == NULL
) {
101 do_error("malloc failed in dir_hash_add (%u bytes)\n",
105 p
->next
= hashtab
->tab
[i
];
107 if (!(p
->junkit
= junk
))
108 p
->ent
.hashval
= hash
;
109 p
->ent
.address
= addr
;
115 dir_hash_tab_t
*hashtab
)
120 for (i
= 0; i
< hashtab
->size
; i
++) {
121 for (p
= hashtab
->tab
[i
]; p
; p
= p
->next
) {
131 dir_hash_tab_t
*hashtab
,
135 static char *seevalstr
[] = {
138 "hash value mismatch",
144 if (seeval
== DIR_HASH_CK_OK
&& dir_hash_unseen(hashtab
))
145 seeval
= DIR_HASH_CK_NOLEAF
;
146 if (seeval
== DIR_HASH_CK_OK
)
148 do_warn("bad hash table for directory inode %llu (%s): ", ip
->i_ino
,
151 do_warn("rebuilding\n");
153 do_warn("would rebuild\n");
159 dir_hash_tab_t
*hashtab
)
165 for (i
= 0; i
< hashtab
->size
; i
++) {
166 for (p
= hashtab
->tab
[i
]; p
; p
= n
) {
174 static dir_hash_tab_t
*
178 dir_hash_tab_t
*hashtab
;
181 hsize
= size
/ (16 * 4);
186 if ((hashtab
= calloc(DIR_HASH_TAB_SIZE(hsize
), 1)) == NULL
) {
187 do_error("calloc failed in dir_hash_init\n");
190 hashtab
->size
= hsize
;
196 dir_hash_tab_t
*hashtab
,
198 xfs_dir2_dataptr_t addr
)
203 i
= DIR_HASH_FUNC(hashtab
, addr
);
204 for (p
= hashtab
->tab
[i
]; p
; p
= p
->next
) {
205 if (p
->ent
.address
!= addr
)
208 return DIR_HASH_CK_DUPLEAF
;
209 if (p
->junkit
== 0 && p
->ent
.hashval
!= hash
)
210 return DIR_HASH_CK_BADHASH
;
212 return DIR_HASH_CK_OK
;
214 return DIR_HASH_CK_NODATA
;
219 dir_hash_tab_t
*hashtab
,
220 xfs_dir2_leaf_entry_t
*ents
,
228 for (i
= j
= 0; i
< count
; i
++) {
229 if (INT_GET(ents
[i
].address
, ARCH_CONVERT
) == XFS_DIR2_NULL_DATAPTR
) {
233 rval
= dir_hash_see(hashtab
, INT_GET(ents
[i
].hashval
, ARCH_CONVERT
), INT_GET(ents
[i
].address
, ARCH_CONVERT
));
234 if (rval
!= DIR_HASH_CK_OK
)
237 return j
== stale
? DIR_HASH_CK_OK
: DIR_HASH_CK_BADSTALE
;
242 * Version 1 or 2 directory routine wrappers
245 dir_init(xfs_mount_t
*mp
, xfs_trans_t
*tp
, xfs_inode_t
*dp
, xfs_inode_t
*pdp
)
247 if (XFS_SB_VERSION_HASDIRV2(&mp
->m_sb
))
248 libxfs_dir2_init(tp
, dp
, pdp
);
250 libxfs_dir_init(tp
, dp
, pdp
);
254 dir_createname(xfs_mount_t
*mp
, xfs_trans_t
*tp
, xfs_inode_t
*pip
,
255 char *name
, int namelen
, xfs_ino_t inum
, xfs_fsblock_t
*first
,
256 xfs_bmap_free_t
*flist
, xfs_extlen_t total
)
258 if (XFS_SB_VERSION_HASDIRV2(&mp
->m_sb
))
259 return libxfs_dir2_createname(tp
, pip
, name
, namelen
,
260 inum
, first
, flist
, total
);
262 return libxfs_dir_createname(tp
, pip
, name
, namelen
,
263 inum
, first
, flist
, total
);
267 dir_lookup(xfs_mount_t
*mp
, xfs_trans_t
*tp
, xfs_inode_t
*dp
, char *name
,
268 int namelen
, xfs_ino_t
*inum
)
270 if (XFS_SB_VERSION_HASDIRV2(&mp
->m_sb
))
271 return libxfs_dir2_lookup(tp
, dp
, name
, namelen
, inum
);
273 return libxfs_dir_lookup(tp
, dp
, name
, namelen
, inum
);
277 dir_replace(xfs_mount_t
*mp
, xfs_trans_t
*tp
, xfs_inode_t
*dp
, char *name
,
278 int namelen
, xfs_ino_t inum
, xfs_fsblock_t
*firstblock
,
279 xfs_bmap_free_t
*flist
, xfs_extlen_t total
)
281 if (XFS_SB_VERSION_HASDIRV2(&mp
->m_sb
))
282 return libxfs_dir2_replace(tp
, dp
, name
, namelen
, inum
,
283 firstblock
, flist
, total
);
285 return libxfs_dir_replace(tp
, dp
, name
, namelen
, inum
,
286 firstblock
, flist
, total
);
290 dir_removename(xfs_mount_t
*mp
, xfs_trans_t
*tp
, xfs_inode_t
*dp
, char *name
,
291 int namelen
, xfs_ino_t inum
, xfs_fsblock_t
*firstblock
,
292 xfs_bmap_free_t
*flist
, xfs_extlen_t total
)
294 if (XFS_SB_VERSION_HASDIRV2(&mp
->m_sb
))
295 return libxfs_dir2_removename(tp
, dp
, name
, namelen
, inum
,
296 firstblock
, flist
, total
);
298 return libxfs_dir_removename(tp
, dp
, name
, namelen
, inum
,
299 firstblock
, flist
, total
);
303 dir_bogus_removename(xfs_mount_t
*mp
, xfs_trans_t
*tp
, xfs_inode_t
*dp
,
304 char *name
, xfs_fsblock_t
*firstblock
, xfs_bmap_free_t
*flist
,
305 xfs_extlen_t total
, xfs_dahash_t hashval
, int namelen
)
307 if (XFS_SB_VERSION_HASDIRV2(&mp
->m_sb
))
308 return libxfs_dir2_bogus_removename(tp
, dp
, name
, firstblock
,
309 flist
, total
, hashval
, namelen
);
311 return libxfs_dir_bogus_removename(tp
, dp
, name
, firstblock
,
312 flist
, total
, hashval
, namelen
);
321 do_error("ran out of disk space!\n");
323 do_error("xfs_trans_reserve returned %d\n", err
);
327 mk_rbmino(xfs_mount_t
*mp
)
337 xfs_bmap_free_t flist
;
339 xfs_bmbt_irec_t map
[XFS_BMAP_MAX_NMAP
];
344 tp
= libxfs_trans_alloc(mp
, 0);
346 if ((i
= libxfs_trans_reserve(tp
, 10, 0, 0, 0, 0)))
349 error
= libxfs_trans_iget(mp
, tp
, mp
->m_sb
.sb_rbmino
, 0, &ip
);
351 do_error("couldn't iget realtime bitmap inode -- error - %d\n",
355 bzero(&ip
->i_d
, sizeof(xfs_dinode_core_t
));
357 ip
->i_d
.di_magic
= XFS_DINODE_MAGIC
;
358 ip
->i_d
.di_mode
= IFREG
;
359 ip
->i_d
.di_version
= XFS_DINODE_VERSION_1
;
360 ip
->i_d
.di_format
= XFS_DINODE_FMT_EXTENTS
;
361 ip
->i_d
.di_aformat
= XFS_DINODE_FMT_EXTENTS
;
363 ip
->i_d
.di_nlink
= 1; /* account for sb ptr */
368 ip
->i_df
.if_flags
= XFS_IFEXTENTS
;
369 ip
->i_df
.if_bytes
= ip
->i_df
.if_real_bytes
= 0;
370 ip
->i_df
.if_u1
.if_extents
= NULL
;
372 ip
->i_d
.di_size
= mp
->m_sb
.sb_rbmblocks
* mp
->m_sb
.sb_blocksize
;
377 libxfs_trans_log_inode(tp
, ip
, XFS_ILOG_CORE
);
378 libxfs_trans_ihold(tp
, ip
);
379 libxfs_trans_commit(tp
, XFS_TRANS_RELEASE_LOG_RES
|XFS_TRANS_SYNC
, NULL
);
382 * then allocate blocks for file and fill with zeroes (stolen
385 tp
= libxfs_trans_alloc(mp
, 0);
386 if ((error
= libxfs_trans_reserve(tp
, mp
->m_sb
.sb_rbmblocks
+
387 (XFS_BM_MAXLEVELS(mp
, XFS_DATA_FORK
) - 1), 0, 0, 0, 0)))
390 libxfs_trans_ijoin(tp
, ip
, 0);
392 XFS_BMAP_INIT(&flist
, &first
);
393 while (bno
< mp
->m_sb
.sb_rbmblocks
) {
394 nmap
= XFS_BMAP_MAX_NMAP
;
395 error
= libxfs_bmapi(tp
, ip
, bno
,
396 (xfs_extlen_t
)(mp
->m_sb
.sb_rbmblocks
- bno
),
397 XFS_BMAPI_WRITE
, &first
, mp
->m_sb
.sb_rbmblocks
,
400 do_error("couldn't allocate realtime bitmap - err %d\n",
403 for (i
= 0, ep
= map
; i
< nmap
; i
++, ep
++) {
404 libxfs_device_zero(mp
->m_dev
,
405 XFS_FSB_TO_DADDR(mp
, ep
->br_startblock
),
406 XFS_FSB_TO_BB(mp
, ep
->br_blockcount
));
407 bno
+= ep
->br_blockcount
;
410 error
= libxfs_bmap_finish(&tp
, &flist
, first
, &committed
);
413 "allocation of the realtime bitmap failed, error = %d\n",
416 libxfs_trans_commit(tp
, XFS_TRANS_RELEASE_LOG_RES
|XFS_TRANS_SYNC
, 0);
420 fill_rbmino(xfs_mount_t
*mp
)
435 tp
= libxfs_trans_alloc(mp
, 0);
437 if ((error
= libxfs_trans_reserve(tp
, 10, 0, 0, 0, 0)))
440 error
= libxfs_trans_iget(mp
, tp
, mp
->m_sb
.sb_rbmino
, 0, &ip
);
442 do_error("couldn't iget realtime bitmap inode -- error - %d\n",
446 while (bno
< mp
->m_sb
.sb_rbmblocks
) {
448 * fill the file one block at a time
451 error
= libxfs_bmapi(tp
, ip
, bno
, 1, XFS_BMAPI_WRITE
,
452 &first
, 1, &map
, &nmap
, NULL
);
453 if (error
|| nmap
!= 1) {
455 "couldn't map realtime bitmap block %llu - err %d\n",
459 ASSERT(map
.br_startblock
!= HOLESTARTBLOCK
);
461 error
= libxfs_trans_read_buf(
463 XFS_FSB_TO_DADDR(mp
, map
.br_startblock
),
464 XFS_FSB_TO_BB(mp
, 1), 1, &bp
);
468 "can't access block %llu (fsbno %llu) of realtime bitmap inode %llu\n",
469 bno
, map
.br_startblock
, mp
->m_sb
.sb_rbmino
);
473 bcopy(bmp
, XFS_BUF_PTR(bp
), mp
->m_sb
.sb_blocksize
);
475 libxfs_trans_log_buf(tp
, bp
, 0, mp
->m_sb
.sb_blocksize
- 1);
477 bmp
= (xfs_rtword_t
*)((__psint_t
) bmp
+ mp
->m_sb
.sb_blocksize
);
481 libxfs_trans_commit(tp
, XFS_TRANS_RELEASE_LOG_RES
|XFS_TRANS_SYNC
, 0);
487 fill_rsumino(xfs_mount_t
*mp
)
497 xfs_dfiloff_t end_bno
;
502 end_bno
= mp
->m_rsumsize
>> mp
->m_sb
.sb_blocklog
;
504 tp
= libxfs_trans_alloc(mp
, 0);
506 if ((error
= libxfs_trans_reserve(tp
, 10, 0, 0, 0, 0)))
509 error
= libxfs_trans_iget(mp
, tp
, mp
->m_sb
.sb_rsumino
, 0, &ip
);
511 do_error("couldn't iget realtime summary inode -- error - %d\n",
515 while (bno
< end_bno
) {
517 * fill the file one block at a time
520 error
= libxfs_bmapi(tp
, ip
, bno
, 1, XFS_BMAPI_WRITE
,
521 &first
, 1, &map
, &nmap
, NULL
);
522 if (error
|| nmap
!= 1) {
524 "couldn't map realtime summary inode block %llu - err %d\n",
528 ASSERT(map
.br_startblock
!= HOLESTARTBLOCK
);
530 error
= libxfs_trans_read_buf(
532 XFS_FSB_TO_DADDR(mp
, map
.br_startblock
),
533 XFS_FSB_TO_BB(mp
, 1), 1, &bp
);
537 "can't access block %llu (fsbno %llu) of realtime summary inode %llu\n",
538 bno
, map
.br_startblock
, mp
->m_sb
.sb_rsumino
);
542 bcopy(smp
, XFS_BUF_PTR(bp
), mp
->m_sb
.sb_blocksize
);
544 libxfs_trans_log_buf(tp
, bp
, 0, mp
->m_sb
.sb_blocksize
- 1);
546 smp
= (xfs_suminfo_t
*)((__psint_t
)smp
+ mp
->m_sb
.sb_blocksize
);
550 libxfs_trans_commit(tp
, XFS_TRANS_RELEASE_LOG_RES
|XFS_TRANS_SYNC
, 0);
556 mk_rsumino(xfs_mount_t
*mp
)
567 xfs_bmap_free_t flist
;
569 xfs_bmbt_irec_t map
[XFS_BMAP_MAX_NMAP
];
574 tp
= libxfs_trans_alloc(mp
, 0);
576 if ((i
= libxfs_trans_reserve(tp
, 10, XFS_ICHANGE_LOG_RES(mp
), 0,
577 XFS_TRANS_PERM_LOG_RES
, XFS_MKDIR_LOG_COUNT
)))
580 error
= libxfs_trans_iget(mp
, tp
, mp
->m_sb
.sb_rsumino
, 0, &ip
);
582 do_error("couldn't iget realtime summary inode -- error - %d\n",
586 bzero(&ip
->i_d
, sizeof(xfs_dinode_core_t
));
588 ip
->i_d
.di_magic
= XFS_DINODE_MAGIC
;
589 ip
->i_d
.di_mode
= IFREG
;
590 ip
->i_d
.di_version
= XFS_DINODE_VERSION_1
;
591 ip
->i_d
.di_format
= XFS_DINODE_FMT_EXTENTS
;
592 ip
->i_d
.di_aformat
= XFS_DINODE_FMT_EXTENTS
;
594 ip
->i_d
.di_nlink
= 1; /* account for sb ptr */
599 ip
->i_df
.if_flags
= XFS_IFEXTENTS
;
600 ip
->i_df
.if_bytes
= ip
->i_df
.if_real_bytes
= 0;
601 ip
->i_df
.if_u1
.if_extents
= NULL
;
603 ip
->i_d
.di_size
= mp
->m_rsumsize
;
608 libxfs_trans_log_inode(tp
, ip
, XFS_ILOG_CORE
);
609 libxfs_trans_ihold(tp
, ip
);
610 libxfs_trans_commit(tp
, XFS_TRANS_RELEASE_LOG_RES
|XFS_TRANS_SYNC
, 0);
613 * then allocate blocks for file and fill with zeroes (stolen
616 tp
= libxfs_trans_alloc(mp
, 0);
617 XFS_BMAP_INIT(&flist
, &first
);
619 nsumblocks
= mp
->m_rsumsize
>> mp
->m_sb
.sb_blocklog
;
620 if ((error
= libxfs_trans_reserve(tp
,
621 mp
->m_sb
.sb_rbmblocks
+
622 (XFS_BM_MAXLEVELS(mp
, XFS_DATA_FORK
) - 1),
623 BBTOB(128), 0, XFS_TRANS_PERM_LOG_RES
,
624 XFS_DEFAULT_PERM_LOG_COUNT
)))
627 libxfs_trans_ijoin(tp
, ip
, 0);
629 XFS_BMAP_INIT(&flist
, &first
);
630 while (bno
< nsumblocks
) {
631 nmap
= XFS_BMAP_MAX_NMAP
;
632 error
= libxfs_bmapi(tp
, ip
, bno
,
633 (xfs_extlen_t
)(nsumblocks
- bno
),
634 XFS_BMAPI_WRITE
, &first
, nsumblocks
,
638 "couldn't allocate realtime summary inode - err %d\n",
641 for (i
= 0, ep
= map
; i
< nmap
; i
++, ep
++) {
642 libxfs_device_zero(mp
->m_dev
,
643 XFS_FSB_TO_DADDR(mp
, ep
->br_startblock
),
644 XFS_FSB_TO_BB(mp
, ep
->br_blockcount
));
645 do_error("dev_zero of rtbitmap failed\n");
646 bno
+= ep
->br_blockcount
;
649 error
= libxfs_bmap_finish(&tp
, &flist
, first
, &committed
);
652 "allocation of the realtime summary ino failed, err = %d\n",
655 libxfs_trans_commit(tp
, XFS_TRANS_RELEASE_LOG_RES
|XFS_TRANS_SYNC
, 0);
659 * makes a new root directory.
662 mk_root_dir(xfs_mount_t
*mp
)
668 const mode_t mode
= 0755;
670 tp
= libxfs_trans_alloc(mp
, 0);
673 if ((i
= libxfs_trans_reserve(tp
, 10, XFS_ICHANGE_LOG_RES(mp
), 0,
674 XFS_TRANS_PERM_LOG_RES
, XFS_MKDIR_LOG_COUNT
)))
677 error
= libxfs_trans_iget(mp
, tp
, mp
->m_sb
.sb_rootino
, 0, &ip
);
679 do_error("could not iget root inode -- error - %d\n", error
);
683 * take care of the core -- initialization from xfs_ialloc()
685 bzero(&ip
->i_d
, sizeof(xfs_dinode_core_t
));
687 ip
->i_d
.di_magic
= XFS_DINODE_MAGIC
;
688 ip
->i_d
.di_mode
= (__uint16_t
) mode
|IFDIR
;
689 ip
->i_d
.di_version
= XFS_DINODE_VERSION_1
;
690 ip
->i_d
.di_format
= XFS_DINODE_FMT_EXTENTS
;
691 ip
->i_d
.di_aformat
= XFS_DINODE_FMT_EXTENTS
;
693 ip
->i_d
.di_nlink
= 1; /* account for . */
695 libxfs_trans_log_inode(tp
, ip
, XFS_ILOG_CORE
);
700 ip
->i_df
.if_flags
= XFS_IFEXTENTS
;
701 ip
->i_df
.if_bytes
= ip
->i_df
.if_real_bytes
= 0;
702 ip
->i_df
.if_u1
.if_extents
= NULL
;
707 * initialize the directory
709 dir_init(mp
, tp
, ip
, ip
);
711 libxfs_trans_commit(tp
, XFS_TRANS_RELEASE_LOG_RES
|XFS_TRANS_SYNC
, 0);
715 * orphanage name == lost+found
718 mk_orphanage(xfs_mount_t
*mp
)
728 xfs_bmap_free_t flist
;
729 const int mode
= 0755;
734 tp
= libxfs_trans_alloc(mp
, 0);
735 XFS_BMAP_INIT(&flist
, &first
);
737 nres
= XFS_MKDIR_SPACE_RES(mp
, strlen(ORPHANAGE
));
738 if ((i
= libxfs_trans_reserve(tp
, nres
, XFS_MKDIR_LOG_RES(mp
), 0,
739 XFS_TRANS_PERM_LOG_RES
, XFS_MKDIR_LOG_COUNT
)))
743 * use iget/ijoin instead of trans_iget because the ialloc
744 * wrapper can commit the transaction and start a new one
746 if ((i
= libxfs_iget(mp
, NULL
, mp
->m_sb
.sb_rootino
, 0, &pip
, 0)))
747 do_error("%d - couldn't iget root inode to make %s\n",
750 error
= libxfs_inode_alloc(&tp
, pip
, mode
|IFDIR
,
751 1, mp
->m_dev
, &zerocr
, &ip
);
754 do_error("%s inode allocation failed %d\n",
758 ip
->i_d
.di_uid
= uid
;
759 ip
->i_d
.di_gid
= gid
;
760 ip
->i_d
.di_nlink
++; /* account for . */
763 * now that we know the transaction will stay around,
764 * add the root inode to it
766 libxfs_trans_ijoin(tp
, pip
, 0);
769 * create the actual entry
771 if ((error
= dir_createname(mp
, tp
, pip
, ORPHANAGE
,
772 strlen(ORPHANAGE
), ip
->i_ino
, &first
, &flist
, nres
))) {
773 do_warn("can't make %s, createname error %d, will try later\n",
775 orphanage_entered
= 0;
777 orphanage_entered
= 1;
780 * bump up the link count in the root directory to account
781 * for .. in the new directory
785 libxfs_trans_log_inode(tp
, pip
, XFS_ILOG_CORE
);
786 dir_init(mp
, tp
, ip
, pip
);
787 libxfs_trans_log_inode(tp
, ip
, XFS_ILOG_CORE
);
789 error
= libxfs_bmap_finish(&tp
, &flist
, first
, &committed
);
791 do_error("%s directory creation failed -- bmapf error %d\n",
797 libxfs_trans_commit(tp
, XFS_TRANS_RELEASE_LOG_RES
|XFS_TRANS_SYNC
, 0);
799 /* need libxfs_iput here? - nathans TODO - possible memory leak? */
805 * move a file to the orphange. the orphanage is guaranteed
806 * at this point to only have file in it whose name == file inode #
809 mv_orphanage(xfs_mount_t
*mp
,
810 xfs_ino_t dir_ino
, /* orphange inode # */
811 xfs_ino_t ino
, /* inode # to be moved */
812 int isa_dir
) /* 1 if inode is a directory */
814 xfs_ino_t entry_ino_num
;
815 xfs_inode_t
*dir_ino_p
;
819 xfs_bmap_free_t flist
;
822 char fname
[MAXPATHLEN
+ 1];
825 snprintf(fname
, sizeof(fname
), "%llu", (unsigned long long)ino
);
827 if ((err
= libxfs_iget(mp
, NULL
, dir_ino
, 0, &dir_ino_p
, 0)))
828 do_error("%d - couldn't iget orphanage inode\n", err
);
830 tp
= libxfs_trans_alloc(mp
, 0);
832 if ((err
= libxfs_iget(mp
, NULL
, ino
, 0, &ino_p
, 0)))
833 do_error("%d - couldn't iget disconnected inode\n", err
);
836 nres
= XFS_DIRENTER_SPACE_RES(mp
, strlen(fname
)) +
837 XFS_DIRENTER_SPACE_RES(mp
, 2);
838 if ((err
= dir_lookup(mp
, tp
, ino_p
, "..", 2,
840 ASSERT(err
== ENOENT
);
842 if ((err
= libxfs_trans_reserve(tp
, nres
,
843 XFS_RENAME_LOG_RES(mp
), 0,
844 XFS_TRANS_PERM_LOG_RES
,
845 XFS_RENAME_LOG_COUNT
)))
847 "space reservation failed (%d), filesystem may be out of space\n",
850 libxfs_trans_ijoin(tp
, dir_ino_p
, 0);
851 libxfs_trans_ijoin(tp
, ino_p
, 0);
853 XFS_BMAP_INIT(&flist
, &first
);
854 if ((err
= dir_createname(mp
, tp
, dir_ino_p
, fname
,
855 strlen(fname
), ino
, &first
,
858 "name create failed in %s (%d), filesystem may be out of space\n",
861 dir_ino_p
->i_d
.di_nlink
++;
862 libxfs_trans_log_inode(tp
, dir_ino_p
, XFS_ILOG_CORE
);
864 if ((err
= dir_createname(mp
, tp
, ino_p
, "..", 2,
865 dir_ino
, &first
, &flist
, nres
)))
867 "creation of .. entry failed (%d), filesystem may be out of space\n",
870 ino_p
->i_d
.di_nlink
++;
871 libxfs_trans_log_inode(tp
, ino_p
, XFS_ILOG_CORE
);
873 if ((err
= libxfs_bmap_finish(&tp
, &flist
, first
, &committed
)))
875 "bmap finish failed (err - %d), filesystem may be out of space\n",
878 libxfs_trans_commit(tp
,
879 XFS_TRANS_RELEASE_LOG_RES
|XFS_TRANS_SYNC
, 0);
881 if ((err
= libxfs_trans_reserve(tp
, nres
,
882 XFS_RENAME_LOG_RES(mp
), 0,
883 XFS_TRANS_PERM_LOG_RES
,
884 XFS_RENAME_LOG_COUNT
)))
886 "space reservation failed (%d), filesystem may be out of space\n",
889 libxfs_trans_ijoin(tp
, dir_ino_p
, 0);
890 libxfs_trans_ijoin(tp
, ino_p
, 0);
892 XFS_BMAP_INIT(&flist
, &first
);
894 if ((err
= dir_createname(mp
, tp
, dir_ino_p
, fname
,
895 strlen(fname
), ino
, &first
,
898 "name create failed in %s (%d), filesystem may be out of space\n",
901 dir_ino_p
->i_d
.di_nlink
++;
902 libxfs_trans_log_inode(tp
, dir_ino_p
, XFS_ILOG_CORE
);
905 * don't replace .. value if it already points
906 * to us. that'll pop a libxfs/kernel ASSERT.
908 if (entry_ino_num
!= dir_ino
) {
909 if ((err
= dir_replace(mp
, tp
, ino_p
, "..",
913 "name replace op failed (%d), filesystem may be out of space\n",
917 if ((err
= libxfs_bmap_finish(&tp
, &flist
, first
,
920 "bmap finish failed (%d), filesystem may be out of space\n",
923 libxfs_trans_commit(tp
,
924 XFS_TRANS_RELEASE_LOG_RES
|XFS_TRANS_SYNC
, 0);
928 * use the remove log reservation as that's
929 * more accurate. we're only creating the
930 * links, we're not doing the inode allocation
931 * also accounted for in the create
933 nres
= XFS_DIRENTER_SPACE_RES(mp
, strlen(fname
));
934 if ((err
= libxfs_trans_reserve(tp
, nres
, XFS_REMOVE_LOG_RES(mp
), 0,
935 XFS_TRANS_PERM_LOG_RES
, XFS_REMOVE_LOG_COUNT
)))
937 "space reservation failed (%d), filesystem may be out of space\n",
940 libxfs_trans_ijoin(tp
, dir_ino_p
, 0);
941 libxfs_trans_ijoin(tp
, ino_p
, 0);
943 XFS_BMAP_INIT(&flist
, &first
);
944 if ((err
= dir_createname(mp
, tp
, dir_ino_p
, fname
,
945 strlen(fname
), ino
, &first
, &flist
, nres
)))
947 "name create failed in %s (%d), filesystem may be out of space\n",
951 ino_p
->i_d
.di_nlink
= 1;
952 libxfs_trans_log_inode(tp
, ino_p
, XFS_ILOG_CORE
);
954 if ((err
= libxfs_bmap_finish(&tp
, &flist
, first
, &committed
)))
956 "bmap finish failed (%d), filesystem may be out of space\n",
959 libxfs_trans_commit(tp
, XFS_TRANS_RELEASE_LOG_RES
|XFS_TRANS_SYNC
, 0);
964 * like get_first_dblock_fsbno only it uses the simulation code instead
967 * Returns the fsbno of the first (leftmost) block in the directory leaf.
968 * sets *bno to the directory block # corresponding to the returned fsbno.
971 map_first_dblock_fsbno(xfs_mount_t
*mp
,
976 xfs_fsblock_t fblock
;
977 xfs_da_intnode_t
*node
;
988 * traverse down left-side of tree until we hit the
989 * left-most leaf block setting up the btree cursor along
996 fblock
= NULLFSBLOCK
;
1000 error
= libxfs_bmapi(NULL
, ip
, (xfs_fileoff_t
) da_bno
, 1,
1001 XFS_BMAPI_METADATA
, &fblock
, 0,
1003 if (error
|| nmap
!= 1) {
1006 "can't map block %d in %s inode %llu, xfs_bmapi returns %d, nmap = %d\n",
1007 da_bno
, ftype
, ino
, error
, nmap
);
1010 "can't map block %d in %s inode %llu, xfs_bmapi returns %d, nmap = %d\n",
1011 da_bno
, ftype
, ino
, error
, nmap
);
1016 if ((fsbno
= map
.br_startblock
) == HOLESTARTBLOCK
) {
1018 do_error("block %d in %s ino %llu doesn't exist\n",
1019 da_bno
, ftype
, ino
);
1021 do_warn("block %d in %s ino %llu doesn't exist\n",
1022 da_bno
, ftype
, ino
);
1027 if (ip
->i_d
.di_size
<= XFS_LBSIZE(mp
))
1030 if (XFS_SB_VERSION_HASDIRV2(&mp
->m_sb
))
1035 * walk down left side of btree, release buffers as you
1036 * go. if the root block is a leaf (single-level btree),
1041 bp
= libxfs_readbuf(mp
->m_dev
, XFS_FSB_TO_DADDR(mp
, fsbno
),
1042 XFS_FSB_TO_BB(mp
, 1), 0);
1046 "can't read block %u (fsbno %llu) for directory inode %llu\n",
1047 da_bno
, fsbno
, ino
);
1051 node
= (xfs_da_intnode_t
*)XFS_BUF_PTR(bp
);
1053 if (INT_GET(node
->hdr
.info
.magic
, ARCH_CONVERT
) != XFS_DA_NODE_MAGIC
) {
1056 "bad dir/attr magic number in inode %llu, file bno = %u, fsbno = %llu\n",
1057 ino
, da_bno
, fsbno
);
1062 i
= INT_GET(node
->hdr
.level
, ARCH_CONVERT
);
1064 da_bno
= INT_GET(node
->btree
[0].before
, ARCH_CONVERT
);
1070 error
= libxfs_bmapi(NULL
, ip
, (xfs_fileoff_t
) da_bno
, 1,
1071 XFS_BMAPI_METADATA
, &fblock
, 0,
1073 if (error
|| nmap
!= 1) {
1076 "can't map block %d in %s ino %llu, xfs_bmapi returns %d, nmap = %d\n",
1077 da_bno
, ftype
, ino
, error
, nmap
);
1080 "can't map block %d in %s ino %llu, xfs_bmapi returns %d, nmap = %d\n",
1081 da_bno
, ftype
, ino
, error
, nmap
);
1085 if ((fsbno
= map
.br_startblock
) == HOLESTARTBLOCK
) {
1088 "block %d in %s inode %llu doesn't exist\n",
1089 da_bno
, ftype
, ino
);
1092 "block %d in %s inode %llu doesn't exist\n",
1093 da_bno
, ftype
, ino
);
1106 * scan longform directory and prune first bad entry. returns 1 if
1107 * it had to remove something, 0 if it made it all the way through
1108 * the directory. prune_lf_dir_entry does all the necessary bmap calls.
1110 * hashval is an in/out -- starting hashvalue in, hashvalue of the
1111 * deleted entry (if there was one) out
1113 * this routine can NOT be called if running in no modify mode
1116 prune_lf_dir_entry(xfs_mount_t
*mp
, xfs_ino_t ino
, xfs_inode_t
*ip
,
1117 xfs_dahash_t
*hashval
)
1124 xfs_bmap_free_t free_list
;
1125 xfs_fsblock_t first_block
;
1127 xfs_dir_leaf_name_t
*namest
;
1128 xfs_dir_leafblock_t
*leaf
;
1129 xfs_dir_leaf_entry_t
*entry
;
1132 xfs_fsblock_t fblock
;
1135 xfs_bmbt_irec_t map
;
1136 char fname
[MAXNAMELEN
+ 1];
1141 * ok, this is kind of a schizoid routine. we use our
1142 * internal bmapi routines to walk the directory. when
1143 * we find a bogus entry, we release the buffer so
1144 * the simulation code doesn't deadlock and use the
1145 * sim code to remove the entry. That will cause an
1146 * extra bmap traversal to map the block but I think
1147 * that's preferable to hacking the bogus removename
1148 * function to be really different and then trying to
1149 * maintain both versions as time goes on.
1151 * first, grab the dinode and find the right leaf block.
1158 fblock
= NULLFSBLOCK
;
1160 fsbno
= map_first_dblock_fsbno(mp
, ino
, ip
, &da_bno
);
1163 * now go foward along the leaves of the btree looking
1164 * for an entry beginning with '/'
1167 bp
= libxfs_readbuf(mp
->m_dev
, XFS_FSB_TO_DADDR(mp
, fsbno
),
1168 XFS_FSB_TO_BB(mp
, 1), 0);
1172 "can't read directory inode %llu (leaf) block %u (fsbno %llu)\n",
1173 ino
, da_bno
, fsbno
);
1177 leaf
= (xfs_dir_leafblock_t
*)XFS_BUF_PTR(bp
);
1178 ASSERT(INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
) == XFS_DIR_LEAF_MAGIC
);
1179 entry
= &leaf
->entries
[0];
1181 for (index
= -1, i
= 0;
1182 i
< INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
) && index
== -1;
1184 namest
= XFS_DIR_LEAF_NAMESTRUCT(leaf
, INT_GET(entry
->nameidx
, ARCH_CONVERT
));
1185 if (namest
->name
[0] != '/')
1192 * if we got a bogus entry, exit loop with a pointer to
1193 * the leaf block buffer. otherwise, keep trying blocks
1195 da_bno
= INT_GET(leaf
->hdr
.info
.forw
, ARCH_CONVERT
);
1204 * map next leaf block unless we've run out
1208 error
= libxfs_bmapi(NULL
, ip
,
1209 (xfs_fileoff_t
) da_bno
, 1,
1210 XFS_BMAPI_METADATA
, &fblock
, 0,
1212 if (error
|| nmap
!= 1)
1214 "can't map block %d in directory %llu, xfs_bmapi returns %d, nmap = %d\n",
1215 da_bno
, ino
, error
, nmap
);
1216 if ((fsbno
= map
.br_startblock
)
1217 == HOLESTARTBLOCK
) {
1219 "%s ino %llu block %d doesn't exist\n",
1220 ftype
, ino
, da_bno
);
1224 } while (da_bno
!= 0 && index
== -1);
1227 * if we hit the edge of the tree with no bad entries, we're done
1228 * and the buffer was released.
1230 if (da_bno
== 0 && index
== -1)
1234 ASSERT(entry
== &leaf
->entries
[index
]);
1235 ASSERT(namest
== XFS_DIR_LEAF_NAMESTRUCT(leaf
, INT_GET(entry
->nameidx
, ARCH_CONVERT
)));
1238 * snag the info we need out of the directory then release all buffers
1240 bcopy(namest
->name
, fname
, entry
->namelen
);
1241 fname
[entry
->namelen
] = '\0';
1242 *hashval
= INT_GET(entry
->hashval
, ARCH_CONVERT
);
1243 namelen
= entry
->namelen
;
1248 * ok, now the hard part, blow away the index'th entry in this block
1250 * allocate a remove transaction for it. that's not quite true since
1251 * we're only messing with one inode, not two but...
1254 tp
= libxfs_trans_alloc(mp
, XFS_TRANS_REMOVE
);
1256 nres
= XFS_REMOVE_SPACE_RES(mp
);
1257 error
= libxfs_trans_reserve(tp
, nres
, XFS_REMOVE_LOG_RES(mp
),
1258 0, XFS_TRANS_PERM_LOG_RES
,
1259 XFS_REMOVE_LOG_COUNT
);
1263 libxfs_trans_ijoin(tp
, ip
, 0);
1264 libxfs_trans_ihold(tp
, ip
);
1266 XFS_BMAP_INIT(&free_list
, &first_block
);
1268 error
= dir_bogus_removename(mp
, tp
, ip
, fname
,
1269 &first_block
, &free_list
, nres
, *hashval
, namelen
);
1273 "couldn't remove bogus entry \"%s\" in\n\tdirectory inode %llu, errno = %d\n",
1278 error
= libxfs_bmap_finish(&tp
, &free_list
, first_block
, &committed
);
1282 libxfs_trans_commit(tp
, XFS_TRANS_RELEASE_LOG_RES
|XFS_TRANS_SYNC
, 0);
1288 * process a leaf block, also checks for .. entry
1289 * and corrects it to match what we think .. should be
1292 lf_block_dir_entry_check(xfs_mount_t
*mp
,
1294 xfs_dir_leafblock_t
*leaf
,
1299 ino_tree_node_t
*current_irec
,
1300 int current_ino_offset
)
1302 xfs_dir_leaf_entry_t
*entry
;
1303 ino_tree_node_t
*irec
;
1306 xfs_dir_leaf_name_t
*namest
;
1311 char fname
[MAXNAMELEN
+ 1];
1313 entry
= &leaf
->entries
[0];
1318 * look at each entry. reference inode pointed to by each
1319 * entry in the incore inode tree.
1320 * if not a directory, set reached flag, increment link count
1321 * if a directory and reached, mark entry as to be deleted.
1322 * if a directory, check to see if recorded parent
1323 * matches current inode #,
1324 * if so, then set reached flag, increment link count
1325 * of current and child dir inodes, push the child
1326 * directory inode onto the directory stack.
1327 * if current inode != parent, then mark entry to be deleted.
1331 for (i
= 0; i
< INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
); entry
++, i
++) {
1333 * snag inode #, update link counts, and make sure
1334 * this isn't a loop if the child is a directory
1336 namest
= XFS_DIR_LEAF_NAMESTRUCT(leaf
, INT_GET(entry
->nameidx
, ARCH_CONVERT
));
1339 * skip bogus entries (leading '/'). they'll be deleted
1342 if (namest
->name
[0] == '/') {
1349 XFS_DIR_SF_GET_DIRINO_ARCH(&namest
->inumber
, &lino
, ARCH_CONVERT
);
1350 bcopy(namest
->name
, fname
, entry
->namelen
);
1351 fname
[entry
->namelen
] = '\0';
1353 ASSERT(lino
!= NULLFSINO
);
1356 * skip the '..' entry since it's checked when the
1357 * directory is reached by something else. if it never
1358 * gets reached, it'll be moved to the orphanage and we'll
1359 * take care of it then.
1361 if (entry
->namelen
== 2 && namest
->name
[0] == '.' &&
1362 namest
->name
[1] == '.') {
1365 ASSERT(no_modify
|| !verify_inum(mp
, lino
));
1368 * special case the . entry. we know there's only one
1369 * '.' and only '.' points to itself because bogus entries
1370 * got trashed in phase 3 if there were > 1.
1371 * bump up link count for '.' but don't set reached
1372 * until we're actually reached by another directory
1373 * '..' is already accounted for or will be taken care
1374 * of when directory is moved to orphanage.
1377 ASSERT(namest
->name
[0] == '.' && entry
->namelen
== 1);
1378 add_inode_ref(current_irec
, current_ino_offset
);
1384 * special case the "lost+found" entry if pointing
1385 * to where we think lost+found should be. if that's
1386 * the case, that's the one we created in phase 6.
1387 * just skip it. no need to process it and it's ..
1388 * link is already accounted for.
1391 if (lino
== orphanage_ino
&& strcmp(fname
, ORPHANAGE
) == 0)
1395 * skip entries with bogus inumbers if we're in no modify mode
1397 if (no_modify
&& verify_inum(mp
, lino
))
1401 * ok, now handle the rest of the cases besides '.' and '..'
1403 irec
= find_inode_rec(XFS_INO_TO_AGNO(mp
, lino
),
1404 XFS_INO_TO_AGINO(mp
, lino
));
1409 "entry \"%s\" in dir inode %llu points to non-existent inode, ",
1413 namest
->name
[0] = '/';
1415 do_warn("marking entry to be junked\n");
1417 do_warn("would junk entry\n");
1423 ino_offset
= XFS_INO_TO_AGINO(mp
, lino
) - irec
->ino_startnum
;
1426 * if it's a free inode, blow out the entry.
1427 * by now, any inode that we think is free
1430 if (is_inode_free(irec
, ino_offset
)) {
1432 * don't complain if this entry points to the old
1433 * and now-free lost+found inode
1435 if (verbose
|| no_modify
|| lino
!= old_orphanage_ino
)
1437 "entry \"%s\" in dir inode %llu points to free inode %llu",
1442 if (verbose
|| lino
!= old_orphanage_ino
)
1443 do_warn(", marking entry to be junked\n");
1447 namest
->name
[0] = '/';
1450 do_warn(", would junk entry\n");
1457 * check easy case first, regular inode, just bump
1458 * the link count and continue
1460 if (!inode_isadir(irec
, ino_offset
)) {
1461 add_inode_reached(irec
, ino_offset
);
1465 parent
= get_inode_parent(irec
, ino_offset
);
1466 ASSERT(parent
!= 0);
1469 * bump up the link counts in parent and child
1470 * directory but if the link doesn't agree with
1471 * the .. in the child, blow out the entry.
1472 * if the directory has already been reached,
1473 * blow away the entry also.
1475 if (is_inode_reached(irec
, ino_offset
)) {
1478 "entry \"%s\" in dir %llu points to an already connected dir inode %llu,\n",
1480 } else if (parent
== ino
) {
1481 add_inode_reached(irec
, ino_offset
);
1482 add_inode_ref(current_irec
, current_ino_offset
);
1484 if (!is_inode_refchecked(lino
, irec
, ino_offset
))
1485 push_dir(stack
, lino
);
1489 "entry \"%s\" in dir ino %llu not consistent with .. value (%llu) in ino %llu,\n",
1490 fname
, ino
, parent
, lino
);
1498 namest
->name
[0] = '/';
1500 if (verbose
|| lino
!= old_orphanage_ino
)
1501 do_warn("\twill clear entry \"%s\"\n",
1504 do_warn("\twould clear entry \"%s\"\n", fname
);
1509 *num_illegal
+= nbad
;
1513 * succeeds or dies, inode never gets dirtied since all changes
1514 * happen in file blocks. the inode size and other core info
1515 * is already correct, it's just the leaf entries that get altered.
1518 longform_dir_entry_check(xfs_mount_t
*mp
,
1524 ino_tree_node_t
*irec
,
1527 xfs_dir_leafblock_t
*leaf
;
1530 xfs_fsblock_t fblock
;
1536 xfs_bmbt_irec_t map
;
1540 fblock
= NULLFSBLOCK
;
1544 fsbno
= map_first_dblock_fsbno(mp
, ino
, ip
, &da_bno
);
1546 if (fsbno
== NULLDFSBNO
&& no_modify
) {
1547 do_warn("cannot map block 0 of directory inode %llu\n", ino
);
1552 ASSERT(fsbno
!= NULLDFSBNO
);
1555 bp
= libxfs_readbuf(mp
->m_dev
, XFS_FSB_TO_DADDR(mp
, fsbno
),
1556 XFS_FSB_TO_BB(mp
, 1), 0);
1560 "can't read block %u (fsbno %llu) for directory inode %llu\n",
1561 da_bno
, fsbno
, ino
);
1565 leaf
= (xfs_dir_leafblock_t
*)XFS_BUF_PTR(bp
);
1567 da_bno
= INT_GET(leaf
->hdr
.info
.forw
, ARCH_CONVERT
);
1569 if (INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
) != XFS_DIR_LEAF_MAGIC
) {
1572 "bad magic # (0x%x) for dir ino %llu leaf block (bno %u fsbno %llu)\n",
1573 INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
),
1574 ino
, da_bno
, fsbno
);
1578 * this block's bad but maybe the
1579 * forward pointer is good...
1587 lf_block_dir_entry_check(mp
, ino
, leaf
, &dirty
,
1588 num_illegal
, need_dot
, stack
,
1591 ASSERT(dirty
== 0 || (dirty
&& !no_modify
));
1593 if (dirty
&& !no_modify
)
1594 libxfs_writebuf(bp
, 0);
1601 error
= libxfs_bmapi(NULL
, ip
, (xfs_fileoff_t
)da_bno
, 1,
1602 XFS_BMAPI_METADATA
, &fblock
, 0,
1604 if (error
|| nmap
!= 1) {
1607 "can't map leaf block %d in dir %llu, xfs_bmapi returns %d, nmap = %d\n",
1608 da_bno
, ino
, error
, nmap
);
1611 "can't map leaf block %d in dir %llu, xfs_bmapi returns %d, nmap = %d\n",
1612 da_bno
, ino
, error
, nmap
);
1616 if ((fsbno
= map
.br_startblock
) == HOLESTARTBLOCK
) {
1619 "block %d in %s ino %llu doesn't exist\n",
1620 da_bno
, ftype
, ino
);
1623 "block %d in %s ino %llu doesn't exist\n",
1624 da_bno
, ftype
, ino
);
1629 } while (da_bno
!= 0);
1633 * Kill a block in a version 2 inode.
1634 * Makes its own transaction.
1646 xfs_fsblock_t firstblock
;
1647 xfs_bmap_free_t flist
;
1651 tp
= libxfs_trans_alloc(mp
, 0);
1652 nres
= XFS_REMOVE_SPACE_RES(mp
);
1653 error
= libxfs_trans_reserve(tp
, nres
, XFS_REMOVE_LOG_RES(mp
), 0,
1654 XFS_TRANS_PERM_LOG_RES
, XFS_REMOVE_LOG_COUNT
);
1657 libxfs_trans_ijoin(tp
, ip
, 0);
1658 libxfs_trans_ihold(tp
, ip
);
1659 libxfs_da_bjoin(tp
, bp
);
1660 bzero(&args
, sizeof(args
));
1661 XFS_BMAP_INIT(&flist
, &firstblock
);
1664 args
.firstblock
= &firstblock
;
1665 args
.flist
= &flist
;
1666 args
.whichfork
= XFS_DATA_FORK
;
1667 if (da_bno
>= mp
->m_dirleafblk
&& da_bno
< mp
->m_dirfreeblk
)
1668 error
= libxfs_da_shrink_inode(&args
, da_bno
, bp
);
1670 error
= libxfs_dir2_shrink_inode(&args
,
1671 XFS_DIR2_DA_TO_DB(mp
, da_bno
), bp
);
1673 do_error("shrink_inode failed inode %llu block %u\n",
1675 libxfs_bmap_finish(&tp
, &flist
, firstblock
, &committed
);
1676 libxfs_trans_commit(tp
, 0, 0);
1680 * process a data block, also checks for .. entry
1681 * and corrects it to match what we think .. should be
1684 longform_dir2_entry_check_data(
1690 ino_tree_node_t
*current_irec
,
1691 int current_ino_offset
,
1693 dir_hash_tab_t
*hashtab
,
1694 freetab_t
**freetabp
,
1698 xfs_dir2_dataptr_t addr
;
1699 xfs_dir2_leaf_entry_t
*blp
;
1701 xfs_dir2_block_tail_t
*btp
;
1705 xfs_dir2_data_entry_t
*dep
;
1706 xfs_dir2_data_unused_t
*dup
;
1709 xfs_fsblock_t firstblock
;
1710 xfs_bmap_free_t flist
;
1711 char fname
[MAXNAMELEN
+ 1];
1715 ino_tree_node_t
*irec
;
1731 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
);
1747 /* check for data block beyond expected end */
1748 if (freetab
->naents
<= db
) {
1749 struct freetab_ent e
;
1751 *freetabp
= freetab
= realloc(freetab
, FREETAB_SIZE(db
+ 1));
1754 "realloc failed in longform_dir2_entry_check_data (%u bytes)\n",
1755 FREETAB_SIZE(db
+ 1));
1760 for (i
= freetab
->naents
; i
< db
; i
++)
1761 freetab
->ents
[i
] = e
;
1762 freetab
->naents
= db
+ 1;
1765 /* check the data block */
1766 while (ptr
< endptr
) {
1768 /* check for freespace */
1769 dup
= (xfs_dir2_data_unused_t
*)ptr
;
1770 if (XFS_DIR2_DATA_FREE_TAG
==
1771 INT_GET(dup
->freetag
, ARCH_CONVERT
)) {
1773 /* check for invalid freespace length */
1774 if (ptr
+ INT_GET(dup
->length
, ARCH_CONVERT
) > endptr
||
1775 INT_GET(dup
->length
, ARCH_CONVERT
) == 0 ||
1776 (INT_GET(dup
->length
, ARCH_CONVERT
) &
1777 (XFS_DIR2_DATA_ALIGN
- 1)))
1780 /* check for invalid tag */
1781 if (INT_GET(*XFS_DIR2_DATA_UNUSED_TAG_P_ARCH(
1782 dup
, ARCH_CONVERT
), ARCH_CONVERT
) !=
1783 (char *)dup
- (char *)d
)
1786 /* check for block with no data entries */
1787 if ((ptr
== (char *)d
->u
) &&
1788 (ptr
+ INT_GET(dup
->length
, ARCH_CONVERT
) >=
1795 /* continue at the end of the freespace */
1796 ptr
+= INT_GET(dup
->length
, ARCH_CONVERT
);
1801 /* validate data entry size */
1802 dep
= (xfs_dir2_data_entry_t
*)ptr
;
1803 if (ptr
+ XFS_DIR2_DATA_ENTSIZE(dep
->namelen
) > endptr
)
1805 if (INT_GET(*XFS_DIR2_DATA_ENTRY_TAG_P(dep
), ARCH_CONVERT
) !=
1806 (char *)dep
- (char *)d
)
1808 ptr
+= XFS_DIR2_DATA_ENTSIZE(dep
->namelen
);
1811 /* did we find an empty or corrupt block? */
1812 if (ptr
!= endptr
) {
1814 do_warn("empty data block %u in directory inode %llu: ",
1817 do_warn("corrupt block %u in directory inode %llu: ",
1821 do_warn("junking block\n");
1822 dir2_kill_block(mp
, ip
, da_bno
, bp
);
1824 do_warn("would junk block\n");
1825 libxfs_da_brelse(NULL
, bp
);
1827 freetab
->ents
[db
].v
= NULLDATAOFF
;
1832 /* update number of data blocks processed */
1833 if (freetab
->nents
< db
+ 1)
1834 freetab
->nents
= db
+ 1;
1836 tp
= libxfs_trans_alloc(mp
, 0);
1837 error
= libxfs_trans_reserve(tp
, 0, XFS_REMOVE_LOG_RES(mp
), 0,
1838 XFS_TRANS_PERM_LOG_RES
, XFS_REMOVE_LOG_COUNT
);
1841 libxfs_trans_ijoin(tp
, ip
, 0);
1842 libxfs_trans_ihold(tp
, ip
);
1843 libxfs_da_bjoin(tp
, bp
);
1845 libxfs_da_bhold(tp
, bp
);
1846 XFS_BMAP_INIT(&flist
, &firstblock
);
1847 if (INT_GET(d
->hdr
.magic
, ARCH_CONVERT
) != wantmagic
) {
1848 do_warn("bad directory block magic # %#x for directory inode "
1850 INT_GET(d
->hdr
.magic
, ARCH_CONVERT
), ip
->i_ino
, da_bno
);
1852 do_warn("fixing magic # to %#x\n", wantmagic
);
1853 INT_SET(d
->hdr
.magic
, ARCH_CONVERT
, wantmagic
);
1856 do_warn("would fix magic # to %#x\n", wantmagic
);
1861 * look at each entry. reference inode pointed to by each
1862 * entry in the incore inode tree.
1863 * if not a directory, set reached flag, increment link count
1864 * if a directory and reached, mark entry as to be deleted.
1865 * if a directory, check to see if recorded parent
1866 * matches current inode #,
1867 * if so, then set reached flag, increment link count
1868 * of current and child dir inodes, push the child
1869 * directory inode onto the directory stack.
1870 * if current inode != parent, then mark entry to be deleted.
1872 while (ptr
< endptr
) {
1873 dup
= (xfs_dir2_data_unused_t
*)ptr
;
1874 if (INT_GET(dup
->freetag
, ARCH_CONVERT
) == XFS_DIR2_DATA_FREE_TAG
) {
1876 do_warn("directory inode %llu block %u has "
1877 "consecutive free entries: ",
1880 do_warn("joining together\n");
1881 len
= INT_GET(dup
->length
, ARCH_CONVERT
);
1882 libxfs_dir2_data_use_free(tp
, bp
, dup
,
1883 ptr
- (char *)d
, len
, &needlog
,
1885 libxfs_dir2_data_make_free(tp
, bp
,
1886 ptr
- (char *)d
, len
, &needlog
,
1889 do_warn("would join together\n");
1891 ptr
+= INT_GET(dup
->length
, ARCH_CONVERT
);
1895 addr
= XFS_DIR2_DB_OFF_TO_DATAPTR(mp
, db
, ptr
- (char *)d
);
1896 dep
= (xfs_dir2_data_entry_t
*)ptr
;
1897 ptr
+= XFS_DIR2_DATA_ENTSIZE(dep
->namelen
);
1899 dir_hash_add(hashtab
,
1900 libxfs_da_hashname((char *)dep
->name
, dep
->namelen
),
1901 addr
, dep
->name
[0] == '/');
1903 * skip bogus entries (leading '/'). they'll be deleted
1906 if (dep
->name
[0] == '/') {
1911 bcopy(dep
->name
, fname
, dep
->namelen
);
1912 fname
[dep
->namelen
] = '\0';
1913 ASSERT(INT_GET(dep
->inumber
, ARCH_CONVERT
) != NULLFSINO
);
1915 * skip the '..' entry since it's checked when the
1916 * directory is reached by something else. if it never
1917 * gets reached, it'll be moved to the orphanage and we'll
1918 * take care of it then.
1920 if (dep
->namelen
== 2 && dep
->name
[0] == '.' &&
1921 dep
->name
[1] == '.')
1923 ASSERT(no_modify
|| !verify_inum(mp
, INT_GET(dep
->inumber
, ARCH_CONVERT
)));
1925 * special case the . entry. we know there's only one
1926 * '.' and only '.' points to itself because bogus entries
1927 * got trashed in phase 3 if there were > 1.
1928 * bump up link count for '.' but don't set reached
1929 * until we're actually reached by another directory
1930 * '..' is already accounted for or will be taken care
1931 * of when directory is moved to orphanage.
1933 if (ip
->i_ino
== INT_GET(dep
->inumber
, ARCH_CONVERT
)) {
1934 ASSERT(dep
->name
[0] == '.' && dep
->namelen
== 1);
1935 add_inode_ref(current_irec
, current_ino_offset
);
1940 * special case the "lost+found" entry if pointing
1941 * to where we think lost+found should be. if that's
1942 * the case, that's the one we created in phase 6.
1943 * just skip it. no need to process it and it's ..
1944 * link is already accounted for.
1946 if (INT_GET(dep
->inumber
, ARCH_CONVERT
) == orphanage_ino
&&
1947 strcmp(fname
, ORPHANAGE
) == 0)
1950 * skip entries with bogus inumbers if we're in no modify mode
1952 if (no_modify
&& verify_inum(mp
, INT_GET(dep
->inumber
, ARCH_CONVERT
)))
1955 * ok, now handle the rest of the cases besides '.' and '..'
1957 irec
= find_inode_rec(XFS_INO_TO_AGNO(mp
, INT_GET(dep
->inumber
, ARCH_CONVERT
)),
1958 XFS_INO_TO_AGINO(mp
, INT_GET(dep
->inumber
, ARCH_CONVERT
)));
1961 do_warn("entry \"%s\" in directory inode %llu points "
1962 "to non-existent inode, ",
1966 libxfs_dir2_data_log_entry(tp
, bp
, dep
);
1967 do_warn("marking entry to be junked\n");
1969 do_warn("would junk entry\n");
1974 XFS_INO_TO_AGINO(mp
, INT_GET(dep
->inumber
, ARCH_CONVERT
)) - irec
->ino_startnum
;
1976 * if it's a free inode, blow out the entry.
1977 * by now, any inode that we think is free
1980 if (is_inode_free(irec
, ino_offset
)) {
1982 * don't complain if this entry points to the old
1983 * and now-free lost+found inode
1985 if (verbose
|| no_modify
||
1986 INT_GET(dep
->inumber
, ARCH_CONVERT
) != old_orphanage_ino
)
1987 do_warn("entry \"%s\" in directory inode %llu "
1988 "points to free inode %llu",
1989 fname
, ip
->i_ino
, INT_GET(dep
->inumber
, ARCH_CONVERT
));
1993 INT_GET(dep
->inumber
, ARCH_CONVERT
) != old_orphanage_ino
)
1994 do_warn(", marking entry to be "
1999 libxfs_dir2_data_log_entry(tp
, bp
, dep
);
2001 do_warn(", would junk entry\n");
2006 * check easy case first, regular inode, just bump
2007 * the link count and continue
2009 if (!inode_isadir(irec
, ino_offset
)) {
2010 add_inode_reached(irec
, ino_offset
);
2013 parent
= get_inode_parent(irec
, ino_offset
);
2014 ASSERT(parent
!= 0);
2016 * bump up the link counts in parent and child
2017 * directory but if the link doesn't agree with
2018 * the .. in the child, blow out the entry.
2019 * if the directory has already been reached,
2020 * blow away the entry also.
2022 if (is_inode_reached(irec
, ino_offset
)) {
2024 do_warn("entry \"%s\" in dir %llu points to an already "
2025 "connected directory inode %llu,\n", fname
,
2026 ip
->i_ino
, INT_GET(dep
->inumber
, ARCH_CONVERT
));
2027 } else if (parent
== ip
->i_ino
) {
2028 add_inode_reached(irec
, ino_offset
);
2029 add_inode_ref(current_irec
, current_ino_offset
);
2030 if (!is_inode_refchecked(INT_GET(dep
->inumber
, ARCH_CONVERT
), irec
,
2032 push_dir(stack
, INT_GET(dep
->inumber
, ARCH_CONVERT
));
2035 do_warn("entry \"%s\" in directory inode %llu not "
2036 "consistent with .. value (%llu) in ino "
2038 fname
, ip
->i_ino
, parent
, INT_GET(dep
->inumber
, ARCH_CONVERT
));
2045 libxfs_dir2_data_log_entry(tp
, bp
, dep
);
2047 INT_GET(dep
->inumber
, ARCH_CONVERT
) != old_orphanage_ino
)
2048 do_warn("\twill clear entry \"%s\"\n",
2051 do_warn("\twould clear entry \"%s\"\n", fname
);
2055 *num_illegal
+= nbad
;
2057 libxfs_dir2_data_freescan(mp
, d
, &needlog
, NULL
);
2059 libxfs_dir2_data_log_header(tp
, bp
);
2060 libxfs_bmap_finish(&tp
, &flist
, firstblock
, &committed
);
2061 libxfs_trans_commit(tp
, 0, 0);
2062 freetab
->ents
[db
].v
= INT_GET(d
->hdr
.bestfree
[0].length
, ARCH_CONVERT
);
2063 freetab
->ents
[db
].s
= 0;
2067 * Check contents of leaf-form block.
2070 longform_dir2_check_leaf(
2073 dir_hash_tab_t
*hashtab
,
2077 xfs_dir2_data_off_t
*bestsp
;
2081 xfs_dir2_leaf_t
*leaf
;
2082 xfs_dir2_leaf_tail_t
*ltp
;
2085 da_bno
= mp
->m_dirleafblk
;
2086 if (libxfs_da_read_bufr(NULL
, ip
, da_bno
, -1, &bp
, XFS_DATA_FORK
)) {
2087 do_error("can't read block %u for directory inode %llu\n",
2092 ltp
= XFS_DIR2_LEAF_TAIL_P(mp
, leaf
);
2093 bestsp
= XFS_DIR2_LEAF_BESTS_P_ARCH(ltp
, ARCH_CONVERT
);
2094 if (INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
) != XFS_DIR2_LEAF1_MAGIC
||
2095 INT_GET(leaf
->hdr
.info
.forw
, ARCH_CONVERT
) || INT_GET(leaf
->hdr
.info
.back
, ARCH_CONVERT
) ||
2096 INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
) < INT_GET(leaf
->hdr
.stale
, ARCH_CONVERT
) ||
2097 INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
) > XFS_DIR2_MAX_LEAF_ENTS(mp
) ||
2098 (char *)&leaf
->ents
[INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
)] > (char *)bestsp
) {
2099 do_warn("leaf block %u for directory inode %llu bad header\n",
2101 libxfs_da_brelse(NULL
, bp
);
2104 seeval
= dir_hash_see_all(hashtab
, leaf
->ents
, INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
),
2105 INT_GET(leaf
->hdr
.stale
, ARCH_CONVERT
));
2106 if (dir_hash_check(hashtab
, ip
, seeval
)) {
2107 libxfs_da_brelse(NULL
, bp
);
2110 badtail
= freetab
->nents
!= INT_GET(ltp
->bestcount
, ARCH_CONVERT
);
2111 for (i
= 0; !badtail
&& i
< INT_GET(ltp
->bestcount
, ARCH_CONVERT
); i
++) {
2112 freetab
->ents
[i
].s
= 1;
2113 badtail
= freetab
->ents
[i
].v
!= INT_GET(bestsp
[i
], ARCH_CONVERT
);
2116 do_warn("leaf block %u for directory inode %llu bad tail\n",
2118 libxfs_da_brelse(NULL
, bp
);
2121 libxfs_da_brelse(NULL
, bp
);
2126 * Check contents of the node blocks (leaves)
2127 * Looks for matching hash values for the data entries.
2130 longform_dir2_check_node(
2133 dir_hash_tab_t
*hashtab
,
2139 xfs_dir2_free_t
*free
;
2141 xfs_dir2_leaf_t
*leaf
;
2142 xfs_fileoff_t next_da_bno
;
2146 for (da_bno
= mp
->m_dirleafblk
, next_da_bno
= 0;
2147 next_da_bno
!= NULLFILEOFF
&& da_bno
< mp
->m_dirfreeblk
;
2148 da_bno
= (xfs_dablk_t
)next_da_bno
) {
2149 next_da_bno
= da_bno
+ mp
->m_dirblkfsbs
- 1;
2150 if (libxfs_bmap_next_offset(NULL
, ip
, &next_da_bno
, XFS_DATA_FORK
))
2152 if (libxfs_da_read_bufr(NULL
, ip
, da_bno
, -1, &bp
,
2154 do_error("can't read block %u for directory inode "
2160 if (INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
) != XFS_DIR2_LEAFN_MAGIC
) {
2161 if (INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
) == XFS_DA_NODE_MAGIC
) {
2162 libxfs_da_brelse(NULL
, bp
);
2165 do_warn("unknown magic number %#x for block %u in "
2166 "directory inode %llu\n",
2167 INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
), da_bno
, ip
->i_ino
);
2168 libxfs_da_brelse(NULL
, bp
);
2171 if (INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
) < INT_GET(leaf
->hdr
.stale
, ARCH_CONVERT
) ||
2172 INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
) > XFS_DIR2_MAX_LEAF_ENTS(mp
)) {
2173 do_warn("leaf block %u for directory inode %llu bad "
2176 libxfs_da_brelse(NULL
, bp
);
2179 seeval
= dir_hash_see_all(hashtab
, leaf
->ents
, INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
),
2180 INT_GET(leaf
->hdr
.stale
, ARCH_CONVERT
));
2181 libxfs_da_brelse(NULL
, bp
);
2182 if (seeval
!= DIR_HASH_CK_OK
)
2185 if (dir_hash_check(hashtab
, ip
, seeval
))
2187 for (da_bno
= mp
->m_dirfreeblk
, next_da_bno
= 0;
2188 next_da_bno
!= NULLFILEOFF
;
2189 da_bno
= (xfs_dablk_t
)next_da_bno
) {
2190 next_da_bno
= da_bno
+ mp
->m_dirblkfsbs
- 1;
2191 if (libxfs_bmap_next_offset(NULL
, ip
, &next_da_bno
, XFS_DATA_FORK
))
2193 if (libxfs_da_read_bufr(NULL
, ip
, da_bno
, -1, &bp
,
2195 do_error("can't read block %u for directory inode "
2201 fdb
= XFS_DIR2_DA_TO_DB(mp
, da_bno
);
2202 if (INT_GET(free
->hdr
.magic
, ARCH_CONVERT
) != XFS_DIR2_FREE_MAGIC
||
2203 INT_GET(free
->hdr
.firstdb
, ARCH_CONVERT
) !=
2204 (fdb
- XFS_DIR2_FREE_FIRSTDB(mp
)) *
2205 XFS_DIR2_MAX_FREE_BESTS(mp
) ||
2206 INT_GET(free
->hdr
.nvalid
, ARCH_CONVERT
) < INT_GET(free
->hdr
.nused
, ARCH_CONVERT
)) {
2207 do_warn("free block %u for directory inode %llu bad "
2210 libxfs_da_brelse(NULL
, bp
);
2213 for (i
= used
= 0; i
< INT_GET(free
->hdr
.nvalid
, ARCH_CONVERT
); i
++) {
2214 if (i
+ INT_GET(free
->hdr
.firstdb
, ARCH_CONVERT
) >= freetab
->nents
||
2215 freetab
->ents
[i
+ INT_GET(free
->hdr
.firstdb
, ARCH_CONVERT
)].v
!=
2216 INT_GET(free
->bests
[i
], ARCH_CONVERT
)) {
2217 do_warn("free block %u entry %i for directory "
2219 da_bno
, i
, ip
->i_ino
);
2220 libxfs_da_brelse(NULL
, bp
);
2223 used
+= INT_GET(free
->bests
[i
], ARCH_CONVERT
) != NULLDATAOFF
;
2224 freetab
->ents
[i
+ INT_GET(free
->hdr
.firstdb
, ARCH_CONVERT
)].s
= 1;
2226 if (used
!= INT_GET(free
->hdr
.nused
, ARCH_CONVERT
)) {
2227 do_warn("free block %u for directory inode %llu bad "
2230 libxfs_da_brelse(NULL
, bp
);
2233 libxfs_da_brelse(NULL
, bp
);
2235 for (i
= 0; i
< freetab
->nents
; i
++) {
2236 if (freetab
->ents
[i
].s
== 0) {
2237 do_warn("missing freetab entry %u for directory inode "
2247 * Rebuild a directory: set up.
2248 * Turn it into a node-format directory with no contents in the
2249 * upper area. Also has correct freespace blocks.
2252 longform_dir2_rebuild_setup(
2260 xfs_dir2_data_t
*data
= NULL
;
2265 xfs_fsblock_t firstblock
;
2266 xfs_bmap_free_t flist
;
2267 xfs_dir2_free_t
*free
;
2272 xfs_dir2_leaf_t
*leaf
;
2276 /* read first directory block */
2277 tp
= libxfs_trans_alloc(mp
, 0);
2278 nres
= XFS_DAENTER_SPACE_RES(mp
, XFS_DATA_FORK
);
2279 error
= libxfs_trans_reserve(tp
,
2280 nres
, XFS_CREATE_LOG_RES(mp
), 0, XFS_TRANS_PERM_LOG_RES
,
2281 XFS_CREATE_LOG_COUNT
);
2284 libxfs_trans_ijoin(tp
, ip
, 0);
2285 libxfs_trans_ihold(tp
, ip
);
2286 XFS_BMAP_INIT(&flist
, &firstblock
);
2287 if (libxfs_da_read_buf(tp
, ip
, mp
->m_dirdatablk
, -2, &dbp
,
2289 do_error("can't read block %u for directory inode %llu\n",
2290 mp
->m_dirdatablk
, ino
);
2297 /* check for block format directory */
2299 INT_GET((data
)->hdr
.magic
, ARCH_CONVERT
) == XFS_DIR2_BLOCK_MAGIC
) {
2300 xfs_dir2_block_t
*block
;
2301 xfs_dir2_leaf_entry_t
*blp
;
2302 xfs_dir2_block_tail_t
*btp
;
2306 /* convert directory block from block format to data format */
2307 INT_SET(data
->hdr
.magic
, ARCH_CONVERT
, XFS_DIR2_DATA_MAGIC
);
2309 /* construct freelist */
2310 block
= (xfs_dir2_block_t
*)data
;
2311 btp
= XFS_DIR2_BLOCK_TAIL_P(mp
, block
);
2312 blp
= XFS_DIR2_BLOCK_LEAF_P_ARCH(btp
, ARCH_CONVERT
);
2313 needlog
= needscan
= 0;
2314 libxfs_dir2_data_make_free(tp
, dbp
, (char *)blp
- (char *)block
,
2315 (char *)block
+ mp
->m_dirblksize
- (char *)blp
,
2316 &needlog
, &needscan
);
2318 libxfs_dir2_data_freescan(mp
, data
, &needlog
, NULL
);
2319 libxfs_da_log_buf(tp
, dbp
, 0, mp
->m_dirblksize
- 1);
2322 /* allocate blocks for btree */
2323 bzero(&args
, sizeof(args
));
2326 args
.whichfork
= XFS_DATA_FORK
;
2327 args
.firstblock
= &firstblock
;
2328 args
.flist
= &flist
;
2330 if ((error
= libxfs_da_grow_inode(&args
, &lblkno
)) ||
2331 (error
= libxfs_da_get_buf(tp
, ip
, lblkno
, -1, &lbp
, XFS_DATA_FORK
))) {
2332 do_error("can't add btree block to directory inode %llu\n",
2337 bzero(leaf
, mp
->m_dirblksize
);
2338 INT_SET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
, XFS_DIR2_LEAFN_MAGIC
);
2339 libxfs_da_log_buf(tp
, lbp
, 0, mp
->m_dirblksize
- 1);
2340 libxfs_bmap_finish(&tp
, &flist
, firstblock
, &committed
);
2341 libxfs_trans_commit(tp
, 0, 0);
2343 for (i
= 0; i
< freetab
->nents
; i
+= XFS_DIR2_MAX_FREE_BESTS(mp
)) {
2344 tp
= libxfs_trans_alloc(mp
, 0);
2345 nres
= XFS_DAENTER_SPACE_RES(mp
, XFS_DATA_FORK
);
2346 error
= libxfs_trans_reserve(tp
,
2347 nres
, XFS_CREATE_LOG_RES(mp
), 0, XFS_TRANS_PERM_LOG_RES
,
2348 XFS_CREATE_LOG_COUNT
);
2351 libxfs_trans_ijoin(tp
, ip
, 0);
2352 libxfs_trans_ihold(tp
, ip
);
2353 XFS_BMAP_INIT(&flist
, &firstblock
);
2354 bzero(&args
, sizeof(args
));
2357 args
.whichfork
= XFS_DATA_FORK
;
2358 args
.firstblock
= &firstblock
;
2359 args
.flist
= &flist
;
2361 if ((error
= libxfs_dir2_grow_inode(&args
, XFS_DIR2_FREE_SPACE
,
2363 (error
= libxfs_da_get_buf(tp
, ip
, XFS_DIR2_DB_TO_DA(mp
, fbno
),
2364 -1, &fbp
, XFS_DATA_FORK
))) {
2365 do_error("can't add free block to directory inode "
2371 bzero(free
, mp
->m_dirblksize
);
2372 INT_SET(free
->hdr
.magic
, ARCH_CONVERT
, XFS_DIR2_FREE_MAGIC
);
2373 INT_SET(free
->hdr
.firstdb
, ARCH_CONVERT
, i
);
2374 INT_SET(free
->hdr
.nvalid
, ARCH_CONVERT
, XFS_DIR2_MAX_FREE_BESTS(mp
));
2375 if (i
+ INT_GET(free
->hdr
.nvalid
, ARCH_CONVERT
) > freetab
->nents
)
2376 INT_SET(free
->hdr
.nvalid
, ARCH_CONVERT
, freetab
->nents
- i
);
2377 for (j
= 0; j
< INT_GET(free
->hdr
.nvalid
, ARCH_CONVERT
); j
++) {
2378 INT_SET(free
->bests
[j
], ARCH_CONVERT
, freetab
->ents
[i
+ j
].v
);
2379 if (INT_GET(free
->bests
[j
], ARCH_CONVERT
) != NULLDATAOFF
)
2380 INT_MOD(free
->hdr
.nused
, ARCH_CONVERT
, +1);
2382 libxfs_da_log_buf(tp
, fbp
, 0, mp
->m_dirblksize
- 1);
2383 libxfs_bmap_finish(&tp
, &flist
, firstblock
, &committed
);
2384 libxfs_trans_commit(tp
, 0, 0);
2389 * Rebuild the entries from a single data block.
2392 longform_dir2_rebuild_data(
2399 xfs_dir2_block_tail_t
*btp
;
2401 xfs_dir2_data_t
*data
;
2403 xfs_dir2_data_entry_t
*dep
;
2404 xfs_dir2_data_unused_t
*dup
;
2407 xfs_dir2_free_t
*fblock
;
2411 xfs_fsblock_t firstblock
;
2412 xfs_bmap_free_t flist
;
2419 if (libxfs_da_read_buf(NULL
, ip
, da_bno
, da_bno
== 0 ? -2 : -1, &bp
,
2421 do_error("can't read block %u for directory inode %llu\n",
2425 if (da_bno
== 0 && bp
== NULL
)
2427 * The block was punched out.
2431 dbno
= XFS_DIR2_DA_TO_DB(mp
, da_bno
);
2432 fdb
= XFS_DIR2_DB_TO_FDB(mp
, dbno
);
2433 if (libxfs_da_read_buf(NULL
, ip
, XFS_DIR2_DB_TO_DA(mp
, fdb
), -1, &fbp
,
2435 do_error("can't read block %u for directory inode %llu\n",
2436 XFS_DIR2_DB_TO_DA(mp
, fdb
), ino
);
2439 data
= malloc(mp
->m_dirblksize
);
2442 "malloc failed in longform_dir2_rebuild_data (%u bytes)\n",
2446 bcopy(bp
->data
, data
, mp
->m_dirblksize
);
2447 ptr
= (char *)data
->u
;
2448 if (INT_GET(data
->hdr
.magic
, ARCH_CONVERT
) == XFS_DIR2_BLOCK_MAGIC
) {
2449 btp
= XFS_DIR2_BLOCK_TAIL_P(mp
, (xfs_dir2_block_t
*)data
);
2450 endptr
= (char *)XFS_DIR2_BLOCK_LEAF_P_ARCH(btp
, ARCH_CONVERT
);
2452 endptr
= (char *)data
+ mp
->m_dirblksize
;
2454 fi
= XFS_DIR2_DB_TO_FDINDEX(mp
, dbno
);
2455 tp
= libxfs_trans_alloc(mp
, 0);
2456 error
= libxfs_trans_reserve(tp
, 0, XFS_CREATE_LOG_RES(mp
), 0,
2457 XFS_TRANS_PERM_LOG_RES
, XFS_CREATE_LOG_COUNT
);
2460 libxfs_trans_ijoin(tp
, ip
, 0);
2461 libxfs_trans_ihold(tp
, ip
);
2462 libxfs_da_bjoin(tp
, bp
);
2463 libxfs_da_bhold(tp
, bp
);
2464 libxfs_da_bjoin(tp
, fbp
);
2465 libxfs_da_bhold(tp
, fbp
);
2466 XFS_BMAP_INIT(&flist
, &firstblock
);
2467 needlog
= needscan
= 0;
2468 bzero(((xfs_dir2_data_t
*)(bp
->data
))->hdr
.bestfree
,
2469 sizeof(data
->hdr
.bestfree
));
2470 libxfs_dir2_data_make_free(tp
, bp
, (xfs_dir2_data_aoff_t
)sizeof(data
->hdr
),
2471 mp
->m_dirblksize
- sizeof(data
->hdr
), &needlog
, &needscan
);
2472 ASSERT(needscan
== 0);
2473 libxfs_dir2_data_log_header(tp
, bp
);
2474 INT_SET(fblock
->bests
[fi
], ARCH_CONVERT
,
2475 INT_GET(((xfs_dir2_data_t
*)(bp
->data
))->hdr
.bestfree
[0].length
, ARCH_CONVERT
));
2476 libxfs_dir2_free_log_bests(tp
, fbp
, fi
, fi
);
2477 libxfs_bmap_finish(&tp
, &flist
, firstblock
, &committed
);
2478 libxfs_trans_commit(tp
, 0, 0);
2480 while (ptr
< endptr
) {
2481 dup
= (xfs_dir2_data_unused_t
*)ptr
;
2482 if (INT_GET(dup
->freetag
, ARCH_CONVERT
) == XFS_DIR2_DATA_FREE_TAG
) {
2483 ptr
+= INT_GET(dup
->length
, ARCH_CONVERT
);
2486 dep
= (xfs_dir2_data_entry_t
*)ptr
;
2487 ptr
+= XFS_DIR2_DATA_ENTSIZE(dep
->namelen
);
2488 if (dep
->name
[0] == '/')
2490 tp
= libxfs_trans_alloc(mp
, 0);
2491 nres
= XFS_CREATE_SPACE_RES(mp
, dep
->namelen
);
2492 error
= libxfs_trans_reserve(tp
, nres
, XFS_CREATE_LOG_RES(mp
), 0,
2493 XFS_TRANS_PERM_LOG_RES
, XFS_CREATE_LOG_COUNT
);
2496 libxfs_trans_ijoin(tp
, ip
, 0);
2497 libxfs_trans_ihold(tp
, ip
);
2498 libxfs_da_bjoin(tp
, bp
);
2499 libxfs_da_bhold(tp
, bp
);
2500 libxfs_da_bjoin(tp
, fbp
);
2501 libxfs_da_bhold(tp
, fbp
);
2502 XFS_BMAP_INIT(&flist
, &firstblock
);
2503 error
= dir_createname(mp
, tp
, ip
, (char *)dep
->name
,
2504 dep
->namelen
, INT_GET(dep
->inumber
, ARCH_CONVERT
),
2505 &firstblock
, &flist
, nres
);
2507 libxfs_bmap_finish(&tp
, &flist
, firstblock
, &committed
);
2508 libxfs_trans_commit(tp
, 0, 0);
2510 libxfs_da_brelse(NULL
, bp
);
2511 libxfs_da_brelse(NULL
, fbp
);
2516 * Finish the rebuild of a directory.
2517 * Stuff / in and then remove it, this forces the directory to end
2518 * up in the right format.
2521 longform_dir2_rebuild_finish(
2528 xfs_fsblock_t firstblock
;
2529 xfs_bmap_free_t flist
;
2533 tp
= libxfs_trans_alloc(mp
, 0);
2534 nres
= XFS_CREATE_SPACE_RES(mp
, 1);
2535 error
= libxfs_trans_reserve(tp
, nres
, XFS_CREATE_LOG_RES(mp
), 0,
2536 XFS_TRANS_PERM_LOG_RES
, XFS_CREATE_LOG_COUNT
);
2539 libxfs_trans_ijoin(tp
, ip
, 0);
2540 libxfs_trans_ihold(tp
, ip
);
2541 XFS_BMAP_INIT(&flist
, &firstblock
);
2542 error
= dir_createname(mp
, tp
, ip
, "/", 1, ino
,
2543 &firstblock
, &flist
, nres
);
2545 libxfs_bmap_finish(&tp
, &flist
, firstblock
, &committed
);
2546 libxfs_trans_commit(tp
, 0, 0);
2548 /* could kill trailing empty data blocks here */
2550 tp
= libxfs_trans_alloc(mp
, 0);
2551 nres
= XFS_REMOVE_SPACE_RES(mp
);
2552 error
= libxfs_trans_reserve(tp
, nres
, XFS_REMOVE_LOG_RES(mp
), 0,
2553 XFS_TRANS_PERM_LOG_RES
, XFS_REMOVE_LOG_COUNT
);
2556 libxfs_trans_ijoin(tp
, ip
, 0);
2557 libxfs_trans_ihold(tp
, ip
);
2558 XFS_BMAP_INIT(&flist
, &firstblock
);
2559 error
= dir_removename(mp
, tp
, ip
, "/", 1, ino
,
2560 &firstblock
, &flist
, nres
);
2562 libxfs_bmap_finish(&tp
, &flist
, firstblock
, &committed
);
2563 libxfs_trans_commit(tp
, 0, 0);
2567 * Rebuild a directory.
2568 * Remove all the non-data blocks.
2569 * Re-initialize to (empty) node form.
2570 * Loop over the data blocks reinserting each entry.
2571 * Force the directory into the right format.
2574 longform_dir2_rebuild(
2584 xfs_fileoff_t next_da_bno
;
2586 do_warn("rebuilding directory inode %llu\n", ino
);
2588 /* kill leaf blocks */
2589 for (da_bno
= mp
->m_dirleafblk
, next_da_bno
= isblock
? NULLFILEOFF
: 0;
2590 next_da_bno
!= NULLFILEOFF
;
2591 da_bno
= (xfs_dablk_t
)next_da_bno
) {
2592 next_da_bno
= da_bno
+ mp
->m_dirblkfsbs
- 1;
2593 if (libxfs_bmap_next_offset(NULL
, ip
, &next_da_bno
, XFS_DATA_FORK
))
2595 if (libxfs_da_get_buf(NULL
, ip
, da_bno
, -1, &bp
, XFS_DATA_FORK
)) {
2596 do_error("can't get block %u for directory inode "
2601 dir2_kill_block(mp
, ip
, da_bno
, bp
);
2604 /* rebuild empty btree and freelist */
2605 longform_dir2_rebuild_setup(mp
, ino
, ip
, freetab
);
2607 /* rebuild directory */
2608 for (da_bno
= mp
->m_dirdatablk
, next_da_bno
= 0;
2609 da_bno
< mp
->m_dirleafblk
&& next_da_bno
!= NULLFILEOFF
;
2610 da_bno
= (xfs_dablk_t
)next_da_bno
) {
2611 next_da_bno
= da_bno
+ mp
->m_dirblkfsbs
- 1;
2612 if (libxfs_bmap_next_offset(NULL
, ip
, &next_da_bno
, XFS_DATA_FORK
))
2614 longform_dir2_rebuild_data(mp
, ino
, ip
, da_bno
);
2617 /* put the directory in the appropriate on-disk format */
2618 longform_dir2_rebuild_finish(mp
, ino
, ip
);
2623 * succeeds or dies, inode never gets dirtied since all changes
2624 * happen in file blocks. the inode size and other core info
2625 * is already correct, it's just the leaf entries that get altered.
2626 * XXX above comment is wrong for v2 - need to see why it matters
2629 longform_dir2_entry_check(xfs_mount_t
*mp
,
2635 ino_tree_node_t
*irec
,
2638 xfs_dir2_block_t
*block
;
2639 xfs_dir2_leaf_entry_t
*blp
;
2641 xfs_dir2_block_tail_t
*btp
;
2644 dir_hash_tab_t
*hashtab
;
2648 xfs_fileoff_t next_da_bno
;
2653 freetab
= malloc(FREETAB_SIZE(ip
->i_d
.di_size
/ mp
->m_dirblksize
));
2656 "malloc failed in longform_dir2_entry_check (%u bytes)\n",
2657 FREETAB_SIZE(ip
->i_d
.di_size
/ mp
->m_dirblksize
));
2660 freetab
->naents
= ip
->i_d
.di_size
/ mp
->m_dirblksize
;
2662 for (i
= 0; i
< freetab
->naents
; i
++) {
2663 freetab
->ents
[i
].v
= NULLDATAOFF
;
2664 freetab
->ents
[i
].s
= 0;
2666 /* is this a block, leaf, or node directory? */
2667 libxfs_dir2_isblock(NULL
, ip
, &isblock
);
2668 libxfs_dir2_isleaf(NULL
, ip
, &isleaf
);
2670 /* check directory data */
2671 hashtab
= dir_hash_init(ip
->i_d
.di_size
);
2672 for (da_bno
= 0, next_da_bno
= 0;
2673 next_da_bno
!= NULLFILEOFF
&& da_bno
< mp
->m_dirleafblk
;
2674 da_bno
= (xfs_dablk_t
)next_da_bno
) {
2675 next_da_bno
= da_bno
+ mp
->m_dirblkfsbs
- 1;
2676 if (libxfs_bmap_next_offset(NULL
, ip
, &next_da_bno
, XFS_DATA_FORK
))
2678 if (libxfs_da_read_bufr(NULL
, ip
, da_bno
, -1, &bp
,
2680 do_error("can't read block %u for directory inode "
2685 longform_dir2_entry_check_data(mp
, ip
, num_illegal
, need_dot
,
2686 stack
, irec
, ino_offset
, &bp
, hashtab
, &freetab
, da_bno
,
2688 /* it releases the buffer unless isblock is set */
2690 fixit
= (*num_illegal
!= 0) || dir2_is_badino(ino
);
2692 /* check btree and freespace */
2696 btp
= XFS_DIR2_BLOCK_TAIL_P(mp
, block
);
2697 blp
= XFS_DIR2_BLOCK_LEAF_P_ARCH(btp
, ARCH_CONVERT
);
2698 seeval
= dir_hash_see_all(hashtab
, blp
, INT_GET(btp
->count
, ARCH_CONVERT
), INT_GET(btp
->stale
, ARCH_CONVERT
));
2699 if (dir_hash_check(hashtab
, ip
, seeval
))
2701 libxfs_da_brelse(NULL
, bp
);
2702 } else if (isleaf
) {
2703 fixit
|= longform_dir2_check_leaf(mp
, ip
, hashtab
, freetab
);
2705 fixit
|= longform_dir2_check_node(mp
, ip
, hashtab
, freetab
);
2707 dir_hash_done(hashtab
);
2708 if (!no_modify
&& fixit
)
2709 longform_dir2_rebuild(mp
, ino
, ip
, num_illegal
, freetab
,
2715 * shortform directory processing routines -- entry verification and
2716 * bad entry deletion (pruning).
2719 shortform_dir_entry_check(xfs_mount_t
*mp
,
2724 ino_tree_node_t
*current_irec
,
2725 int current_ino_offset
)
2729 xfs_dir_shortform_t
*sf
;
2730 xfs_dir_sf_entry_t
*sf_entry
, *next_sfe
, *tmp_sfe
;
2732 ino_tree_node_t
*irec
;
2742 char fname
[MAXNAMELEN
+ 1];
2745 sf
= (xfs_dir_shortform_t
*) ifp
->if_u1
.if_data
;
2749 max_size
= ifp
->if_bytes
;
2750 ASSERT(ip
->i_d
.di_size
<= ifp
->if_bytes
);
2753 * no '.' entry in shortform dirs, just bump up ref count by 1
2754 * '..' was already (or will be) accounted for and checked when
2755 * the directory is reached or will be taken care of when the
2756 * directory is moved to orphanage.
2758 add_inode_ref(current_irec
, current_ino_offset
);
2761 * now run through entries, stop at first bad entry, don't need
2762 * to skip over '..' since that's encoded in its own field and
2763 * no need to worry about '.' since it doesn't exist.
2765 sf_entry
= next_sfe
= &sf
->list
[0];
2768 do_warn("shortform dir inode %llu has null data entries \n", ino
);
2772 for (i
= 0; i
< INT_GET(sf
->hdr
.count
, ARCH_CONVERT
) && max_size
>
2773 (__psint_t
)next_sfe
- (__psint_t
)sf
;
2774 sf_entry
= next_sfe
, i
++) {
2779 XFS_DIR_SF_GET_DIRINO_ARCH(&sf_entry
->inumber
, &lino
, ARCH_CONVERT
);
2781 namelen
= sf_entry
->namelen
;
2783 ASSERT(no_modify
|| namelen
> 0);
2785 if (no_modify
&& namelen
== 0) {
2787 * if we're really lucky, this is
2788 * the last entry in which case we
2789 * can use the dir size to set the
2790 * namelen value. otherwise, forget
2791 * it because we're not going to be
2792 * able to find the next entry.
2796 if (i
== INT_GET(sf
->hdr
.count
, ARCH_CONVERT
) - 1) {
2797 namelen
= ip
->i_d
.di_size
-
2798 ((__psint_t
) &sf_entry
->name
[0] -
2802 * don't process the rest of the directory,
2803 * break out of processing looop
2807 } else if (no_modify
&& (__psint_t
) sf_entry
- (__psint_t
) sf
+
2808 + XFS_DIR_SF_ENTSIZE_BYENTRY(sf_entry
)
2809 > ip
->i_d
.di_size
) {
2812 if (i
== INT_GET(sf
->hdr
.count
, ARCH_CONVERT
) - 1) {
2813 namelen
= ip
->i_d
.di_size
-
2814 ((__psint_t
) &sf_entry
->name
[0] -
2818 * don't process the rest of the directory,
2819 * break out of processing looop
2825 bcopy(sf_entry
->name
, fname
, sf_entry
->namelen
);
2826 fname
[sf_entry
->namelen
] = '\0';
2828 ASSERT(no_modify
|| lino
!= NULLFSINO
);
2829 ASSERT(no_modify
|| !verify_inum(mp
, lino
));
2832 * special case the "lost+found" entry if it's pointing
2833 * to where we think lost+found should be. if that's
2834 * the case, that's the one we created in phase 6.
2835 * just skip it. no need to process it and its ..
2836 * link is already accounted for. Also skip entries
2837 * with bogus inode numbers if we're in no modify mode.
2840 if ((lino
== orphanage_ino
&& strcmp(fname
, ORPHANAGE
) == 0)
2841 || (no_modify
&& verify_inum(mp
, lino
))) {
2842 next_sfe
= (xfs_dir_sf_entry_t
*)
2843 ((__psint_t
) sf_entry
+
2844 XFS_DIR_SF_ENTSIZE_BYENTRY(sf_entry
));
2848 irec
= find_inode_rec(XFS_INO_TO_AGNO(mp
, lino
),
2849 XFS_INO_TO_AGINO(mp
, lino
));
2851 if (irec
== NULL
&& no_modify
) {
2853 "entry \"%s\" in shortform dir %llu references non-existent ino %llu\n",
2855 do_warn("would junk entry\n");
2859 ASSERT(irec
!= NULL
);
2861 ino_offset
= XFS_INO_TO_AGINO(mp
, lino
) - irec
->ino_startnum
;
2864 * if it's a free inode, blow out the entry.
2865 * by now, any inode that we think is free
2868 if (is_inode_free(irec
, ino_offset
)) {
2870 * don't complain if this entry points to the old
2871 * and now-free lost+found inode
2873 if (verbose
|| no_modify
|| lino
!= old_orphanage_ino
)
2875 "entry \"%s\" in shortform dir inode %llu points to free inode %llu\n",
2881 do_warn("would junk entry \"%s\"\n",
2884 } else if (!inode_isadir(irec
, ino_offset
)) {
2886 * check easy case first, regular inode, just bump
2887 * the link count and continue
2889 add_inode_reached(irec
, ino_offset
);
2891 next_sfe
= (xfs_dir_sf_entry_t
*)
2892 ((__psint_t
) sf_entry
+
2893 XFS_DIR_SF_ENTSIZE_BYENTRY(sf_entry
));
2896 parent
= get_inode_parent(irec
, ino_offset
);
2899 * bump up the link counts in parent and child.
2900 * directory but if the link doesn't agree with
2901 * the .. in the child, blow out the entry
2903 if (is_inode_reached(irec
, ino_offset
)) {
2906 "entry \"%s\" in dir %llu references already connected dir ino %llu,\n",
2908 } else if (parent
== ino
) {
2909 add_inode_reached(irec
, ino_offset
);
2910 add_inode_ref(current_irec
, current_ino_offset
);
2912 if (!is_inode_refchecked(lino
, irec
,
2914 push_dir(stack
, lino
);
2918 "entry \"%s\" in dir %llu not consistent with .. value (%llu) in dir ino %llu,\n",
2919 fname
, ino
, parent
, lino
);
2925 tmp_elen
= XFS_DIR_SF_ENTSIZE_BYENTRY(sf_entry
);
2926 tmp_sfe
= (xfs_dir_sf_entry_t
*)
2927 ((__psint_t
) sf_entry
+ tmp_elen
);
2928 tmp_len
= max_size
- ((__psint_t
) tmp_sfe
2930 max_size
-= tmp_elen
;
2931 bytes_deleted
+= tmp_elen
;
2933 memmove(sf_entry
, tmp_sfe
, tmp_len
);
2935 INT_MOD(sf
->hdr
.count
, ARCH_CONVERT
, -1);
2936 bzero((void *) ((__psint_t
) sf_entry
+ tmp_len
),
2940 * set the tmp value to the current
2941 * pointer so we'll process the entry
2947 * WARNING: drop the index i by one
2948 * so it matches the decremented count for
2949 * accurate comparisons in the loop test
2955 if (verbose
|| lino
!= old_orphanage_ino
)
2957 "junking entry \"%s\" in directory inode %llu\n",
2960 do_warn("would junk entry \"%s\"\n", fname
);
2965 * go onto next entry unless we've just junked an
2966 * entry in which the current entry pointer points
2967 * to an unprocessed entry. have to take into entries
2968 * with bad namelen into account in no modify mode since we
2969 * calculate size based on next_sfe.
2971 ASSERT(no_modify
|| bad_sfnamelen
== 0);
2973 next_sfe
= (tmp_sfe
== NULL
)
2974 ? (xfs_dir_sf_entry_t
*) ((__psint_t
) sf_entry
2976 ? XFS_DIR_SF_ENTSIZE_BYENTRY(sf_entry
)
2977 : sizeof(xfs_dir_sf_entry_t
) - 1
2984 * sync up sizes if required
2987 ASSERT(bytes_deleted
> 0);
2989 libxfs_idata_realloc(ip
, -bytes_deleted
, XFS_DATA_FORK
);
2990 ip
->i_d
.di_size
-= bytes_deleted
;
2993 if (ip
->i_d
.di_size
!= ip
->i_df
.if_bytes
) {
2994 ASSERT(ip
->i_df
.if_bytes
== (xfs_fsize_t
)
2995 ((__psint_t
) next_sfe
- (__psint_t
) sf
));
2996 ip
->i_d
.di_size
= (xfs_fsize_t
)
2997 ((__psint_t
) next_sfe
- (__psint_t
) sf
);
2999 "setting size to %lld bytes to reflect junked entries\n",
3007 prune_sf_dir_entry(xfs_mount_t
*mp
, xfs_ino_t ino
, xfs_inode_t
*ip
)
3011 xfs_dir_shortform_t
*sf
;
3012 xfs_dir_sf_entry_t
*sf_entry
, *next_sfe
, *tmp_sfe
;
3019 char fname
[MAXNAMELEN
+ 1];
3022 sf
= (xfs_dir_shortform_t
*) ifp
->if_u1
.if_data
;
3025 max_size
= ifp
->if_bytes
;
3026 ASSERT(ip
->i_d
.di_size
<= ifp
->if_bytes
);
3029 * now run through entries and delete every bad entry
3031 sf_entry
= next_sfe
= &sf
->list
[0];
3033 for (i
= 0; i
< INT_GET(sf
->hdr
.count
, ARCH_CONVERT
) && max_size
>
3034 (__psint_t
)next_sfe
- (__psint_t
)sf
;
3035 sf_entry
= next_sfe
, i
++) {
3038 XFS_DIR_SF_GET_DIRINO_ARCH(&sf_entry
->inumber
, &lino
, ARCH_CONVERT
);
3040 bcopy(sf_entry
->name
, fname
, sf_entry
->namelen
);
3041 fname
[sf_entry
->namelen
] = '\0';
3043 if (sf_entry
->name
[0] == '/') {
3045 tmp_elen
= XFS_DIR_SF_ENTSIZE_BYENTRY(sf_entry
);
3046 tmp_sfe
= (xfs_dir_sf_entry_t
*)
3047 ((__psint_t
) sf_entry
+ tmp_elen
);
3048 tmp_len
= max_size
- ((__psint_t
) tmp_sfe
3050 max_size
-= tmp_elen
;
3051 bytes_deleted
+= tmp_elen
;
3053 memmove(sf_entry
, tmp_sfe
, tmp_len
);
3055 INT_MOD(sf
->hdr
.count
, ARCH_CONVERT
, -1);
3056 bzero((void *) ((__psint_t
) sf_entry
+ tmp_len
),
3060 * set the tmp value to the current
3061 * pointer so we'll process the entry
3067 * WARNING: drop the index i by one
3068 * so it matches the decremented count for
3069 * accurate comparisons in the loop test
3074 next_sfe
= (tmp_sfe
== NULL
)
3075 ? (xfs_dir_sf_entry_t
*) ((__psint_t
) sf_entry
+
3076 XFS_DIR_SF_ENTSIZE_BYENTRY(sf_entry
))
3081 * sync up sizes if required
3083 if (bytes_deleted
> 0) {
3084 libxfs_idata_realloc(ip
, -bytes_deleted
, XFS_DATA_FORK
);
3085 ip
->i_d
.di_size
-= bytes_deleted
;
3088 if (ip
->i_d
.di_size
!= ip
->i_df
.if_bytes
) {
3089 ASSERT(ip
->i_df
.if_bytes
== (xfs_fsize_t
)
3090 ((__psint_t
) next_sfe
- (__psint_t
) sf
));
3091 ip
->i_d
.di_size
= (xfs_fsize_t
)
3092 ((__psint_t
) next_sfe
- (__psint_t
) sf
);
3094 "setting size to %lld bytes to reflect junked entries\n",
3100 * shortform directory v2 processing routines -- entry verification and
3101 * bad entry deletion (pruning).
3104 shortform_dir2_entry_check(xfs_mount_t
*mp
,
3109 ino_tree_node_t
*current_irec
,
3110 int current_ino_offset
)
3115 xfs_dir2_sf_entry_t
*sfep
, *next_sfep
, *tmp_sfep
;
3117 ino_tree_node_t
*irec
;
3127 char fname
[MAXNAMELEN
+ 1];
3131 sfp
= (xfs_dir2_sf_t
*) ifp
->if_u1
.if_data
;
3135 max_size
= ifp
->if_bytes
;
3136 ASSERT(ip
->i_d
.di_size
<= ifp
->if_bytes
);
3139 * no '.' entry in shortform dirs, just bump up ref count by 1
3140 * '..' was already (or will be) accounted for and checked when
3141 * the directory is reached or will be taken care of when the
3142 * directory is moved to orphanage.
3144 add_inode_ref(current_irec
, current_ino_offset
);
3147 * Initialise i8 counter -- the parent inode number counts as well.
3149 i8
= (XFS_DIR2_SF_GET_INUMBER_ARCH(sfp
, &sfp
->hdr
.parent
, ARCH_CONVERT
) > XFS_DIR2_MAX_SHORT_INUM
);
3152 * now run through entries, stop at first bad entry, don't need
3153 * to skip over '..' since that's encoded in its own field and
3154 * no need to worry about '.' since it doesn't exist.
3156 sfep
= next_sfep
= XFS_DIR2_SF_FIRSTENTRY(sfp
);
3158 for (i
= 0; i
< INT_GET(sfp
->hdr
.count
, ARCH_CONVERT
) && max_size
>
3159 (__psint_t
)next_sfep
- (__psint_t
)sfp
;
3160 sfep
= next_sfep
, i
++) {
3165 lino
= XFS_DIR2_SF_GET_INUMBER_ARCH(sfp
, XFS_DIR2_SF_INUMBERP(sfep
), ARCH_CONVERT
);
3167 namelen
= sfep
->namelen
;
3169 ASSERT(no_modify
|| namelen
> 0);
3171 if (no_modify
&& namelen
== 0) {
3173 * if we're really lucky, this is
3174 * the last entry in which case we
3175 * can use the dir size to set the
3176 * namelen value. otherwise, forget
3177 * it because we're not going to be
3178 * able to find the next entry.
3182 if (i
== INT_GET(sfp
->hdr
.count
, ARCH_CONVERT
) - 1) {
3183 namelen
= ip
->i_d
.di_size
-
3184 ((__psint_t
) &sfep
->name
[0] -
3188 * don't process the rest of the directory,
3189 * break out of processing loop
3193 } else if (no_modify
&& (__psint_t
) sfep
- (__psint_t
) sfp
+
3194 + XFS_DIR2_SF_ENTSIZE_BYENTRY(sfp
, sfep
)
3195 > ip
->i_d
.di_size
) {
3198 if (i
== INT_GET(sfp
->hdr
.count
, ARCH_CONVERT
) - 1) {
3199 namelen
= ip
->i_d
.di_size
-
3200 ((__psint_t
) &sfep
->name
[0] -
3204 * don't process the rest of the directory,
3205 * break out of processing loop
3211 bcopy(sfep
->name
, fname
, sfep
->namelen
);
3212 fname
[sfep
->namelen
] = '\0';
3214 ASSERT(no_modify
|| (lino
!= NULLFSINO
&& lino
!= 0));
3215 ASSERT(no_modify
|| !verify_inum(mp
, lino
));
3218 * special case the "lost+found" entry if it's pointing
3219 * to where we think lost+found should be. if that's
3220 * the case, that's the one we created in phase 6.
3221 * just skip it. no need to process it and its ..
3222 * link is already accounted for.
3225 if (lino
== orphanage_ino
&& strcmp(fname
, ORPHANAGE
) == 0) {
3226 if (lino
> XFS_DIR2_MAX_SHORT_INUM
)
3228 next_sfep
= (xfs_dir2_sf_entry_t
*)
3230 XFS_DIR2_SF_ENTSIZE_BYENTRY(sfp
, sfep
));
3235 * Also skip entries with bogus inode numbers if we're
3236 * in no modify mode.
3239 if (no_modify
&& verify_inum(mp
, lino
)) {
3240 next_sfep
= (xfs_dir2_sf_entry_t
*)
3242 XFS_DIR2_SF_ENTSIZE_BYENTRY(sfp
, sfep
));
3246 irec
= find_inode_rec(XFS_INO_TO_AGNO(mp
, lino
),
3247 XFS_INO_TO_AGINO(mp
, lino
));
3249 if (irec
== NULL
&& no_modify
) {
3250 do_warn("entry \"%s\" in shortform directory %llu "
3251 "references non-existent inode %llu\n",
3253 do_warn("would junk entry\n");
3257 ASSERT(irec
!= NULL
);
3259 ino_offset
= XFS_INO_TO_AGINO(mp
, lino
) - irec
->ino_startnum
;
3262 * if it's a free inode, blow out the entry.
3263 * by now, any inode that we think is free
3266 if (is_inode_free(irec
, ino_offset
)) {
3268 * don't complain if this entry points to the old
3269 * and now-free lost+found inode
3271 if (verbose
|| no_modify
|| lino
!= old_orphanage_ino
)
3272 do_warn("entry \"%s\" in shortform directory "
3273 "inode %llu points to free inode "
3280 do_warn("would junk entry \"%s\"\n",
3283 } else if (!inode_isadir(irec
, ino_offset
)) {
3285 * check easy case first, regular inode, just bump
3288 add_inode_reached(irec
, ino_offset
);
3290 parent
= get_inode_parent(irec
, ino_offset
);
3293 * bump up the link counts in parent and child.
3294 * directory but if the link doesn't agree with
3295 * the .. in the child, blow out the entry
3297 if (is_inode_reached(irec
, ino_offset
)) {
3299 do_warn("entry \"%s\" in directory inode %llu "
3300 "references already connected inode "
3303 } else if (parent
== ino
) {
3304 add_inode_reached(irec
, ino_offset
);
3305 add_inode_ref(current_irec
, current_ino_offset
);
3307 if (!is_inode_refchecked(lino
, irec
,
3309 push_dir(stack
, lino
);
3312 do_warn("entry \"%s\" in directory inode %llu "
3313 "not consistent with .. value (%llu) "
3315 fname
, ino
, parent
, lino
);
3321 tmp_elen
= XFS_DIR2_SF_ENTSIZE_BYENTRY(sfp
, sfep
);
3322 tmp_sfep
= (xfs_dir2_sf_entry_t
*)
3323 ((__psint_t
) sfep
+ tmp_elen
);
3324 tmp_len
= max_size
- ((__psint_t
) tmp_sfep
3326 max_size
-= tmp_elen
;
3327 bytes_deleted
+= tmp_elen
;
3329 memmove(sfep
, tmp_sfep
, tmp_len
);
3331 INT_MOD(sfp
->hdr
.count
, ARCH_CONVERT
, -1);
3332 bzero((void *) ((__psint_t
) sfep
+ tmp_len
),
3336 * set the tmp value to the current
3337 * pointer so we'll process the entry
3343 * WARNING: drop the index i by one
3344 * so it matches the decremented count for
3345 * accurate comparisons in the loop test
3351 if (verbose
|| lino
!= old_orphanage_ino
)
3352 do_warn("junking entry \"%s\" in "
3353 "directory inode %llu\n",
3356 do_warn("would junk entry \"%s\"\n", fname
);
3358 } else if (lino
> XFS_DIR2_MAX_SHORT_INUM
)
3362 * go onto next entry unless we've just junked an
3363 * entry in which the current entry pointer points
3364 * to an unprocessed entry. have to take into entries
3365 * with bad namelen into account in no modify mode since we
3366 * calculate size based on next_sfep.
3368 ASSERT(no_modify
|| bad_sfnamelen
== 0);
3370 next_sfep
= (tmp_sfep
== NULL
)
3371 ? (xfs_dir2_sf_entry_t
*) ((__psint_t
) sfep
3373 ? XFS_DIR2_SF_ENTSIZE_BYENTRY(sfp
, sfep
)
3374 : XFS_DIR2_SF_ENTSIZE_BYNAME(sfp
, namelen
)))
3378 if (sfp
->hdr
.i8count
!= i8
) {
3380 do_warn("would fix i8count in inode %llu\n", ino
);
3383 tmp_sfep
= next_sfep
;
3384 process_sf_dir2_fixi8(sfp
, &tmp_sfep
);
3386 (__psint_t
)next_sfep
-
3387 (__psint_t
)tmp_sfep
;
3388 next_sfep
= tmp_sfep
;
3390 sfp
->hdr
.i8count
= i8
;
3392 do_warn("fixing i8count in inode %llu\n", ino
);
3397 * sync up sizes if required
3400 ASSERT(bytes_deleted
> 0);
3402 libxfs_idata_realloc(ip
, -bytes_deleted
, XFS_DATA_FORK
);
3403 ip
->i_d
.di_size
-= bytes_deleted
;
3406 if (ip
->i_d
.di_size
!= ip
->i_df
.if_bytes
) {
3407 ASSERT(ip
->i_df
.if_bytes
== (xfs_fsize_t
)
3408 ((__psint_t
) next_sfep
- (__psint_t
) sfp
));
3409 ip
->i_d
.di_size
= (xfs_fsize_t
)
3410 ((__psint_t
) next_sfep
- (__psint_t
) sfp
);
3411 do_warn("setting size to %lld bytes to reflect junked "
3419 * processes all directories reachable via the inodes on the stack
3420 * returns 0 if things are good, 1 if there's a problem
3423 process_dirstack(xfs_mount_t
*mp
, dir_stack_t
*stack
)
3425 xfs_bmap_free_t flist
;
3426 xfs_fsblock_t first
;
3430 xfs_dahash_t hashval
;
3431 ino_tree_node_t
*irec
;
3432 int ino_offset
, need_dot
, committed
;
3433 int dirty
, num_illegal
, error
, nres
;
3436 * pull directory inode # off directory stack
3438 * open up directory inode, check all entries,
3439 * then call prune_dir_entries to remove all
3440 * remaining illegal directory entries.
3443 while ((ino
= pop_dir(stack
)) != NULLFSINO
) {
3444 irec
= find_inode_rec(XFS_INO_TO_AGNO(mp
, ino
),
3445 XFS_INO_TO_AGINO(mp
, ino
));
3446 ASSERT(irec
!= NULL
);
3448 ino_offset
= XFS_INO_TO_AGINO(mp
, ino
) - irec
->ino_startnum
;
3450 ASSERT(!is_inode_refchecked(ino
, irec
, ino_offset
));
3452 if ((error
= libxfs_iget(mp
, NULL
, ino
, 0, &ip
, 0))) {
3454 do_error("couldn't map inode %llu, err = %d\n",
3457 do_warn("couldn't map inode %llu, err = %d\n",
3460 * see below for what we're doing if this
3461 * is root. Why do we need to do this here?
3462 * to ensure that the root doesn't show up
3463 * as being disconnected in the no_modify case.
3465 if (mp
->m_sb
.sb_rootino
== ino
) {
3466 add_inode_reached(irec
, 0);
3467 add_inode_ref(irec
, 0);
3471 add_inode_refchecked(ino
, irec
, 0);
3475 need_dot
= dirty
= num_illegal
= 0;
3477 if (mp
->m_sb
.sb_rootino
== ino
) {
3479 * mark root inode reached and bump up
3480 * link count for root inode to account
3481 * for '..' entry since the root inode is
3482 * never reached by a parent. we know
3483 * that root's '..' is always good --
3484 * guaranteed by phase 3 and/or below.
3486 add_inode_reached(irec
, ino_offset
);
3488 * account for link for the orphanage
3489 * "lost+found". if we're running in
3490 * modify mode and it already existed,
3491 * we deleted it so it's '..' reference
3492 * never got counted. so add it here if
3493 * we're going to create lost+found.
3495 * if we're running in no_modify mode,
3496 * we never deleted lost+found and we're
3497 * not going to create it so do nothing.
3499 * either way, the counts will match when
3500 * we look at the root inode's nlinks
3501 * field and compare that to our incore
3505 add_inode_ref(irec
, ino_offset
);
3508 add_inode_refchecked(ino
, irec
, ino_offset
);
3511 * look for bogus entries
3513 switch (ip
->i_d
.di_format
) {
3514 case XFS_DINODE_FMT_EXTENTS
:
3515 case XFS_DINODE_FMT_BTREE
:
3517 * also check for missing '.' in longform dirs.
3518 * missing .. entries are added if required when
3519 * the directory is connected to lost+found. but
3520 * we need to create '.' entries here.
3522 if (XFS_SB_VERSION_HASDIRV2(&mp
->m_sb
))
3523 longform_dir2_entry_check(mp
, ino
, ip
,
3524 &num_illegal
, &need_dot
,
3528 longform_dir_entry_check(mp
, ino
, ip
,
3529 &num_illegal
, &need_dot
,
3533 case XFS_DINODE_FMT_LOCAL
:
3534 tp
= libxfs_trans_alloc(mp
, 0);
3536 * using the remove reservation is overkill
3537 * since at most we'll only need to log the
3538 * inode but it's easier than wedging a
3539 * new define in ourselves.
3541 nres
= no_modify
? 0 : XFS_REMOVE_SPACE_RES(mp
);
3542 error
= libxfs_trans_reserve(tp
, nres
,
3543 XFS_REMOVE_LOG_RES(mp
), 0,
3544 XFS_TRANS_PERM_LOG_RES
,
3545 XFS_REMOVE_LOG_COUNT
);
3549 libxfs_trans_ijoin(tp
, ip
, 0);
3550 libxfs_trans_ihold(tp
, ip
);
3552 if (XFS_SB_VERSION_HASDIRV2(&mp
->m_sb
))
3553 shortform_dir2_entry_check(mp
, ino
, ip
, &dirty
,
3557 shortform_dir_entry_check(mp
, ino
, ip
, &dirty
,
3561 ASSERT(dirty
== 0 || (dirty
&& !no_modify
));
3563 libxfs_trans_log_inode(tp
, ip
,
3564 XFS_ILOG_CORE
| XFS_ILOG_DDATA
);
3565 libxfs_trans_commit(tp
, XFS_TRANS_RELEASE_LOG_RES
3566 |XFS_TRANS_SYNC
, 0);
3568 libxfs_trans_cancel(tp
, XFS_TRANS_RELEASE_LOG_RES
);
3577 if (!no_modify
&& !orphanage_entered
&&
3578 ino
== mp
->m_sb
.sb_rootino
) {
3579 do_warn("re-entering %s into root directory\n",
3581 tp
= libxfs_trans_alloc(mp
, 0);
3582 nres
= XFS_MKDIR_SPACE_RES(mp
, strlen(ORPHANAGE
));
3583 error
= libxfs_trans_reserve(tp
, nres
,
3584 XFS_MKDIR_LOG_RES(mp
), 0,
3585 XFS_TRANS_PERM_LOG_RES
,
3586 XFS_MKDIR_LOG_COUNT
);
3589 libxfs_trans_ijoin(tp
, ip
, 0);
3590 libxfs_trans_ihold(tp
, ip
);
3591 XFS_BMAP_INIT(&flist
, &first
);
3592 if ((error
= dir_createname(mp
, tp
, ip
, ORPHANAGE
,
3594 orphanage_ino
, &first
, &flist
,
3596 do_error("can't make %s entry in root inode "
3597 "%llu, createname error %d\n",
3598 ORPHANAGE
, ino
, error
);
3599 libxfs_trans_log_inode(tp
, ip
, XFS_ILOG_CORE
);
3600 error
= libxfs_bmap_finish(&tp
, &flist
, first
, &committed
);
3602 libxfs_trans_commit(tp
,
3603 XFS_TRANS_RELEASE_LOG_RES
| XFS_TRANS_SYNC
, 0);
3604 orphanage_entered
= 1;
3608 * if we have to create a .. for /, do it now *before*
3609 * we delete the bogus entries, otherwise the directory
3610 * could transform into a shortform dir which would
3611 * probably cause the simulation to choke. Even
3612 * if the illegal entries get shifted around, it's ok
3613 * because the entries are structurally intact and in
3614 * in hash-value order so the simulation won't get confused
3615 * if it has to move them around.
3617 if (!no_modify
&& need_root_dotdot
&&
3618 ino
== mp
->m_sb
.sb_rootino
) {
3619 ASSERT(ip
->i_d
.di_format
!= XFS_DINODE_FMT_LOCAL
);
3621 do_warn("recreating root directory .. entry\n");
3623 tp
= libxfs_trans_alloc(mp
, 0);
3626 nres
= XFS_MKDIR_SPACE_RES(mp
, 2);
3627 error
= libxfs_trans_reserve(tp
, nres
,
3628 XFS_MKDIR_LOG_RES(mp
),
3630 XFS_TRANS_PERM_LOG_RES
,
3631 XFS_MKDIR_LOG_COUNT
);
3636 libxfs_trans_ijoin(tp
, ip
, 0);
3637 libxfs_trans_ihold(tp
, ip
);
3639 XFS_BMAP_INIT(&flist
, &first
);
3641 if ((error
= dir_createname(mp
, tp
, ip
, "..", 2,
3642 ip
->i_ino
, &first
, &flist
, nres
)))
3644 "can't make \"..\" entry in root inode %llu, createname error %d\n",
3647 libxfs_trans_log_inode(tp
, ip
, XFS_ILOG_CORE
);
3649 error
= libxfs_bmap_finish(&tp
, &flist
, first
,
3652 libxfs_trans_commit(tp
, XFS_TRANS_RELEASE_LOG_RES
3653 |XFS_TRANS_SYNC
, 0);
3655 need_root_dotdot
= 0;
3656 } else if (need_root_dotdot
&& ino
== mp
->m_sb
.sb_rootino
) {
3657 do_warn("would recreate root directory .. entry\n");
3661 * delete any illegal entries -- which should only exist
3662 * if the directory is a longform directory. bogus
3663 * shortform directory entries were deleted in phase 4.
3665 if (!no_modify
&& num_illegal
> 0) {
3666 ASSERT(ip
->i_d
.di_format
!= XFS_DINODE_FMT_LOCAL
);
3667 ASSERT(!XFS_SB_VERSION_HASDIRV2(&mp
->m_sb
));
3669 while (num_illegal
> 0 && ip
->i_d
.di_format
!=
3670 XFS_DINODE_FMT_LOCAL
) {
3671 prune_lf_dir_entry(mp
, ino
, ip
, &hashval
);
3676 * handle case where we've deleted so many
3677 * entries that the directory has changed from
3678 * a longform to a shortform directory. have
3679 * to allocate a transaction since we're working
3680 * with the incore data fork.
3682 if (num_illegal
> 0) {
3683 ASSERT(ip
->i_d
.di_format
==
3684 XFS_DINODE_FMT_LOCAL
);
3685 tp
= libxfs_trans_alloc(mp
, 0);
3687 * using the remove reservation is overkill
3688 * since at most we'll only need to log the
3689 * inode but it's easier than wedging a
3690 * new define in ourselves. 10 block fs
3691 * space reservation is also overkill but
3694 nres
= XFS_REMOVE_SPACE_RES(mp
);
3695 error
= libxfs_trans_reserve(tp
, nres
,
3696 XFS_REMOVE_LOG_RES(mp
), 0,
3697 XFS_TRANS_PERM_LOG_RES
,
3698 XFS_REMOVE_LOG_COUNT
);
3702 libxfs_trans_ijoin(tp
, ip
, 0);
3703 libxfs_trans_ihold(tp
, ip
);
3705 prune_sf_dir_entry(mp
, ino
, ip
);
3707 libxfs_trans_log_inode(tp
, ip
,
3708 XFS_ILOG_CORE
| XFS_ILOG_DDATA
);
3710 libxfs_trans_commit(tp
, XFS_TRANS_RELEASE_LOG_RES
3711 |XFS_TRANS_SYNC
, 0);
3716 * if we need to create the '.' entry, do so only if
3717 * the directory is a longform dir. it it's been
3718 * turned into a shortform dir, then the inode is ok
3719 * since shortform dirs have no '.' entry and the inode
3720 * has already been committed by prune_lf_dir_entry().
3724 * bump up our link count but don't
3725 * bump up the inode link count. chances
3726 * are good that even though we lost '.'
3727 * the inode link counts reflect '.' so
3728 * leave the inode link count alone and if
3729 * it turns out to be wrong, we'll catch
3732 add_inode_ref(irec
, ino_offset
);
3736 "would create missing \".\" entry in dir ino %llu\n",
3738 } else if (ip
->i_d
.di_format
!= XFS_DINODE_FMT_LOCAL
) {
3740 * need to create . entry in longform dir.
3743 "creating missing \".\" entry in dir ino %llu\n",
3746 tp
= libxfs_trans_alloc(mp
, 0);
3749 nres
= XFS_MKDIR_SPACE_RES(mp
, 1);
3750 error
= libxfs_trans_reserve(tp
, nres
,
3751 XFS_MKDIR_LOG_RES(mp
),
3753 XFS_TRANS_PERM_LOG_RES
,
3754 XFS_MKDIR_LOG_COUNT
);
3759 libxfs_trans_ijoin(tp
, ip
, 0);
3760 libxfs_trans_ihold(tp
, ip
);
3762 XFS_BMAP_INIT(&flist
, &first
);
3764 if ((error
= dir_createname(mp
, tp
, ip
, ".",
3765 1, ip
->i_ino
, &first
, &flist
,
3768 "can't make \".\" entry in dir ino %llu, createname error %d\n",
3771 libxfs_trans_log_inode(tp
, ip
, XFS_ILOG_CORE
);
3773 error
= libxfs_bmap_finish(&tp
, &flist
, first
,
3776 libxfs_trans_commit(tp
, XFS_TRANS_RELEASE_LOG_RES
3777 |XFS_TRANS_SYNC
, 0);
3786 * mark realtime bitmap and summary inodes as reached.
3787 * quota inode will be marked here as well
3790 mark_standalone_inodes(xfs_mount_t
*mp
)
3792 ino_tree_node_t
*irec
;
3795 irec
= find_inode_rec(XFS_INO_TO_AGNO(mp
, mp
->m_sb
.sb_rbmino
),
3796 XFS_INO_TO_AGINO(mp
, mp
->m_sb
.sb_rbmino
));
3798 ASSERT(irec
!= NULL
);
3800 offset
= XFS_INO_TO_AGINO(mp
, mp
->m_sb
.sb_rbmino
) -
3803 add_inode_reached(irec
, offset
);
3805 irec
= find_inode_rec(XFS_INO_TO_AGNO(mp
, mp
->m_sb
.sb_rsumino
),
3806 XFS_INO_TO_AGINO(mp
, mp
->m_sb
.sb_rsumino
));
3808 offset
= XFS_INO_TO_AGINO(mp
, mp
->m_sb
.sb_rsumino
) -
3811 ASSERT(irec
!= NULL
);
3813 add_inode_reached(irec
, offset
);
3816 if (mp
->m_sb
.sb_uquotino
3817 && mp
->m_sb
.sb_uquotino
!= NULLFSINO
) {
3818 irec
= find_inode_rec(XFS_INO_TO_AGNO(mp
,
3819 mp
->m_sb
.sb_uquotino
),
3820 XFS_INO_TO_AGINO(mp
, mp
->m_sb
.sb_uquotino
));
3821 offset
= XFS_INO_TO_AGINO(mp
, mp
->m_sb
.sb_uquotino
)
3822 - irec
->ino_startnum
;
3823 add_inode_reached(irec
, offset
);
3825 if (mp
->m_sb
.sb_gquotino
3826 && mp
->m_sb
.sb_gquotino
!= NULLFSINO
) {
3827 irec
= find_inode_rec(XFS_INO_TO_AGNO(mp
,
3828 mp
->m_sb
.sb_gquotino
),
3829 XFS_INO_TO_AGINO(mp
, mp
->m_sb
.sb_gquotino
));
3830 offset
= XFS_INO_TO_AGINO(mp
, mp
->m_sb
.sb_gquotino
)
3831 - irec
->ino_startnum
;
3832 add_inode_reached(irec
, offset
);
3838 phase6(xfs_mount_t
*mp
)
3841 ino_tree_node_t
*irec
;
3846 bzero(&zerocr
, sizeof(cred_t
));
3848 do_log("Phase 6 - check inode connectivity...\n");
3851 teardown_bmap_finish(mp
);
3855 incore_ext_teardown(mp
);
3857 add_ino_backptrs(mp
);
3860 * verify existence of root directory - if we have to
3861 * make one, it's ok for the incore data structs not to
3862 * know about it since everything about it (and the other
3863 * inodes in its chunk if a new chunk was created) are ok
3865 if (need_root_inode
) {
3867 do_warn("reinitializing root directory\n");
3869 need_root_inode
= 0;
3870 need_root_dotdot
= 0;
3872 do_warn("would reinitialize root directory\n");
3878 do_warn("reinitializing realtime bitmap inode\n");
3882 do_warn("would reinitialize realtime bitmap inode\n");
3888 do_warn("reinitializing realtime summary inode\n");
3892 do_warn("would reinitialize realtime summary inode\n");
3898 " - resetting contents of realtime bitmap and summary inodes\n");
3899 if (fill_rbmino(mp
)) {
3901 "Warning: realtime bitmap may be inconsistent\n");
3904 if (fill_rsumino(mp
)) {
3906 "Warning: realtime bitmap may be inconsistent\n");
3911 * make orphanage (it's guaranteed to not exist now)
3914 do_log(" - ensuring existence of %s directory\n",
3916 orphanage_ino
= mk_orphanage(mp
);
3919 dir_stack_init(&stack
);
3921 mark_standalone_inodes(mp
);
3924 * push root dir on stack, then go
3926 if (!need_root_inode
) {
3927 do_log(" - traversing filesystem starting at / ... \n");
3929 push_dir(&stack
, mp
->m_sb
.sb_rootino
);
3930 process_dirstack(mp
, &stack
);
3932 do_log(" - traversal finished ... \n");
3934 ASSERT(no_modify
!= 0);
3937 " - root inode lost, cannot make new one in no modify mode ... \n");
3939 " - skipping filesystem traversal from / ... \n");
3942 do_log(" - traversing all unattached subtrees ... \n");
3944 irec
= find_inode_rec(XFS_INO_TO_AGNO(mp
, mp
->m_sb
.sb_rootino
),
3945 XFS_INO_TO_AGINO(mp
, mp
->m_sb
.sb_rootino
));
3948 * we always have a root inode, even if it's free...
3949 * if the root is free, forget it, lost+found is already gone
3951 if (is_inode_free(irec
, 0) || !inode_isadir(irec
, 0)) {
3952 need_root_inode
= 1;
3956 * then process all unreached inodes
3957 * by walking incore inode tree
3959 * get next unreached directory inode # from
3961 * push inode on dir stack
3962 * call process_dirstack
3964 for (i
= 0; i
< glob_agcount
; i
++) {
3965 irec
= findfirst_inode_rec(i
);
3970 while (irec
!= NULL
) {
3971 for (j
= 0; j
< XFS_INODES_PER_CHUNK
; j
++) {
3972 if (!is_inode_confirmed(irec
, j
))
3975 * skip directories that have already been
3976 * processed, even if they haven't been
3977 * reached. If they are reachable, we'll
3978 * pick them up when we process their parent.
3980 ino
= XFS_AGINO_TO_INO(mp
, i
,
3981 j
+ irec
->ino_startnum
);
3982 if (inode_isadir(irec
, j
) &&
3983 !is_inode_refchecked(ino
,
3985 push_dir(&stack
, ino
);
3986 process_dirstack(mp
, &stack
);
3989 irec
= next_ino_rec(irec
);
3993 do_log(" - traversals finished ... \n");
3994 do_log(" - moving disconnected inodes to lost+found ... \n");
3997 * move all disconnected inodes to the orphanage
3999 for (i
= 0; i
< glob_agcount
; i
++) {
4000 irec
= findfirst_inode_rec(i
);
4005 while (irec
!= NULL
) {
4006 for (j
= 0; j
< XFS_INODES_PER_CHUNK
; j
++) {
4007 ASSERT(is_inode_confirmed(irec
, j
));
4008 if (is_inode_free(irec
, j
))
4010 if (!is_inode_reached(irec
, j
)) {
4011 ASSERT(inode_isadir(irec
, j
) ||
4012 num_inode_references(irec
, j
)
4014 ino
= XFS_AGINO_TO_INO(mp
, i
,
4015 j
+ irec
->ino_startnum
);
4016 if (inode_isadir(irec
, j
))
4018 "disconnected dir inode %llu, ",
4022 "disconnected inode %llu, ",
4025 do_warn("moving to %s\n",
4027 mv_orphanage(mp
, orphanage_ino
,
4029 inode_isadir(irec
, j
));
4031 do_warn("would move to %s\n",
4035 * for read-only case, even though
4036 * the inode isn't really reachable,
4037 * set the flag (and bump our link
4038 * count) anyway to fool phase 7
4040 add_inode_reached(irec
, j
);
4043 irec
= next_ino_rec(irec
);