2 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like. Any license provided herein, whether implied or
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc., 59
21 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
28 * For further information regarding this notice, see:
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
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
{
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;
1732 freetab
= *freetabp
;
1734 btp
= XFS_DIR2_BLOCK_TAIL_P(mp
, d
);
1735 blp
= XFS_DIR2_BLOCK_LEAF_P_ARCH(btp
, ARCH_CONVERT
);
1736 endptr
= (char *)blp
;
1737 if (endptr
> (char *)btp
)
1738 endptr
= (char *)btp
;
1739 wantmagic
= XFS_DIR2_BLOCK_MAGIC
;
1741 endptr
= (char *)d
+ mp
->m_dirblksize
;
1742 wantmagic
= XFS_DIR2_DATA_MAGIC
;
1744 db
= XFS_DIR2_DA_TO_DB(mp
, da_bno
);
1745 if (freetab
->naents
<= db
) {
1746 struct freetab_ent e
;
1748 *freetabp
= freetab
= realloc(freetab
, FREETAB_SIZE(db
+ 1));
1751 "realloc failed in longform_dir2_entry_check_data (%u bytes)\n",
1752 FREETAB_SIZE(db
+ 1));
1757 for (i
= freetab
->naents
; i
< db
; i
++)
1758 freetab
->ents
[i
] = e
;
1759 freetab
->naents
= db
+ 1;
1761 if (freetab
->nents
< db
+ 1)
1762 freetab
->nents
= db
+ 1;
1763 while (ptr
< endptr
) {
1764 dup
= (xfs_dir2_data_unused_t
*)ptr
;
1765 if (INT_GET(dup
->freetag
, ARCH_CONVERT
) == XFS_DIR2_DATA_FREE_TAG
) {
1766 if (ptr
+ INT_GET(dup
->length
, ARCH_CONVERT
) > endptr
|| INT_GET(dup
->length
, ARCH_CONVERT
) == 0 ||
1767 (INT_GET(dup
->length
, ARCH_CONVERT
) & (XFS_DIR2_DATA_ALIGN
- 1)))
1769 if (INT_GET(*XFS_DIR2_DATA_UNUSED_TAG_P_ARCH(dup
, ARCH_CONVERT
), ARCH_CONVERT
) !=
1770 (char *)dup
- (char *)d
)
1772 ptr
+= INT_GET(dup
->length
, ARCH_CONVERT
);
1776 dep
= (xfs_dir2_data_entry_t
*)ptr
;
1777 if (ptr
+ XFS_DIR2_DATA_ENTSIZE(dep
->namelen
) > endptr
)
1779 if (INT_GET(*XFS_DIR2_DATA_ENTRY_TAG_P(dep
), ARCH_CONVERT
) != (char *)dep
- (char *)d
)
1781 ptr
+= XFS_DIR2_DATA_ENTSIZE(dep
->namelen
);
1783 if (ptr
!= endptr
) {
1784 do_warn("corrupt block %u in directory inode %llu: ",
1787 do_warn("junking block\n");
1788 dir2_kill_block(mp
, ip
, da_bno
, bp
);
1790 do_warn("would junk block\n");
1791 libxfs_da_brelse(NULL
, bp
);
1793 freetab
->ents
[db
].v
= NULLDATAOFF
;
1797 tp
= libxfs_trans_alloc(mp
, 0);
1798 error
= libxfs_trans_reserve(tp
, 0, XFS_REMOVE_LOG_RES(mp
), 0,
1799 XFS_TRANS_PERM_LOG_RES
, XFS_REMOVE_LOG_COUNT
);
1802 libxfs_trans_ijoin(tp
, ip
, 0);
1803 libxfs_trans_ihold(tp
, ip
);
1804 libxfs_da_bjoin(tp
, bp
);
1806 libxfs_da_bhold(tp
, bp
);
1807 XFS_BMAP_INIT(&flist
, &firstblock
);
1808 if (INT_GET(d
->hdr
.magic
, ARCH_CONVERT
) != wantmagic
) {
1809 do_warn("bad directory block magic # %#x for directory inode "
1811 INT_GET(d
->hdr
.magic
, ARCH_CONVERT
), ip
->i_ino
, da_bno
);
1813 do_warn("fixing magic # to %#x\n", wantmagic
);
1814 INT_SET(d
->hdr
.magic
, ARCH_CONVERT
, wantmagic
);
1817 do_warn("would fix magic # to %#x\n", wantmagic
);
1822 * look at each entry. reference inode pointed to by each
1823 * entry in the incore inode tree.
1824 * if not a directory, set reached flag, increment link count
1825 * if a directory and reached, mark entry as to be deleted.
1826 * if a directory, check to see if recorded parent
1827 * matches current inode #,
1828 * if so, then set reached flag, increment link count
1829 * of current and child dir inodes, push the child
1830 * directory inode onto the directory stack.
1831 * if current inode != parent, then mark entry to be deleted.
1833 while (ptr
< endptr
) {
1834 dup
= (xfs_dir2_data_unused_t
*)ptr
;
1835 if (INT_GET(dup
->freetag
, ARCH_CONVERT
) == XFS_DIR2_DATA_FREE_TAG
) {
1837 do_warn("directory inode %llu block %u has "
1838 "consecutive free entries: ",
1841 do_warn("joining together\n");
1842 len
= INT_GET(dup
->length
, ARCH_CONVERT
);
1843 libxfs_dir2_data_use_free(tp
, bp
, dup
,
1844 ptr
- (char *)d
, len
, &needlog
,
1846 libxfs_dir2_data_make_free(tp
, bp
,
1847 ptr
- (char *)d
, len
, &needlog
,
1850 do_warn("would join together\n");
1852 ptr
+= INT_GET(dup
->length
, ARCH_CONVERT
);
1856 addr
= XFS_DIR2_DB_OFF_TO_DATAPTR(mp
, db
, ptr
- (char *)d
);
1857 dep
= (xfs_dir2_data_entry_t
*)ptr
;
1858 ptr
+= XFS_DIR2_DATA_ENTSIZE(dep
->namelen
);
1860 dir_hash_add(hashtab
,
1861 libxfs_da_hashname((char *)dep
->name
, dep
->namelen
),
1862 addr
, dep
->name
[0] == '/');
1864 * skip bogus entries (leading '/'). they'll be deleted
1867 if (dep
->name
[0] == '/') {
1872 bcopy(dep
->name
, fname
, dep
->namelen
);
1873 fname
[dep
->namelen
] = '\0';
1874 ASSERT(INT_GET(dep
->inumber
, ARCH_CONVERT
) != NULLFSINO
);
1876 * skip the '..' entry since it's checked when the
1877 * directory is reached by something else. if it never
1878 * gets reached, it'll be moved to the orphanage and we'll
1879 * take care of it then.
1881 if (dep
->namelen
== 2 && dep
->name
[0] == '.' &&
1882 dep
->name
[1] == '.')
1884 ASSERT(no_modify
|| !verify_inum(mp
, INT_GET(dep
->inumber
, ARCH_CONVERT
)));
1886 * special case the . entry. we know there's only one
1887 * '.' and only '.' points to itself because bogus entries
1888 * got trashed in phase 3 if there were > 1.
1889 * bump up link count for '.' but don't set reached
1890 * until we're actually reached by another directory
1891 * '..' is already accounted for or will be taken care
1892 * of when directory is moved to orphanage.
1894 if (ip
->i_ino
== INT_GET(dep
->inumber
, ARCH_CONVERT
)) {
1895 ASSERT(dep
->name
[0] == '.' && dep
->namelen
== 1);
1896 add_inode_ref(current_irec
, current_ino_offset
);
1901 * special case the "lost+found" entry if pointing
1902 * to where we think lost+found should be. if that's
1903 * the case, that's the one we created in phase 6.
1904 * just skip it. no need to process it and it's ..
1905 * link is already accounted for.
1907 if (INT_GET(dep
->inumber
, ARCH_CONVERT
) == orphanage_ino
&&
1908 strcmp(fname
, ORPHANAGE
) == 0)
1911 * skip entries with bogus inumbers if we're in no modify mode
1913 if (no_modify
&& verify_inum(mp
, INT_GET(dep
->inumber
, ARCH_CONVERT
)))
1916 * ok, now handle the rest of the cases besides '.' and '..'
1918 irec
= find_inode_rec(XFS_INO_TO_AGNO(mp
, INT_GET(dep
->inumber
, ARCH_CONVERT
)),
1919 XFS_INO_TO_AGINO(mp
, INT_GET(dep
->inumber
, ARCH_CONVERT
)));
1922 do_warn("entry \"%s\" in directory inode %llu points "
1923 "to non-existent inode, ",
1927 libxfs_dir2_data_log_entry(tp
, bp
, dep
);
1928 do_warn("marking entry to be junked\n");
1930 do_warn("would junk entry\n");
1935 XFS_INO_TO_AGINO(mp
, INT_GET(dep
->inumber
, ARCH_CONVERT
)) - irec
->ino_startnum
;
1937 * if it's a free inode, blow out the entry.
1938 * by now, any inode that we think is free
1941 if (is_inode_free(irec
, ino_offset
)) {
1943 * don't complain if this entry points to the old
1944 * and now-free lost+found inode
1946 if (verbose
|| no_modify
||
1947 INT_GET(dep
->inumber
, ARCH_CONVERT
) != old_orphanage_ino
)
1948 do_warn("entry \"%s\" in directory inode %llu "
1949 "points to free inode %llu",
1950 fname
, ip
->i_ino
, INT_GET(dep
->inumber
, ARCH_CONVERT
));
1954 INT_GET(dep
->inumber
, ARCH_CONVERT
) != old_orphanage_ino
)
1955 do_warn(", marking entry to be "
1960 libxfs_dir2_data_log_entry(tp
, bp
, dep
);
1962 do_warn(", would junk entry\n");
1967 * check easy case first, regular inode, just bump
1968 * the link count and continue
1970 if (!inode_isadir(irec
, ino_offset
)) {
1971 add_inode_reached(irec
, ino_offset
);
1974 parent
= get_inode_parent(irec
, ino_offset
);
1975 ASSERT(parent
!= 0);
1977 * bump up the link counts in parent and child
1978 * directory but if the link doesn't agree with
1979 * the .. in the child, blow out the entry.
1980 * if the directory has already been reached,
1981 * blow away the entry also.
1983 if (is_inode_reached(irec
, ino_offset
)) {
1985 do_warn("entry \"%s\" in dir %llu points to an already "
1986 "connected directory inode %llu,\n", fname
,
1987 ip
->i_ino
, INT_GET(dep
->inumber
, ARCH_CONVERT
));
1988 } else if (parent
== ip
->i_ino
) {
1989 add_inode_reached(irec
, ino_offset
);
1990 add_inode_ref(current_irec
, current_ino_offset
);
1991 if (!is_inode_refchecked(INT_GET(dep
->inumber
, ARCH_CONVERT
), irec
,
1993 push_dir(stack
, INT_GET(dep
->inumber
, ARCH_CONVERT
));
1996 do_warn("entry \"%s\" in directory inode %llu not "
1997 "consistent with .. value (%llu) in ino "
1999 fname
, ip
->i_ino
, parent
, INT_GET(dep
->inumber
, ARCH_CONVERT
));
2006 libxfs_dir2_data_log_entry(tp
, bp
, dep
);
2008 INT_GET(dep
->inumber
, ARCH_CONVERT
) != old_orphanage_ino
)
2009 do_warn("\twill clear entry \"%s\"\n",
2012 do_warn("\twould clear entry \"%s\"\n", fname
);
2016 *num_illegal
+= nbad
;
2018 libxfs_dir2_data_freescan(mp
, d
, &needlog
, NULL
);
2020 libxfs_dir2_data_log_header(tp
, bp
);
2021 libxfs_bmap_finish(&tp
, &flist
, firstblock
, &committed
);
2022 libxfs_trans_commit(tp
, 0, 0);
2023 freetab
->ents
[db
].v
= INT_GET(d
->hdr
.bestfree
[0].length
, ARCH_CONVERT
);
2024 freetab
->ents
[db
].s
= 0;
2028 * Check contents of leaf-form block.
2031 longform_dir2_check_leaf(
2034 dir_hash_tab_t
*hashtab
,
2038 xfs_dir2_data_off_t
*bestsp
;
2042 xfs_dir2_leaf_t
*leaf
;
2043 xfs_dir2_leaf_tail_t
*ltp
;
2046 da_bno
= mp
->m_dirleafblk
;
2047 if (libxfs_da_read_bufr(NULL
, ip
, da_bno
, -1, &bp
, XFS_DATA_FORK
)) {
2048 do_error("can't read block %u for directory inode %llu\n",
2053 ltp
= XFS_DIR2_LEAF_TAIL_P(mp
, leaf
);
2054 bestsp
= XFS_DIR2_LEAF_BESTS_P_ARCH(ltp
, ARCH_CONVERT
);
2055 if (INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
) != XFS_DIR2_LEAF1_MAGIC
||
2056 INT_GET(leaf
->hdr
.info
.forw
, ARCH_CONVERT
) || INT_GET(leaf
->hdr
.info
.back
, ARCH_CONVERT
) ||
2057 INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
) < INT_GET(leaf
->hdr
.stale
, ARCH_CONVERT
) ||
2058 INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
) > XFS_DIR2_MAX_LEAF_ENTS(mp
) ||
2059 (char *)&leaf
->ents
[INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
)] > (char *)bestsp
) {
2060 do_warn("leaf block %u for directory inode %llu bad header\n",
2062 libxfs_da_brelse(NULL
, bp
);
2065 seeval
= dir_hash_see_all(hashtab
, leaf
->ents
, INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
),
2066 INT_GET(leaf
->hdr
.stale
, ARCH_CONVERT
));
2067 if (dir_hash_check(hashtab
, ip
, seeval
)) {
2068 libxfs_da_brelse(NULL
, bp
);
2071 badtail
= freetab
->nents
!= INT_GET(ltp
->bestcount
, ARCH_CONVERT
);
2072 for (i
= 0; !badtail
&& i
< INT_GET(ltp
->bestcount
, ARCH_CONVERT
); i
++) {
2073 freetab
->ents
[i
].s
= 1;
2074 badtail
= freetab
->ents
[i
].v
!= INT_GET(bestsp
[i
], ARCH_CONVERT
);
2077 do_warn("leaf block %u for directory inode %llu bad tail\n",
2079 libxfs_da_brelse(NULL
, bp
);
2082 libxfs_da_brelse(NULL
, bp
);
2087 * Check contents of the node blocks (leaves)
2088 * Looks for matching hash values for the data entries.
2091 longform_dir2_check_node(
2094 dir_hash_tab_t
*hashtab
,
2100 xfs_dir2_free_t
*free
;
2102 xfs_dir2_leaf_t
*leaf
;
2103 xfs_fileoff_t next_da_bno
;
2107 for (da_bno
= mp
->m_dirleafblk
, next_da_bno
= 0;
2108 next_da_bno
!= NULLFILEOFF
&& da_bno
< mp
->m_dirfreeblk
;
2109 da_bno
= (xfs_dablk_t
)next_da_bno
) {
2110 next_da_bno
= da_bno
+ mp
->m_dirblkfsbs
- 1;
2111 if (libxfs_bmap_next_offset(NULL
, ip
, &next_da_bno
, XFS_DATA_FORK
))
2113 if (libxfs_da_read_bufr(NULL
, ip
, da_bno
, -1, &bp
,
2115 do_error("can't read block %u for directory inode "
2121 if (INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
) != XFS_DIR2_LEAFN_MAGIC
) {
2122 if (INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
) == XFS_DA_NODE_MAGIC
) {
2123 libxfs_da_brelse(NULL
, bp
);
2126 do_warn("unknown magic number %#x for block %u in "
2127 "directory inode %llu\n",
2128 INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
), da_bno
, ip
->i_ino
);
2129 libxfs_da_brelse(NULL
, bp
);
2132 if (INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
) < INT_GET(leaf
->hdr
.stale
, ARCH_CONVERT
) ||
2133 INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
) > XFS_DIR2_MAX_LEAF_ENTS(mp
)) {
2134 do_warn("leaf block %u for directory inode %llu bad "
2137 libxfs_da_brelse(NULL
, bp
);
2140 seeval
= dir_hash_see_all(hashtab
, leaf
->ents
, INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
),
2141 INT_GET(leaf
->hdr
.stale
, ARCH_CONVERT
));
2142 libxfs_da_brelse(NULL
, bp
);
2143 if (seeval
!= DIR_HASH_CK_OK
)
2146 if (dir_hash_check(hashtab
, ip
, seeval
))
2148 for (da_bno
= mp
->m_dirfreeblk
, next_da_bno
= 0;
2149 next_da_bno
!= NULLFILEOFF
;
2150 da_bno
= (xfs_dablk_t
)next_da_bno
) {
2151 next_da_bno
= da_bno
+ mp
->m_dirblkfsbs
- 1;
2152 if (libxfs_bmap_next_offset(NULL
, ip
, &next_da_bno
, XFS_DATA_FORK
))
2154 if (libxfs_da_read_bufr(NULL
, ip
, da_bno
, -1, &bp
,
2156 do_error("can't read block %u for directory inode "
2162 fdb
= XFS_DIR2_DA_TO_DB(mp
, da_bno
);
2163 if (INT_GET(free
->hdr
.magic
, ARCH_CONVERT
) != XFS_DIR2_FREE_MAGIC
||
2164 INT_GET(free
->hdr
.firstdb
, ARCH_CONVERT
) !=
2165 (fdb
- XFS_DIR2_FREE_FIRSTDB(mp
)) *
2166 XFS_DIR2_MAX_FREE_BESTS(mp
) ||
2167 INT_GET(free
->hdr
.nvalid
, ARCH_CONVERT
) < INT_GET(free
->hdr
.nused
, ARCH_CONVERT
)) {
2168 do_warn("free block %u for directory inode %llu bad "
2171 libxfs_da_brelse(NULL
, bp
);
2174 for (i
= used
= 0; i
< INT_GET(free
->hdr
.nvalid
, ARCH_CONVERT
); i
++) {
2175 if (i
+ INT_GET(free
->hdr
.firstdb
, ARCH_CONVERT
) >= freetab
->nents
||
2176 freetab
->ents
[i
+ INT_GET(free
->hdr
.firstdb
, ARCH_CONVERT
)].v
!=
2177 INT_GET(free
->bests
[i
], ARCH_CONVERT
)) {
2178 do_warn("free block %u entry %i for directory "
2180 da_bno
, i
, ip
->i_ino
);
2181 libxfs_da_brelse(NULL
, bp
);
2184 used
+= INT_GET(free
->bests
[i
], ARCH_CONVERT
) != NULLDATAOFF
;
2185 freetab
->ents
[i
+ INT_GET(free
->hdr
.firstdb
, ARCH_CONVERT
)].s
= 1;
2187 if (used
!= INT_GET(free
->hdr
.nused
, ARCH_CONVERT
)) {
2188 do_warn("free block %u for directory inode %llu bad "
2191 libxfs_da_brelse(NULL
, bp
);
2194 libxfs_da_brelse(NULL
, bp
);
2196 for (i
= 0; i
< freetab
->nents
; i
++) {
2197 if (freetab
->ents
[i
].s
== 0) {
2198 do_warn("missing freetab entry %u for directory inode "
2208 * Rebuild a directory: set up.
2209 * Turn it into a node-format directory with no contents in the
2210 * upper area. Also has correct freespace blocks.
2213 longform_dir2_rebuild_setup(
2221 xfs_dir2_data_t
*data
;
2226 xfs_fsblock_t firstblock
;
2227 xfs_bmap_free_t flist
;
2228 xfs_dir2_free_t
*free
;
2233 xfs_dir2_leaf_t
*leaf
;
2237 tp
= libxfs_trans_alloc(mp
, 0);
2238 nres
= XFS_DAENTER_SPACE_RES(mp
, XFS_DATA_FORK
);
2239 error
= libxfs_trans_reserve(tp
,
2240 nres
, XFS_CREATE_LOG_RES(mp
), 0, XFS_TRANS_PERM_LOG_RES
,
2241 XFS_CREATE_LOG_COUNT
);
2244 libxfs_trans_ijoin(tp
, ip
, 0);
2245 libxfs_trans_ihold(tp
, ip
);
2246 XFS_BMAP_INIT(&flist
, &firstblock
);
2247 if (libxfs_da_read_buf(tp
, ip
, mp
->m_dirdatablk
, -2, &dbp
,
2249 do_error("can't read block %u for directory inode %llu\n",
2250 mp
->m_dirdatablk
, ino
);
2253 if (dbp
&& (data
= dbp
->data
)->hdr
.magic
== XFS_DIR2_BLOCK_MAGIC
) {
2254 xfs_dir2_block_t
*block
;
2255 xfs_dir2_leaf_entry_t
*blp
;
2256 xfs_dir2_block_tail_t
*btp
;
2260 INT_SET(data
->hdr
.magic
, ARCH_CONVERT
, XFS_DIR2_DATA_MAGIC
);
2261 block
= (xfs_dir2_block_t
*)data
;
2262 btp
= XFS_DIR2_BLOCK_TAIL_P(mp
, block
);
2263 blp
= XFS_DIR2_BLOCK_LEAF_P_ARCH(btp
, ARCH_CONVERT
);
2264 needlog
= needscan
= 0;
2265 libxfs_dir2_data_make_free(tp
, dbp
, (char *)blp
- (char *)block
,
2266 (char *)block
+ mp
->m_dirblksize
- (char *)blp
,
2267 &needlog
, &needscan
);
2269 libxfs_dir2_data_freescan(mp
, data
, &needlog
, NULL
);
2270 libxfs_da_log_buf(tp
, dbp
, 0, mp
->m_dirblksize
- 1);
2272 bzero(&args
, sizeof(args
));
2275 args
.whichfork
= XFS_DATA_FORK
;
2276 args
.firstblock
= &firstblock
;
2277 args
.flist
= &flist
;
2279 if ((error
= libxfs_da_grow_inode(&args
, &lblkno
)) ||
2280 (error
= libxfs_da_get_buf(tp
, ip
, lblkno
, -1, &lbp
, XFS_DATA_FORK
))) {
2281 do_error("can't add btree block to directory inode %llu\n",
2286 bzero(leaf
, mp
->m_dirblksize
);
2287 INT_SET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
, XFS_DIR2_LEAFN_MAGIC
);
2288 libxfs_da_log_buf(tp
, lbp
, 0, mp
->m_dirblksize
- 1);
2289 libxfs_bmap_finish(&tp
, &flist
, firstblock
, &committed
);
2290 libxfs_trans_commit(tp
, 0, 0);
2292 for (i
= 0; i
< freetab
->nents
; i
+= XFS_DIR2_MAX_FREE_BESTS(mp
)) {
2293 tp
= libxfs_trans_alloc(mp
, 0);
2294 nres
= XFS_DAENTER_SPACE_RES(mp
, XFS_DATA_FORK
);
2295 error
= libxfs_trans_reserve(tp
,
2296 nres
, XFS_CREATE_LOG_RES(mp
), 0, XFS_TRANS_PERM_LOG_RES
,
2297 XFS_CREATE_LOG_COUNT
);
2300 libxfs_trans_ijoin(tp
, ip
, 0);
2301 libxfs_trans_ihold(tp
, ip
);
2302 XFS_BMAP_INIT(&flist
, &firstblock
);
2303 bzero(&args
, sizeof(args
));
2306 args
.whichfork
= XFS_DATA_FORK
;
2307 args
.firstblock
= &firstblock
;
2308 args
.flist
= &flist
;
2310 if ((error
= libxfs_dir2_grow_inode(&args
, XFS_DIR2_FREE_SPACE
,
2312 (error
= libxfs_da_get_buf(tp
, ip
, XFS_DIR2_DB_TO_DA(mp
, fbno
),
2313 -1, &fbp
, XFS_DATA_FORK
))) {
2314 do_error("can't add free block to directory inode "
2320 bzero(free
, mp
->m_dirblksize
);
2321 INT_SET(free
->hdr
.magic
, ARCH_CONVERT
, XFS_DIR2_FREE_MAGIC
);
2322 INT_SET(free
->hdr
.firstdb
, ARCH_CONVERT
, i
);
2323 INT_SET(free
->hdr
.nvalid
, ARCH_CONVERT
, XFS_DIR2_MAX_FREE_BESTS(mp
));
2324 if (i
+ INT_GET(free
->hdr
.nvalid
, ARCH_CONVERT
) > freetab
->nents
)
2325 INT_SET(free
->hdr
.nvalid
, ARCH_CONVERT
, freetab
->nents
- i
);
2326 for (j
= 0; j
< INT_GET(free
->hdr
.nvalid
, ARCH_CONVERT
); j
++) {
2327 INT_SET(free
->bests
[j
], ARCH_CONVERT
, freetab
->ents
[i
+ j
].v
);
2328 if (INT_GET(free
->bests
[j
], ARCH_CONVERT
) != NULLDATAOFF
)
2329 INT_MOD(free
->hdr
.nused
, ARCH_CONVERT
, +1);
2331 libxfs_da_log_buf(tp
, fbp
, 0, mp
->m_dirblksize
- 1);
2332 libxfs_bmap_finish(&tp
, &flist
, firstblock
, &committed
);
2333 libxfs_trans_commit(tp
, 0, 0);
2338 * Rebuild the entries from a single data block.
2341 longform_dir2_rebuild_data(
2348 xfs_dir2_block_tail_t
*btp
;
2350 xfs_dir2_data_t
*data
;
2352 xfs_dir2_data_entry_t
*dep
;
2353 xfs_dir2_data_unused_t
*dup
;
2356 xfs_dir2_free_t
*fblock
;
2360 xfs_fsblock_t firstblock
;
2361 xfs_bmap_free_t flist
;
2368 if (libxfs_da_read_buf(NULL
, ip
, da_bno
, da_bno
== 0 ? -2 : -1, &bp
,
2370 do_error("can't read block %u for directory inode %llu\n",
2374 if (da_bno
== 0 && bp
== NULL
)
2376 * The block was punched out.
2380 dbno
= XFS_DIR2_DA_TO_DB(mp
, da_bno
);
2381 fdb
= XFS_DIR2_DB_TO_FDB(mp
, dbno
);
2382 if (libxfs_da_read_buf(NULL
, ip
, XFS_DIR2_DB_TO_DA(mp
, fdb
), -1, &fbp
,
2384 do_error("can't read block %u for directory inode %llu\n",
2385 XFS_DIR2_DB_TO_DA(mp
, fdb
), ino
);
2388 data
= malloc(mp
->m_dirblksize
);
2391 "malloc failed in longform_dir2_rebuild_data (%u bytes)\n",
2395 bcopy(bp
->data
, data
, mp
->m_dirblksize
);
2396 ptr
= (char *)data
->u
;
2397 if (INT_GET(data
->hdr
.magic
, ARCH_CONVERT
) == XFS_DIR2_BLOCK_MAGIC
) {
2398 btp
= XFS_DIR2_BLOCK_TAIL_P(mp
, (xfs_dir2_block_t
*)data
);
2399 endptr
= (char *)XFS_DIR2_BLOCK_LEAF_P_ARCH(btp
, ARCH_CONVERT
);
2401 endptr
= (char *)data
+ mp
->m_dirblksize
;
2403 fi
= XFS_DIR2_DB_TO_FDINDEX(mp
, dbno
);
2404 tp
= libxfs_trans_alloc(mp
, 0);
2405 error
= libxfs_trans_reserve(tp
, 0, XFS_CREATE_LOG_RES(mp
), 0,
2406 XFS_TRANS_PERM_LOG_RES
, XFS_CREATE_LOG_COUNT
);
2409 libxfs_trans_ijoin(tp
, ip
, 0);
2410 libxfs_trans_ihold(tp
, ip
);
2411 libxfs_da_bjoin(tp
, bp
);
2412 libxfs_da_bhold(tp
, bp
);
2413 libxfs_da_bjoin(tp
, fbp
);
2414 libxfs_da_bhold(tp
, fbp
);
2415 XFS_BMAP_INIT(&flist
, &firstblock
);
2416 needlog
= needscan
= 0;
2417 bzero(((xfs_dir2_data_t
*)(bp
->data
))->hdr
.bestfree
,
2418 sizeof(data
->hdr
.bestfree
));
2419 libxfs_dir2_data_make_free(tp
, bp
, (xfs_dir2_data_aoff_t
)sizeof(data
->hdr
),
2420 mp
->m_dirblksize
- sizeof(data
->hdr
), &needlog
, &needscan
);
2421 ASSERT(needscan
== 0);
2422 libxfs_dir2_data_log_header(tp
, bp
);
2423 INT_SET(fblock
->bests
[fi
], ARCH_CONVERT
,
2424 INT_GET(((xfs_dir2_data_t
*)(bp
->data
))->hdr
.bestfree
[0].length
, ARCH_CONVERT
));
2425 libxfs_dir2_free_log_bests(tp
, fbp
, fi
, fi
);
2426 libxfs_bmap_finish(&tp
, &flist
, firstblock
, &committed
);
2427 libxfs_trans_commit(tp
, 0, 0);
2429 while (ptr
< endptr
) {
2430 dup
= (xfs_dir2_data_unused_t
*)ptr
;
2431 if (INT_GET(dup
->freetag
, ARCH_CONVERT
) == XFS_DIR2_DATA_FREE_TAG
) {
2432 ptr
+= INT_GET(dup
->length
, ARCH_CONVERT
);
2435 dep
= (xfs_dir2_data_entry_t
*)ptr
;
2436 ptr
+= XFS_DIR2_DATA_ENTSIZE(dep
->namelen
);
2437 if (dep
->name
[0] == '/')
2439 tp
= libxfs_trans_alloc(mp
, 0);
2440 nres
= XFS_CREATE_SPACE_RES(mp
, dep
->namelen
);
2441 error
= libxfs_trans_reserve(tp
, nres
, XFS_CREATE_LOG_RES(mp
), 0,
2442 XFS_TRANS_PERM_LOG_RES
, XFS_CREATE_LOG_COUNT
);
2445 libxfs_trans_ijoin(tp
, ip
, 0);
2446 libxfs_trans_ihold(tp
, ip
);
2447 libxfs_da_bjoin(tp
, bp
);
2448 libxfs_da_bhold(tp
, bp
);
2449 libxfs_da_bjoin(tp
, fbp
);
2450 libxfs_da_bhold(tp
, fbp
);
2451 XFS_BMAP_INIT(&flist
, &firstblock
);
2452 error
= dir_createname(mp
, tp
, ip
, (char *)dep
->name
,
2453 dep
->namelen
, INT_GET(dep
->inumber
, ARCH_CONVERT
),
2454 &firstblock
, &flist
, nres
);
2456 libxfs_bmap_finish(&tp
, &flist
, firstblock
, &committed
);
2457 libxfs_trans_commit(tp
, 0, 0);
2459 libxfs_da_brelse(NULL
, bp
);
2460 libxfs_da_brelse(NULL
, fbp
);
2465 * Finish the rebuild of a directory.
2466 * Stuff / in and then remove it, this forces the directory to end
2467 * up in the right format.
2470 longform_dir2_rebuild_finish(
2477 xfs_fsblock_t firstblock
;
2478 xfs_bmap_free_t flist
;
2482 tp
= libxfs_trans_alloc(mp
, 0);
2483 nres
= XFS_CREATE_SPACE_RES(mp
, 1);
2484 error
= libxfs_trans_reserve(tp
, nres
, XFS_CREATE_LOG_RES(mp
), 0,
2485 XFS_TRANS_PERM_LOG_RES
, XFS_CREATE_LOG_COUNT
);
2488 libxfs_trans_ijoin(tp
, ip
, 0);
2489 libxfs_trans_ihold(tp
, ip
);
2490 XFS_BMAP_INIT(&flist
, &firstblock
);
2491 error
= dir_createname(mp
, tp
, ip
, "/", 1, ino
,
2492 &firstblock
, &flist
, nres
);
2494 libxfs_bmap_finish(&tp
, &flist
, firstblock
, &committed
);
2495 libxfs_trans_commit(tp
, 0, 0);
2497 /* could kill trailing empty data blocks here */
2499 tp
= libxfs_trans_alloc(mp
, 0);
2500 nres
= XFS_REMOVE_SPACE_RES(mp
);
2501 error
= libxfs_trans_reserve(tp
, nres
, XFS_REMOVE_LOG_RES(mp
), 0,
2502 XFS_TRANS_PERM_LOG_RES
, XFS_REMOVE_LOG_COUNT
);
2505 libxfs_trans_ijoin(tp
, ip
, 0);
2506 libxfs_trans_ihold(tp
, ip
);
2507 XFS_BMAP_INIT(&flist
, &firstblock
);
2508 error
= dir_removename(mp
, tp
, ip
, "/", 1, ino
,
2509 &firstblock
, &flist
, nres
);
2511 libxfs_bmap_finish(&tp
, &flist
, firstblock
, &committed
);
2512 libxfs_trans_commit(tp
, 0, 0);
2516 * Rebuild a directory.
2517 * Remove all the non-data blocks.
2518 * Re-initialize to (empty) node form.
2519 * Loop over the data blocks reinserting each entry.
2520 * Force the directory into the right format.
2523 longform_dir2_rebuild(
2533 xfs_fileoff_t next_da_bno
;
2535 do_warn("rebuilding directory inode %llu\n", ino
);
2536 for (da_bno
= mp
->m_dirleafblk
, next_da_bno
= isblock
? NULLFILEOFF
: 0;
2537 next_da_bno
!= NULLFILEOFF
;
2538 da_bno
= (xfs_dablk_t
)next_da_bno
) {
2539 next_da_bno
= da_bno
+ mp
->m_dirblkfsbs
- 1;
2540 if (libxfs_bmap_next_offset(NULL
, ip
, &next_da_bno
, XFS_DATA_FORK
))
2542 if (libxfs_da_get_buf(NULL
, ip
, da_bno
, -1, &bp
, XFS_DATA_FORK
)) {
2543 do_error("can't get block %u for directory inode "
2548 dir2_kill_block(mp
, ip
, da_bno
, bp
);
2550 longform_dir2_rebuild_setup(mp
, ino
, ip
, freetab
);
2551 for (da_bno
= mp
->m_dirdatablk
, next_da_bno
= 0;
2552 da_bno
< mp
->m_dirleafblk
&& next_da_bno
!= NULLFILEOFF
;
2553 da_bno
= (xfs_dablk_t
)next_da_bno
) {
2554 next_da_bno
= da_bno
+ mp
->m_dirblkfsbs
- 1;
2555 if (libxfs_bmap_next_offset(NULL
, ip
, &next_da_bno
, XFS_DATA_FORK
))
2557 longform_dir2_rebuild_data(mp
, ino
, ip
, da_bno
);
2559 longform_dir2_rebuild_finish(mp
, ino
, ip
);
2564 * succeeds or dies, inode never gets dirtied since all changes
2565 * happen in file blocks. the inode size and other core info
2566 * is already correct, it's just the leaf entries that get altered.
2567 * XXX above comment is wrong for v2 - need to see why it matters
2570 longform_dir2_entry_check(xfs_mount_t
*mp
,
2576 ino_tree_node_t
*irec
,
2579 xfs_dir2_block_t
*block
;
2580 xfs_dir2_leaf_entry_t
*blp
;
2582 xfs_dir2_block_tail_t
*btp
;
2585 dir_hash_tab_t
*hashtab
;
2589 xfs_fileoff_t next_da_bno
;
2594 freetab
= malloc(FREETAB_SIZE(ip
->i_d
.di_size
/ mp
->m_dirblksize
));
2597 "malloc failed in longform_dir2_entry_check (%u bytes)\n",
2598 FREETAB_SIZE(ip
->i_d
.di_size
/ mp
->m_dirblksize
));
2601 freetab
->naents
= ip
->i_d
.di_size
/ mp
->m_dirblksize
;
2603 for (i
= 0; i
< freetab
->naents
; i
++) {
2604 freetab
->ents
[i
].v
= NULLDATAOFF
;
2605 freetab
->ents
[i
].s
= 0;
2607 libxfs_dir2_isblock(NULL
, ip
, &isblock
);
2608 libxfs_dir2_isleaf(NULL
, ip
, &isleaf
);
2609 hashtab
= dir_hash_init(ip
->i_d
.di_size
);
2610 for (da_bno
= 0, next_da_bno
= 0;
2611 next_da_bno
!= NULLFILEOFF
&& da_bno
< mp
->m_dirleafblk
;
2612 da_bno
= (xfs_dablk_t
)next_da_bno
) {
2613 next_da_bno
= da_bno
+ mp
->m_dirblkfsbs
- 1;
2614 if (libxfs_bmap_next_offset(NULL
, ip
, &next_da_bno
, XFS_DATA_FORK
))
2616 if (libxfs_da_read_bufr(NULL
, ip
, da_bno
, -1, &bp
,
2618 do_error("can't read block %u for directory inode "
2623 longform_dir2_entry_check_data(mp
, ip
, num_illegal
, need_dot
,
2624 stack
, irec
, ino_offset
, &bp
, hashtab
, &freetab
, da_bno
,
2626 /* it releases the buffer unless isblock is set */
2628 fixit
= (*num_illegal
!= 0) || dir2_is_badino(ino
);
2632 btp
= XFS_DIR2_BLOCK_TAIL_P(mp
, block
);
2633 blp
= XFS_DIR2_BLOCK_LEAF_P_ARCH(btp
, ARCH_CONVERT
);
2634 seeval
= dir_hash_see_all(hashtab
, blp
, INT_GET(btp
->count
, ARCH_CONVERT
), INT_GET(btp
->stale
, ARCH_CONVERT
));
2635 if (dir_hash_check(hashtab
, ip
, seeval
))
2637 libxfs_da_brelse(NULL
, bp
);
2638 } else if (isleaf
) {
2639 fixit
|= longform_dir2_check_leaf(mp
, ip
, hashtab
, freetab
);
2641 fixit
|= longform_dir2_check_node(mp
, ip
, hashtab
, freetab
);
2643 dir_hash_done(hashtab
);
2644 if (!no_modify
&& fixit
)
2645 longform_dir2_rebuild(mp
, ino
, ip
, num_illegal
, freetab
,
2651 * shortform directory processing routines -- entry verification and
2652 * bad entry deletion (pruning).
2655 shortform_dir_entry_check(xfs_mount_t
*mp
,
2660 ino_tree_node_t
*current_irec
,
2661 int current_ino_offset
)
2665 xfs_dir_shortform_t
*sf
;
2666 xfs_dir_sf_entry_t
*sf_entry
, *next_sfe
, *tmp_sfe
;
2668 ino_tree_node_t
*irec
;
2678 char fname
[MAXNAMELEN
+ 1];
2681 sf
= (xfs_dir_shortform_t
*) ifp
->if_u1
.if_data
;
2685 max_size
= ifp
->if_bytes
;
2686 ASSERT(ip
->i_d
.di_size
<= ifp
->if_bytes
);
2689 * no '.' entry in shortform dirs, just bump up ref count by 1
2690 * '..' was already (or will be) accounted for and checked when
2691 * the directory is reached or will be taken care of when the
2692 * directory is moved to orphanage.
2694 add_inode_ref(current_irec
, current_ino_offset
);
2697 * now run through entries, stop at first bad entry, don't need
2698 * to skip over '..' since that's encoded in its own field and
2699 * no need to worry about '.' since it doesn't exist.
2701 sf_entry
= next_sfe
= &sf
->list
[0];
2704 do_warn("shortform dir inode %llu has null data entries \n", ino
);
2708 for (i
= 0; i
< INT_GET(sf
->hdr
.count
, ARCH_CONVERT
) && max_size
>
2709 (__psint_t
)next_sfe
- (__psint_t
)sf
;
2710 sf_entry
= next_sfe
, i
++) {
2715 XFS_DIR_SF_GET_DIRINO_ARCH(&sf_entry
->inumber
, &lino
, ARCH_CONVERT
);
2717 namelen
= sf_entry
->namelen
;
2719 ASSERT(no_modify
|| namelen
> 0);
2721 if (no_modify
&& namelen
== 0) {
2723 * if we're really lucky, this is
2724 * the last entry in which case we
2725 * can use the dir size to set the
2726 * namelen value. otherwise, forget
2727 * it because we're not going to be
2728 * able to find the next entry.
2732 if (i
== INT_GET(sf
->hdr
.count
, ARCH_CONVERT
) - 1) {
2733 namelen
= ip
->i_d
.di_size
-
2734 ((__psint_t
) &sf_entry
->name
[0] -
2738 * don't process the rest of the directory,
2739 * break out of processing looop
2743 } else if (no_modify
&& (__psint_t
) sf_entry
- (__psint_t
) sf
+
2744 + XFS_DIR_SF_ENTSIZE_BYENTRY(sf_entry
)
2745 > ip
->i_d
.di_size
) {
2748 if (i
== INT_GET(sf
->hdr
.count
, ARCH_CONVERT
) - 1) {
2749 namelen
= ip
->i_d
.di_size
-
2750 ((__psint_t
) &sf_entry
->name
[0] -
2754 * don't process the rest of the directory,
2755 * break out of processing looop
2761 bcopy(sf_entry
->name
, fname
, sf_entry
->namelen
);
2762 fname
[sf_entry
->namelen
] = '\0';
2764 ASSERT(no_modify
|| lino
!= NULLFSINO
);
2765 ASSERT(no_modify
|| !verify_inum(mp
, lino
));
2768 * special case the "lost+found" entry if it's pointing
2769 * to where we think lost+found should be. if that's
2770 * the case, that's the one we created in phase 6.
2771 * just skip it. no need to process it and its ..
2772 * link is already accounted for. Also skip entries
2773 * with bogus inode numbers if we're in no modify mode.
2776 if ((lino
== orphanage_ino
&& strcmp(fname
, ORPHANAGE
) == 0)
2777 || (no_modify
&& verify_inum(mp
, lino
))) {
2778 next_sfe
= (xfs_dir_sf_entry_t
*)
2779 ((__psint_t
) sf_entry
+
2780 XFS_DIR_SF_ENTSIZE_BYENTRY(sf_entry
));
2784 irec
= find_inode_rec(XFS_INO_TO_AGNO(mp
, lino
),
2785 XFS_INO_TO_AGINO(mp
, lino
));
2787 if (irec
== NULL
&& no_modify
) {
2789 "entry \"%s\" in shortform dir %llu references non-existent ino %llu\n",
2791 do_warn("would junk entry\n");
2795 ASSERT(irec
!= NULL
);
2797 ino_offset
= XFS_INO_TO_AGINO(mp
, lino
) - irec
->ino_startnum
;
2800 * if it's a free inode, blow out the entry.
2801 * by now, any inode that we think is free
2804 if (is_inode_free(irec
, ino_offset
)) {
2806 * don't complain if this entry points to the old
2807 * and now-free lost+found inode
2809 if (verbose
|| no_modify
|| lino
!= old_orphanage_ino
)
2811 "entry \"%s\" in shortform dir inode %llu points to free inode %llu\n",
2817 do_warn("would junk entry \"%s\"\n",
2820 } else if (!inode_isadir(irec
, ino_offset
)) {
2822 * check easy case first, regular inode, just bump
2823 * the link count and continue
2825 add_inode_reached(irec
, ino_offset
);
2827 next_sfe
= (xfs_dir_sf_entry_t
*)
2828 ((__psint_t
) sf_entry
+
2829 XFS_DIR_SF_ENTSIZE_BYENTRY(sf_entry
));
2832 parent
= get_inode_parent(irec
, ino_offset
);
2835 * bump up the link counts in parent and child.
2836 * directory but if the link doesn't agree with
2837 * the .. in the child, blow out the entry
2839 if (is_inode_reached(irec
, ino_offset
)) {
2842 "entry \"%s\" in dir %llu references already connected dir ino %llu,\n",
2844 } else if (parent
== ino
) {
2845 add_inode_reached(irec
, ino_offset
);
2846 add_inode_ref(current_irec
, current_ino_offset
);
2848 if (!is_inode_refchecked(lino
, irec
,
2850 push_dir(stack
, lino
);
2854 "entry \"%s\" in dir %llu not consistent with .. value (%llu) in dir ino %llu,\n",
2855 fname
, ino
, parent
, lino
);
2861 tmp_elen
= XFS_DIR_SF_ENTSIZE_BYENTRY(sf_entry
);
2862 tmp_sfe
= (xfs_dir_sf_entry_t
*)
2863 ((__psint_t
) sf_entry
+ tmp_elen
);
2864 tmp_len
= max_size
- ((__psint_t
) tmp_sfe
2866 max_size
-= tmp_elen
;
2867 bytes_deleted
+= tmp_elen
;
2869 memmove(sf_entry
, tmp_sfe
, tmp_len
);
2871 INT_MOD(sf
->hdr
.count
, ARCH_CONVERT
, -1);
2872 bzero((void *) ((__psint_t
) sf_entry
+ tmp_len
),
2876 * set the tmp value to the current
2877 * pointer so we'll process the entry
2883 * WARNING: drop the index i by one
2884 * so it matches the decremented count for
2885 * accurate comparisons in the loop test
2891 if (verbose
|| lino
!= old_orphanage_ino
)
2893 "junking entry \"%s\" in directory inode %llu\n",
2896 do_warn("would junk entry \"%s\"\n", fname
);
2901 * go onto next entry unless we've just junked an
2902 * entry in which the current entry pointer points
2903 * to an unprocessed entry. have to take into entries
2904 * with bad namelen into account in no modify mode since we
2905 * calculate size based on next_sfe.
2907 ASSERT(no_modify
|| bad_sfnamelen
== 0);
2909 next_sfe
= (tmp_sfe
== NULL
)
2910 ? (xfs_dir_sf_entry_t
*) ((__psint_t
) sf_entry
2912 ? XFS_DIR_SF_ENTSIZE_BYENTRY(sf_entry
)
2913 : sizeof(xfs_dir_sf_entry_t
) - 1
2920 * sync up sizes if required
2923 ASSERT(bytes_deleted
> 0);
2925 libxfs_idata_realloc(ip
, -bytes_deleted
, XFS_DATA_FORK
);
2926 ip
->i_d
.di_size
-= bytes_deleted
;
2929 if (ip
->i_d
.di_size
!= ip
->i_df
.if_bytes
) {
2930 ASSERT(ip
->i_df
.if_bytes
== (xfs_fsize_t
)
2931 ((__psint_t
) next_sfe
- (__psint_t
) sf
));
2932 ip
->i_d
.di_size
= (xfs_fsize_t
)
2933 ((__psint_t
) next_sfe
- (__psint_t
) sf
);
2935 "setting size to %lld bytes to reflect junked entries\n",
2943 prune_sf_dir_entry(xfs_mount_t
*mp
, xfs_ino_t ino
, xfs_inode_t
*ip
)
2947 xfs_dir_shortform_t
*sf
;
2948 xfs_dir_sf_entry_t
*sf_entry
, *next_sfe
, *tmp_sfe
;
2955 char fname
[MAXNAMELEN
+ 1];
2958 sf
= (xfs_dir_shortform_t
*) ifp
->if_u1
.if_data
;
2961 max_size
= ifp
->if_bytes
;
2962 ASSERT(ip
->i_d
.di_size
<= ifp
->if_bytes
);
2965 * now run through entries and delete every bad entry
2967 sf_entry
= next_sfe
= &sf
->list
[0];
2969 for (i
= 0; i
< INT_GET(sf
->hdr
.count
, ARCH_CONVERT
) && max_size
>
2970 (__psint_t
)next_sfe
- (__psint_t
)sf
;
2971 sf_entry
= next_sfe
, i
++) {
2974 XFS_DIR_SF_GET_DIRINO_ARCH(&sf_entry
->inumber
, &lino
, ARCH_CONVERT
);
2976 bcopy(sf_entry
->name
, fname
, sf_entry
->namelen
);
2977 fname
[sf_entry
->namelen
] = '\0';
2979 if (sf_entry
->name
[0] == '/') {
2981 tmp_elen
= XFS_DIR_SF_ENTSIZE_BYENTRY(sf_entry
);
2982 tmp_sfe
= (xfs_dir_sf_entry_t
*)
2983 ((__psint_t
) sf_entry
+ tmp_elen
);
2984 tmp_len
= max_size
- ((__psint_t
) tmp_sfe
2986 max_size
-= tmp_elen
;
2987 bytes_deleted
+= tmp_elen
;
2989 memmove(sf_entry
, tmp_sfe
, tmp_len
);
2991 INT_MOD(sf
->hdr
.count
, ARCH_CONVERT
, -1);
2992 bzero((void *) ((__psint_t
) sf_entry
+ tmp_len
),
2996 * set the tmp value to the current
2997 * pointer so we'll process the entry
3003 * WARNING: drop the index i by one
3004 * so it matches the decremented count for
3005 * accurate comparisons in the loop test
3010 next_sfe
= (tmp_sfe
== NULL
)
3011 ? (xfs_dir_sf_entry_t
*) ((__psint_t
) sf_entry
+
3012 XFS_DIR_SF_ENTSIZE_BYENTRY(sf_entry
))
3017 * sync up sizes if required
3019 if (bytes_deleted
> 0) {
3020 libxfs_idata_realloc(ip
, -bytes_deleted
, XFS_DATA_FORK
);
3021 ip
->i_d
.di_size
-= bytes_deleted
;
3024 if (ip
->i_d
.di_size
!= ip
->i_df
.if_bytes
) {
3025 ASSERT(ip
->i_df
.if_bytes
== (xfs_fsize_t
)
3026 ((__psint_t
) next_sfe
- (__psint_t
) sf
));
3027 ip
->i_d
.di_size
= (xfs_fsize_t
)
3028 ((__psint_t
) next_sfe
- (__psint_t
) sf
);
3030 "setting size to %lld bytes to reflect junked entries\n",
3036 * shortform directory v2 processing routines -- entry verification and
3037 * bad entry deletion (pruning).
3040 shortform_dir2_entry_check(xfs_mount_t
*mp
,
3045 ino_tree_node_t
*current_irec
,
3046 int current_ino_offset
)
3051 xfs_dir2_sf_entry_t
*sfep
, *next_sfep
, *tmp_sfep
;
3053 ino_tree_node_t
*irec
;
3063 char fname
[MAXNAMELEN
+ 1];
3067 sfp
= (xfs_dir2_sf_t
*) ifp
->if_u1
.if_data
;
3069 bytes_deleted
= i8
= 0;
3071 max_size
= ifp
->if_bytes
;
3072 ASSERT(ip
->i_d
.di_size
<= ifp
->if_bytes
);
3075 * no '.' entry in shortform dirs, just bump up ref count by 1
3076 * '..' was already (or will be) accounted for and checked when
3077 * the directory is reached or will be taken care of when the
3078 * directory is moved to orphanage.
3080 add_inode_ref(current_irec
, current_ino_offset
);
3083 * now run through entries, stop at first bad entry, don't need
3084 * to skip over '..' since that's encoded in its own field and
3085 * no need to worry about '.' since it doesn't exist.
3087 sfep
= next_sfep
= XFS_DIR2_SF_FIRSTENTRY(sfp
);
3089 for (i
= 0; i
< INT_GET(sfp
->hdr
.count
, ARCH_CONVERT
) && max_size
>
3090 (__psint_t
)next_sfep
- (__psint_t
)sfp
;
3091 sfep
= next_sfep
, i
++) {
3096 lino
= XFS_DIR2_SF_GET_INUMBER_ARCH(sfp
, XFS_DIR2_SF_INUMBERP(sfep
), ARCH_CONVERT
);
3098 namelen
= sfep
->namelen
;
3100 ASSERT(no_modify
|| namelen
> 0);
3102 if (no_modify
&& namelen
== 0) {
3104 * if we're really lucky, this is
3105 * the last entry in which case we
3106 * can use the dir size to set the
3107 * namelen value. otherwise, forget
3108 * it because we're not going to be
3109 * able to find the next entry.
3113 if (i
== INT_GET(sfp
->hdr
.count
, ARCH_CONVERT
) - 1) {
3114 namelen
= ip
->i_d
.di_size
-
3115 ((__psint_t
) &sfep
->name
[0] -
3119 * don't process the rest of the directory,
3120 * break out of processing loop
3124 } else if (no_modify
&& (__psint_t
) sfep
- (__psint_t
) sfp
+
3125 + XFS_DIR2_SF_ENTSIZE_BYENTRY(sfp
, sfep
)
3126 > ip
->i_d
.di_size
) {
3129 if (i
== INT_GET(sfp
->hdr
.count
, ARCH_CONVERT
) - 1) {
3130 namelen
= ip
->i_d
.di_size
-
3131 ((__psint_t
) &sfep
->name
[0] -
3135 * don't process the rest of the directory,
3136 * break out of processing loop
3142 bcopy(sfep
->name
, fname
, sfep
->namelen
);
3143 fname
[sfep
->namelen
] = '\0';
3145 ASSERT(no_modify
|| (lino
!= NULLFSINO
&& lino
!= 0));
3146 ASSERT(no_modify
|| !verify_inum(mp
, lino
));
3149 * special case the "lost+found" entry if it's pointing
3150 * to where we think lost+found should be. if that's
3151 * the case, that's the one we created in phase 6.
3152 * just skip it. no need to process it and its ..
3153 * link is already accounted for. Also skip entries
3154 * with bogus inode numbers if we're in no modify mode.
3157 if ((lino
== orphanage_ino
&& strcmp(fname
, ORPHANAGE
) == 0)
3158 || (no_modify
&& verify_inum(mp
, lino
))) {
3159 next_sfep
= (xfs_dir2_sf_entry_t
*)
3161 XFS_DIR2_SF_ENTSIZE_BYENTRY(sfp
, sfep
));
3165 irec
= find_inode_rec(XFS_INO_TO_AGNO(mp
, lino
),
3166 XFS_INO_TO_AGINO(mp
, lino
));
3168 if (irec
== NULL
&& no_modify
) {
3169 do_warn("entry \"%s\" in shortform directory %llu "
3170 "references non-existent inode %llu\n",
3172 do_warn("would junk entry\n");
3176 ASSERT(irec
!= NULL
);
3178 ino_offset
= XFS_INO_TO_AGINO(mp
, lino
) - irec
->ino_startnum
;
3181 * if it's a free inode, blow out the entry.
3182 * by now, any inode that we think is free
3185 if (is_inode_free(irec
, ino_offset
)) {
3187 * don't complain if this entry points to the old
3188 * and now-free lost+found inode
3190 if (verbose
|| no_modify
|| lino
!= old_orphanage_ino
)
3191 do_warn("entry \"%s\" in shortform directory "
3192 "inode %llu points to free inode "
3199 do_warn("would junk entry \"%s\"\n",
3202 } else if (!inode_isadir(irec
, ino_offset
)) {
3204 * check easy case first, regular inode, just bump
3205 * the link count and continue
3207 add_inode_reached(irec
, ino_offset
);
3209 next_sfep
= (xfs_dir2_sf_entry_t
*)
3211 XFS_DIR2_SF_ENTSIZE_BYENTRY(sfp
, sfep
));
3214 parent
= get_inode_parent(irec
, ino_offset
);
3217 * bump up the link counts in parent and child.
3218 * directory but if the link doesn't agree with
3219 * the .. in the child, blow out the entry
3221 if (is_inode_reached(irec
, ino_offset
)) {
3223 do_warn("entry \"%s\" in directory inode %llu "
3224 "references already connected inode "
3227 } else if (parent
== ino
) {
3228 add_inode_reached(irec
, ino_offset
);
3229 add_inode_ref(current_irec
, current_ino_offset
);
3231 if (!is_inode_refchecked(lino
, irec
,
3233 push_dir(stack
, lino
);
3236 do_warn("entry \"%s\" in directory inode %llu "
3237 "not consistent with .. value (%llu) "
3239 fname
, ino
, parent
, lino
);
3245 tmp_elen
= XFS_DIR2_SF_ENTSIZE_BYENTRY(sfp
, sfep
);
3246 tmp_sfep
= (xfs_dir2_sf_entry_t
*)
3247 ((__psint_t
) sfep
+ tmp_elen
);
3248 tmp_len
= max_size
- ((__psint_t
) tmp_sfep
3250 max_size
-= tmp_elen
;
3251 bytes_deleted
+= tmp_elen
;
3253 memmove(sfep
, tmp_sfep
, tmp_len
);
3255 INT_MOD(sfp
->hdr
.count
, ARCH_CONVERT
, -1);
3256 bzero((void *) ((__psint_t
) sfep
+ tmp_len
),
3260 * set the tmp value to the current
3261 * pointer so we'll process the entry
3267 * WARNING: drop the index i by one
3268 * so it matches the decremented count for
3269 * accurate comparisons in the loop test
3275 if (verbose
|| lino
!= old_orphanage_ino
)
3276 do_warn("junking entry \"%s\" in "
3277 "directory inode %llu\n",
3280 do_warn("would junk entry \"%s\"\n", fname
);
3282 } else if (lino
> XFS_DIR2_MAX_SHORT_INUM
)
3286 * go onto next entry unless we've just junked an
3287 * entry in which the current entry pointer points
3288 * to an unprocessed entry. have to take into entries
3289 * with bad namelen into account in no modify mode since we
3290 * calculate size based on next_sfep.
3292 ASSERT(no_modify
|| bad_sfnamelen
== 0);
3294 next_sfep
= (tmp_sfep
== NULL
)
3295 ? (xfs_dir2_sf_entry_t
*) ((__psint_t
) sfep
3297 ? XFS_DIR2_SF_ENTSIZE_BYENTRY(sfp
, sfep
)
3298 : XFS_DIR2_SF_ENTSIZE_BYNAME(sfp
, namelen
)))
3302 if (sfp
->hdr
.i8count
!= i8
) {
3304 do_warn("would fix i8count in inode %llu\n", ino
);
3307 tmp_sfep
= next_sfep
;
3308 process_sf_dir2_fixi8(sfp
, &tmp_sfep
);
3310 (__psint_t
)next_sfep
-
3311 (__psint_t
)tmp_sfep
;
3312 next_sfep
= tmp_sfep
;
3314 sfp
->hdr
.i8count
= i8
;
3316 do_warn("fixing i8count in inode %llu\n", ino
);
3321 * sync up sizes if required
3324 ASSERT(bytes_deleted
> 0);
3326 libxfs_idata_realloc(ip
, -bytes_deleted
, XFS_DATA_FORK
);
3327 ip
->i_d
.di_size
-= bytes_deleted
;
3330 if (ip
->i_d
.di_size
!= ip
->i_df
.if_bytes
) {
3331 ASSERT(ip
->i_df
.if_bytes
== (xfs_fsize_t
)
3332 ((__psint_t
) next_sfep
- (__psint_t
) sfp
));
3333 ip
->i_d
.di_size
= (xfs_fsize_t
)
3334 ((__psint_t
) next_sfep
- (__psint_t
) sfp
);
3335 do_warn("setting size to %lld bytes to reflect junked "
3343 * processes all directories reachable via the inodes on the stack
3344 * returns 0 if things are good, 1 if there's a problem
3347 process_dirstack(xfs_mount_t
*mp
, dir_stack_t
*stack
)
3349 xfs_bmap_free_t flist
;
3350 xfs_fsblock_t first
;
3354 xfs_dahash_t hashval
;
3355 ino_tree_node_t
*irec
;
3356 int ino_offset
, need_dot
, committed
;
3357 int dirty
, num_illegal
, error
, nres
;
3360 * pull directory inode # off directory stack
3362 * open up directory inode, check all entries,
3363 * then call prune_dir_entries to remove all
3364 * remaining illegal directory entries.
3367 while ((ino
= pop_dir(stack
)) != NULLFSINO
) {
3368 irec
= find_inode_rec(XFS_INO_TO_AGNO(mp
, ino
),
3369 XFS_INO_TO_AGINO(mp
, ino
));
3370 ASSERT(irec
!= NULL
);
3372 ino_offset
= XFS_INO_TO_AGINO(mp
, ino
) - irec
->ino_startnum
;
3374 ASSERT(!is_inode_refchecked(ino
, irec
, ino_offset
));
3376 if ((error
= libxfs_iget(mp
, NULL
, ino
, 0, &ip
, 0))) {
3378 do_error("couldn't map inode %llu, err = %d\n",
3381 do_warn("couldn't map inode %llu, err = %d\n",
3384 * see below for what we're doing if this
3385 * is root. Why do we need to do this here?
3386 * to ensure that the root doesn't show up
3387 * as being disconnected in the no_modify case.
3389 if (mp
->m_sb
.sb_rootino
== ino
) {
3390 add_inode_reached(irec
, 0);
3391 add_inode_ref(irec
, 0);
3395 add_inode_refchecked(ino
, irec
, 0);
3399 need_dot
= dirty
= num_illegal
= 0;
3401 if (mp
->m_sb
.sb_rootino
== ino
) {
3403 * mark root inode reached and bump up
3404 * link count for root inode to account
3405 * for '..' entry since the root inode is
3406 * never reached by a parent. we know
3407 * that root's '..' is always good --
3408 * guaranteed by phase 3 and/or below.
3410 add_inode_reached(irec
, ino_offset
);
3412 * account for link for the orphanage
3413 * "lost+found". if we're running in
3414 * modify mode and it already existed,
3415 * we deleted it so it's '..' reference
3416 * never got counted. so add it here if
3417 * we're going to create lost+found.
3419 * if we're running in no_modify mode,
3420 * we never deleted lost+found and we're
3421 * not going to create it so do nothing.
3423 * either way, the counts will match when
3424 * we look at the root inode's nlinks
3425 * field and compare that to our incore
3429 add_inode_ref(irec
, ino_offset
);
3432 add_inode_refchecked(ino
, irec
, ino_offset
);
3435 * look for bogus entries
3437 switch (ip
->i_d
.di_format
) {
3438 case XFS_DINODE_FMT_EXTENTS
:
3439 case XFS_DINODE_FMT_BTREE
:
3441 * also check for missing '.' in longform dirs.
3442 * missing .. entries are added if required when
3443 * the directory is connected to lost+found. but
3444 * we need to create '.' entries here.
3446 if (XFS_SB_VERSION_HASDIRV2(&mp
->m_sb
))
3447 longform_dir2_entry_check(mp
, ino
, ip
,
3448 &num_illegal
, &need_dot
,
3452 longform_dir_entry_check(mp
, ino
, ip
,
3453 &num_illegal
, &need_dot
,
3457 case XFS_DINODE_FMT_LOCAL
:
3458 tp
= libxfs_trans_alloc(mp
, 0);
3460 * using the remove reservation is overkill
3461 * since at most we'll only need to log the
3462 * inode but it's easier than wedging a
3463 * new define in ourselves.
3465 nres
= no_modify
? 0 : XFS_REMOVE_SPACE_RES(mp
);
3466 error
= libxfs_trans_reserve(tp
, nres
,
3467 XFS_REMOVE_LOG_RES(mp
), 0,
3468 XFS_TRANS_PERM_LOG_RES
,
3469 XFS_REMOVE_LOG_COUNT
);
3473 libxfs_trans_ijoin(tp
, ip
, 0);
3474 libxfs_trans_ihold(tp
, ip
);
3476 if (XFS_SB_VERSION_HASDIRV2(&mp
->m_sb
))
3477 shortform_dir2_entry_check(mp
, ino
, ip
, &dirty
,
3481 shortform_dir_entry_check(mp
, ino
, ip
, &dirty
,
3485 ASSERT(dirty
== 0 || (dirty
&& !no_modify
));
3487 libxfs_trans_log_inode(tp
, ip
,
3488 XFS_ILOG_CORE
| XFS_ILOG_DDATA
);
3489 libxfs_trans_commit(tp
, XFS_TRANS_RELEASE_LOG_RES
3490 |XFS_TRANS_SYNC
, 0);
3492 libxfs_trans_cancel(tp
, XFS_TRANS_RELEASE_LOG_RES
);
3501 if (!no_modify
&& !orphanage_entered
&&
3502 ino
== mp
->m_sb
.sb_rootino
) {
3503 do_warn("re-entering %s into root directory\n",
3505 tp
= libxfs_trans_alloc(mp
, 0);
3506 nres
= XFS_MKDIR_SPACE_RES(mp
, strlen(ORPHANAGE
));
3507 error
= libxfs_trans_reserve(tp
, nres
,
3508 XFS_MKDIR_LOG_RES(mp
), 0,
3509 XFS_TRANS_PERM_LOG_RES
,
3510 XFS_MKDIR_LOG_COUNT
);
3513 libxfs_trans_ijoin(tp
, ip
, 0);
3514 libxfs_trans_ihold(tp
, ip
);
3515 XFS_BMAP_INIT(&flist
, &first
);
3516 if ((error
= dir_createname(mp
, tp
, ip
, ORPHANAGE
,
3518 orphanage_ino
, &first
, &flist
,
3520 do_error("can't make %s entry in root inode "
3521 "%llu, createname error %d\n",
3522 ORPHANAGE
, ino
, error
);
3523 libxfs_trans_log_inode(tp
, ip
, XFS_ILOG_CORE
);
3524 error
= libxfs_bmap_finish(&tp
, &flist
, first
, &committed
);
3526 libxfs_trans_commit(tp
,
3527 XFS_TRANS_RELEASE_LOG_RES
| XFS_TRANS_SYNC
, 0);
3528 orphanage_entered
= 1;
3532 * if we have to create a .. for /, do it now *before*
3533 * we delete the bogus entries, otherwise the directory
3534 * could transform into a shortform dir which would
3535 * probably cause the simulation to choke. Even
3536 * if the illegal entries get shifted around, it's ok
3537 * because the entries are structurally intact and in
3538 * in hash-value order so the simulation won't get confused
3539 * if it has to move them around.
3541 if (!no_modify
&& need_root_dotdot
&&
3542 ino
== mp
->m_sb
.sb_rootino
) {
3543 ASSERT(ip
->i_d
.di_format
!= XFS_DINODE_FMT_LOCAL
);
3545 do_warn("recreating root directory .. entry\n");
3547 tp
= libxfs_trans_alloc(mp
, 0);
3550 nres
= XFS_MKDIR_SPACE_RES(mp
, 2);
3551 error
= libxfs_trans_reserve(tp
, nres
,
3552 XFS_MKDIR_LOG_RES(mp
),
3554 XFS_TRANS_PERM_LOG_RES
,
3555 XFS_MKDIR_LOG_COUNT
);
3560 libxfs_trans_ijoin(tp
, ip
, 0);
3561 libxfs_trans_ihold(tp
, ip
);
3563 XFS_BMAP_INIT(&flist
, &first
);
3565 if ((error
= dir_createname(mp
, tp
, ip
, "..", 2,
3566 ip
->i_ino
, &first
, &flist
, nres
)))
3568 "can't make \"..\" entry in root inode %llu, createname error %d\n",
3571 libxfs_trans_log_inode(tp
, ip
, XFS_ILOG_CORE
);
3573 error
= libxfs_bmap_finish(&tp
, &flist
, first
,
3576 libxfs_trans_commit(tp
, XFS_TRANS_RELEASE_LOG_RES
3577 |XFS_TRANS_SYNC
, 0);
3579 need_root_dotdot
= 0;
3580 } else if (need_root_dotdot
&& ino
== mp
->m_sb
.sb_rootino
) {
3581 do_warn("would recreate root directory .. entry\n");
3585 * delete any illegal entries -- which should only exist
3586 * if the directory is a longform directory. bogus
3587 * shortform directory entries were deleted in phase 4.
3589 if (!no_modify
&& num_illegal
> 0) {
3590 ASSERT(ip
->i_d
.di_format
!= XFS_DINODE_FMT_LOCAL
);
3591 ASSERT(!XFS_SB_VERSION_HASDIRV2(&mp
->m_sb
));
3593 while (num_illegal
> 0 && ip
->i_d
.di_format
!=
3594 XFS_DINODE_FMT_LOCAL
) {
3595 prune_lf_dir_entry(mp
, ino
, ip
, &hashval
);
3600 * handle case where we've deleted so many
3601 * entries that the directory has changed from
3602 * a longform to a shortform directory. have
3603 * to allocate a transaction since we're working
3604 * with the incore data fork.
3606 if (num_illegal
> 0) {
3607 ASSERT(ip
->i_d
.di_format
==
3608 XFS_DINODE_FMT_LOCAL
);
3609 tp
= libxfs_trans_alloc(mp
, 0);
3611 * using the remove reservation is overkill
3612 * since at most we'll only need to log the
3613 * inode but it's easier than wedging a
3614 * new define in ourselves. 10 block fs
3615 * space reservation is also overkill but
3618 nres
= XFS_REMOVE_SPACE_RES(mp
);
3619 error
= libxfs_trans_reserve(tp
, nres
,
3620 XFS_REMOVE_LOG_RES(mp
), 0,
3621 XFS_TRANS_PERM_LOG_RES
,
3622 XFS_REMOVE_LOG_COUNT
);
3626 libxfs_trans_ijoin(tp
, ip
, 0);
3627 libxfs_trans_ihold(tp
, ip
);
3629 prune_sf_dir_entry(mp
, ino
, ip
);
3631 libxfs_trans_log_inode(tp
, ip
,
3632 XFS_ILOG_CORE
| XFS_ILOG_DDATA
);
3634 libxfs_trans_commit(tp
, XFS_TRANS_RELEASE_LOG_RES
3635 |XFS_TRANS_SYNC
, 0);
3640 * if we need to create the '.' entry, do so only if
3641 * the directory is a longform dir. it it's been
3642 * turned into a shortform dir, then the inode is ok
3643 * since shortform dirs have no '.' entry and the inode
3644 * has already been committed by prune_lf_dir_entry().
3648 * bump up our link count but don't
3649 * bump up the inode link count. chances
3650 * are good that even though we lost '.'
3651 * the inode link counts reflect '.' so
3652 * leave the inode link count alone and if
3653 * it turns out to be wrong, we'll catch
3656 add_inode_ref(irec
, ino_offset
);
3660 "would create missing \".\" entry in dir ino %llu\n",
3662 } else if (ip
->i_d
.di_format
!= XFS_DINODE_FMT_LOCAL
) {
3664 * need to create . entry in longform dir.
3667 "creating missing \".\" entry in dir ino %llu\n",
3670 tp
= libxfs_trans_alloc(mp
, 0);
3673 nres
= XFS_MKDIR_SPACE_RES(mp
, 1);
3674 error
= libxfs_trans_reserve(tp
, nres
,
3675 XFS_MKDIR_LOG_RES(mp
),
3677 XFS_TRANS_PERM_LOG_RES
,
3678 XFS_MKDIR_LOG_COUNT
);
3683 libxfs_trans_ijoin(tp
, ip
, 0);
3684 libxfs_trans_ihold(tp
, ip
);
3686 XFS_BMAP_INIT(&flist
, &first
);
3688 if ((error
= dir_createname(mp
, tp
, ip
, ".",
3689 1, ip
->i_ino
, &first
, &flist
,
3692 "can't make \".\" entry in dir ino %llu, createname error %d\n",
3695 libxfs_trans_log_inode(tp
, ip
, XFS_ILOG_CORE
);
3697 error
= libxfs_bmap_finish(&tp
, &flist
, first
,
3700 libxfs_trans_commit(tp
, XFS_TRANS_RELEASE_LOG_RES
3701 |XFS_TRANS_SYNC
, 0);
3710 * mark realtime bitmap and summary inodes as reached.
3711 * quota inode will be marked here as well
3714 mark_standalone_inodes(xfs_mount_t
*mp
)
3716 ino_tree_node_t
*irec
;
3719 irec
= find_inode_rec(XFS_INO_TO_AGNO(mp
, mp
->m_sb
.sb_rbmino
),
3720 XFS_INO_TO_AGINO(mp
, mp
->m_sb
.sb_rbmino
));
3722 ASSERT(irec
!= NULL
);
3724 offset
= XFS_INO_TO_AGINO(mp
, mp
->m_sb
.sb_rbmino
) -
3727 add_inode_reached(irec
, offset
);
3729 irec
= find_inode_rec(XFS_INO_TO_AGNO(mp
, mp
->m_sb
.sb_rsumino
),
3730 XFS_INO_TO_AGINO(mp
, mp
->m_sb
.sb_rsumino
));
3732 offset
= XFS_INO_TO_AGINO(mp
, mp
->m_sb
.sb_rsumino
) -
3735 ASSERT(irec
!= NULL
);
3737 add_inode_reached(irec
, offset
);
3740 if (mp
->m_sb
.sb_uquotino
3741 && mp
->m_sb
.sb_uquotino
!= NULLFSINO
) {
3742 irec
= find_inode_rec(XFS_INO_TO_AGNO(mp
,
3743 mp
->m_sb
.sb_uquotino
),
3744 XFS_INO_TO_AGINO(mp
, mp
->m_sb
.sb_uquotino
));
3745 offset
= XFS_INO_TO_AGINO(mp
, mp
->m_sb
.sb_uquotino
)
3746 - irec
->ino_startnum
;
3747 add_inode_reached(irec
, offset
);
3749 if (mp
->m_sb
.sb_gquotino
3750 && mp
->m_sb
.sb_gquotino
!= NULLFSINO
) {
3751 irec
= find_inode_rec(XFS_INO_TO_AGNO(mp
,
3752 mp
->m_sb
.sb_gquotino
),
3753 XFS_INO_TO_AGINO(mp
, mp
->m_sb
.sb_gquotino
));
3754 offset
= XFS_INO_TO_AGINO(mp
, mp
->m_sb
.sb_gquotino
)
3755 - irec
->ino_startnum
;
3756 add_inode_reached(irec
, offset
);
3762 phase6(xfs_mount_t
*mp
)
3765 ino_tree_node_t
*irec
;
3770 bzero(&zerocr
, sizeof(cred_t
));
3772 do_log("Phase 6 - check inode connectivity...\n");
3775 teardown_bmap_finish(mp
);
3779 incore_ext_teardown(mp
);
3781 add_ino_backptrs(mp
);
3784 * verify existence of root directory - if we have to
3785 * make one, it's ok for the incore data structs not to
3786 * know about it since everything about it (and the other
3787 * inodes in its chunk if a new chunk was created) are ok
3789 if (need_root_inode
) {
3791 do_warn("reinitializing root directory\n");
3793 need_root_inode
= 0;
3794 need_root_dotdot
= 0;
3796 do_warn("would reinitialize root directory\n");
3802 do_warn("reinitializing realtime bitmap inode\n");
3806 do_warn("would reinitialize realtime bitmap inode\n");
3812 do_warn("reinitializing realtime summary inode\n");
3816 do_warn("would reinitialize realtime summary inode\n");
3822 " - resetting contents of realtime bitmap and summary inodes\n");
3823 if (fill_rbmino(mp
)) {
3825 "Warning: realtime bitmap may be inconsistent\n");
3828 if (fill_rsumino(mp
)) {
3830 "Warning: realtime bitmap may be inconsistent\n");
3835 * make orphanage (it's guaranteed to not exist now)
3838 do_log(" - ensuring existence of %s directory\n",
3840 orphanage_ino
= mk_orphanage(mp
);
3843 dir_stack_init(&stack
);
3845 mark_standalone_inodes(mp
);
3848 * push root dir on stack, then go
3850 if (!need_root_inode
) {
3851 do_log(" - traversing filesystem starting at / ... \n");
3853 push_dir(&stack
, mp
->m_sb
.sb_rootino
);
3854 process_dirstack(mp
, &stack
);
3856 do_log(" - traversal finished ... \n");
3858 ASSERT(no_modify
!= 0);
3861 " - root inode lost, cannot make new one in no modify mode ... \n");
3863 " - skipping filesystem traversal from / ... \n");
3866 do_log(" - traversing all unattached subtrees ... \n");
3868 irec
= find_inode_rec(XFS_INO_TO_AGNO(mp
, mp
->m_sb
.sb_rootino
),
3869 XFS_INO_TO_AGINO(mp
, mp
->m_sb
.sb_rootino
));
3872 * we always have a root inode, even if it's free...
3873 * if the root is free, forget it, lost+found is already gone
3875 if (is_inode_free(irec
, 0) || !inode_isadir(irec
, 0)) {
3876 need_root_inode
= 1;
3880 * then process all unreached inodes
3881 * by walking incore inode tree
3883 * get next unreached directory inode # from
3885 * push inode on dir stack
3886 * call process_dirstack
3888 for (i
= 0; i
< glob_agcount
; i
++) {
3889 irec
= findfirst_inode_rec(i
);
3894 while (irec
!= NULL
) {
3895 for (j
= 0; j
< XFS_INODES_PER_CHUNK
; j
++) {
3896 if (!is_inode_confirmed(irec
, j
))
3899 * skip directories that have already been
3900 * processed, even if they haven't been
3901 * reached. If they are reachable, we'll
3902 * pick them up when we process their parent.
3904 ino
= XFS_AGINO_TO_INO(mp
, i
,
3905 j
+ irec
->ino_startnum
);
3906 if (inode_isadir(irec
, j
) &&
3907 !is_inode_refchecked(ino
,
3909 push_dir(&stack
, ino
);
3910 process_dirstack(mp
, &stack
);
3913 irec
= next_ino_rec(irec
);
3917 do_log(" - traversals finished ... \n");
3918 do_log(" - moving disconnected inodes to lost+found ... \n");
3921 * move all disconnected inodes to the orphanage
3923 for (i
= 0; i
< glob_agcount
; i
++) {
3924 irec
= findfirst_inode_rec(i
);
3929 while (irec
!= NULL
) {
3930 for (j
= 0; j
< XFS_INODES_PER_CHUNK
; j
++) {
3931 ASSERT(is_inode_confirmed(irec
, j
));
3932 if (is_inode_free(irec
, j
))
3934 if (!is_inode_reached(irec
, j
)) {
3935 ASSERT(inode_isadir(irec
, j
) ||
3936 num_inode_references(irec
, j
)
3938 ino
= XFS_AGINO_TO_INO(mp
, i
,
3939 j
+ irec
->ino_startnum
);
3940 if (inode_isadir(irec
, j
))
3942 "disconnected dir inode %llu, ",
3946 "disconnected inode %llu, ",
3949 do_warn("moving to %s\n",
3951 mv_orphanage(mp
, orphanage_ino
,
3953 inode_isadir(irec
, j
));
3955 do_warn("would move to %s\n",
3959 * for read-only case, even though
3960 * the inode isn't really reachable,
3961 * set the flag (and bump our link
3962 * count) anyway to fool phase 7
3964 add_inode_reached(irec
, j
);
3967 irec
= next_ino_rec(irec
);