2 * Copyright (c) 2000-2003 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/
36 * GROT: figure out how to recover gracefully when bmap returns ENOSPC.
41 #include "xfs_macros.h"
42 #include "xfs_types.h"
45 #include "xfs_trans.h"
49 #include "xfs_dmapi.h"
50 #include "xfs_mount.h"
51 #include "xfs_alloc_btree.h"
52 #include "xfs_bmap_btree.h"
53 #include "xfs_ialloc_btree.h"
54 #include "xfs_alloc.h"
55 #include "xfs_btree.h"
56 #include "xfs_attr_sf.h"
57 #include "xfs_dir_sf.h"
58 #include "xfs_dir2_sf.h"
59 #include "xfs_dinode.h"
60 #include "xfs_inode_item.h"
61 #include "xfs_inode.h"
63 #include "xfs_da_btree.h"
64 #include "xfs_dir_leaf.h"
65 #include "xfs_error.h"
70 * Routines to implement leaf blocks of directories as Btrees of hashed names.
73 /*========================================================================
74 * Function prototypes for the kernel.
75 *========================================================================*/
78 * Routines used for growing the Btree.
80 STATIC
void xfs_dir_leaf_add_work(xfs_dabuf_t
*leaf_buffer
, xfs_da_args_t
*args
,
83 STATIC
int xfs_dir_leaf_compact(xfs_trans_t
*trans
, xfs_dabuf_t
*leaf_buffer
,
84 int musthave
, int justcheck
);
85 STATIC
void xfs_dir_leaf_rebalance(xfs_da_state_t
*state
,
86 xfs_da_state_blk_t
*blk1
,
87 xfs_da_state_blk_t
*blk2
);
88 STATIC
int xfs_dir_leaf_figure_balance(xfs_da_state_t
*state
,
89 xfs_da_state_blk_t
*leaf_blk_1
,
90 xfs_da_state_blk_t
*leaf_blk_2
,
91 int *number_entries_in_blk1
,
92 int *number_namebytes_in_blk1
);
97 STATIC
void xfs_dir_leaf_moveents(xfs_dir_leafblock_t
*src_leaf
,
99 xfs_dir_leafblock_t
*dst_leaf
,
100 int dst_start
, int move_count
,
104 /*========================================================================
105 * External routines when dirsize < XFS_IFORK_DSIZE(dp).
106 *========================================================================*/
110 * Validate a given inode number.
113 xfs_dir_ino_validate(xfs_mount_t
*mp
, xfs_ino_t ino
)
115 xfs_agblock_t agblkno
;
121 agno
= XFS_INO_TO_AGNO(mp
, ino
);
122 agblkno
= XFS_INO_TO_AGBNO(mp
, ino
);
123 ioff
= XFS_INO_TO_OFFSET(mp
, ino
);
124 agino
= XFS_OFFBNO_TO_AGINO(mp
, agblkno
, ioff
);
126 agno
< mp
->m_sb
.sb_agcount
&&
127 agblkno
< mp
->m_sb
.sb_agblocks
&&
129 ioff
< (1 << mp
->m_sb
.sb_inopblog
) &&
130 XFS_AGINO_TO_INO(mp
, agno
, agino
) == ino
;
131 if (unlikely(XFS_TEST_ERROR(!ino_ok
, mp
, XFS_ERRTAG_DIR_INO_VALIDATE
,
132 XFS_RANDOM_DIR_INO_VALIDATE
))) {
133 xfs_fs_cmn_err(CE_WARN
, mp
, "Invalid inode number 0x%Lx",
134 (unsigned long long) ino
);
135 XFS_ERROR_REPORT("xfs_dir_ino_validate", XFS_ERRLEVEL_LOW
, mp
);
136 return XFS_ERROR(EFSCORRUPTED
);
142 * Create the initial contents of a shortform directory.
145 xfs_dir_shortform_create(xfs_da_args_t
*args
, xfs_ino_t parent
)
147 xfs_dir_sf_hdr_t
*hdr
;
152 ASSERT(dp
->i_d
.di_size
== 0);
153 if (dp
->i_d
.di_format
== XFS_DINODE_FMT_EXTENTS
) {
154 dp
->i_df
.if_flags
&= ~XFS_IFEXTENTS
; /* just in case */
155 dp
->i_d
.di_format
= XFS_DINODE_FMT_LOCAL
;
156 xfs_trans_log_inode(args
->trans
, dp
, XFS_ILOG_CORE
);
157 dp
->i_df
.if_flags
|= XFS_IFINLINE
;
159 ASSERT(dp
->i_df
.if_flags
& XFS_IFINLINE
);
160 ASSERT(dp
->i_df
.if_bytes
== 0);
161 xfs_idata_realloc(dp
, sizeof(*hdr
), XFS_DATA_FORK
);
162 hdr
= (xfs_dir_sf_hdr_t
*)dp
->i_df
.if_u1
.if_data
;
163 XFS_DIR_SF_PUT_DIRINO(&parent
, &hdr
->parent
);
166 dp
->i_d
.di_size
= sizeof(*hdr
);
167 xfs_trans_log_inode(args
->trans
, dp
, XFS_ILOG_CORE
| XFS_ILOG_DDATA
);
172 * Add a name to the shortform directory structure.
173 * Overflow from the inode has already been checked for.
176 xfs_dir_shortform_addname(xfs_da_args_t
*args
)
178 xfs_dir_shortform_t
*sf
;
179 xfs_dir_sf_entry_t
*sfe
;
184 ASSERT(dp
->i_df
.if_flags
& XFS_IFINLINE
);
186 * Catch the case where the conversion from shortform to leaf
187 * failed part way through.
189 if (dp
->i_d
.di_size
< sizeof(xfs_dir_sf_hdr_t
)) {
190 ASSERT(XFS_FORCED_SHUTDOWN(dp
->i_mount
));
191 return XFS_ERROR(EIO
);
193 ASSERT(dp
->i_df
.if_bytes
== dp
->i_d
.di_size
);
194 ASSERT(dp
->i_df
.if_u1
.if_data
!= NULL
);
195 sf
= (xfs_dir_shortform_t
*)dp
->i_df
.if_u1
.if_data
;
197 for (i
= INT_GET(sf
->hdr
.count
, ARCH_CONVERT
)-1; i
>= 0; i
--) {
198 if (sfe
->namelen
== args
->namelen
&&
199 args
->name
[0] == sfe
->name
[0] &&
200 memcmp(args
->name
, sfe
->name
, args
->namelen
) == 0)
201 return(XFS_ERROR(EEXIST
));
202 sfe
= XFS_DIR_SF_NEXTENTRY(sfe
);
205 offset
= (int)((char *)sfe
- (char *)sf
);
206 size
= XFS_DIR_SF_ENTSIZE_BYNAME(args
->namelen
);
207 xfs_idata_realloc(dp
, size
, XFS_DATA_FORK
);
208 sf
= (xfs_dir_shortform_t
*)dp
->i_df
.if_u1
.if_data
;
209 sfe
= (xfs_dir_sf_entry_t
*)((char *)sf
+ offset
);
211 XFS_DIR_SF_PUT_DIRINO(&args
->inumber
, &sfe
->inumber
);
212 sfe
->namelen
= args
->namelen
;
213 memcpy(sfe
->name
, args
->name
, sfe
->namelen
);
214 INT_MOD(sf
->hdr
.count
, ARCH_CONVERT
, +1);
216 dp
->i_d
.di_size
+= size
;
217 xfs_trans_log_inode(args
->trans
, dp
, XFS_ILOG_CORE
| XFS_ILOG_DDATA
);
223 * Remove a name from the shortform directory structure.
226 xfs_dir_shortform_removename(xfs_da_args_t
*args
)
228 xfs_dir_shortform_t
*sf
;
229 xfs_dir_sf_entry_t
*sfe
;
230 int base
, size
= 0, i
;
234 ASSERT(dp
->i_df
.if_flags
& XFS_IFINLINE
);
236 * Catch the case where the conversion from shortform to leaf
237 * failed part way through.
239 if (dp
->i_d
.di_size
< sizeof(xfs_dir_sf_hdr_t
)) {
240 ASSERT(XFS_FORCED_SHUTDOWN(dp
->i_mount
));
241 return XFS_ERROR(EIO
);
243 ASSERT(dp
->i_df
.if_bytes
== dp
->i_d
.di_size
);
244 ASSERT(dp
->i_df
.if_u1
.if_data
!= NULL
);
245 base
= sizeof(xfs_dir_sf_hdr_t
);
246 sf
= (xfs_dir_shortform_t
*)dp
->i_df
.if_u1
.if_data
;
248 for (i
= INT_GET(sf
->hdr
.count
, ARCH_CONVERT
)-1; i
>= 0; i
--) {
249 size
= XFS_DIR_SF_ENTSIZE_BYENTRY(sfe
);
250 if (sfe
->namelen
== args
->namelen
&&
251 sfe
->name
[0] == args
->name
[0] &&
252 memcmp(sfe
->name
, args
->name
, args
->namelen
) == 0)
255 sfe
= XFS_DIR_SF_NEXTENTRY(sfe
);
258 ASSERT(args
->oknoent
);
259 return(XFS_ERROR(ENOENT
));
262 if ((base
+ size
) != dp
->i_d
.di_size
) {
263 memmove(&((char *)sf
)[base
], &((char *)sf
)[base
+size
],
264 dp
->i_d
.di_size
- (base
+size
));
266 INT_MOD(sf
->hdr
.count
, ARCH_CONVERT
, -1);
268 xfs_idata_realloc(dp
, -size
, XFS_DATA_FORK
);
269 dp
->i_d
.di_size
-= size
;
270 xfs_trans_log_inode(args
->trans
, dp
, XFS_ILOG_CORE
| XFS_ILOG_DDATA
);
276 * Look up a name in a shortform directory structure.
279 xfs_dir_shortform_lookup(xfs_da_args_t
*args
)
281 xfs_dir_shortform_t
*sf
;
282 xfs_dir_sf_entry_t
*sfe
;
287 ASSERT(dp
->i_df
.if_flags
& XFS_IFINLINE
);
289 * Catch the case where the conversion from shortform to leaf
290 * failed part way through.
292 if (dp
->i_d
.di_size
< sizeof(xfs_dir_sf_hdr_t
)) {
293 ASSERT(XFS_FORCED_SHUTDOWN(dp
->i_mount
));
294 return XFS_ERROR(EIO
);
296 ASSERT(dp
->i_df
.if_bytes
== dp
->i_d
.di_size
);
297 ASSERT(dp
->i_df
.if_u1
.if_data
!= NULL
);
298 sf
= (xfs_dir_shortform_t
*)dp
->i_df
.if_u1
.if_data
;
299 if (args
->namelen
== 2 &&
300 args
->name
[0] == '.' && args
->name
[1] == '.') {
301 XFS_DIR_SF_GET_DIRINO(&sf
->hdr
.parent
, &args
->inumber
);
302 return(XFS_ERROR(EEXIST
));
304 if (args
->namelen
== 1 && args
->name
[0] == '.') {
305 args
->inumber
= dp
->i_ino
;
306 return(XFS_ERROR(EEXIST
));
309 for (i
= INT_GET(sf
->hdr
.count
, ARCH_CONVERT
)-1; i
>= 0; i
--) {
310 if (sfe
->namelen
== args
->namelen
&&
311 sfe
->name
[0] == args
->name
[0] &&
312 memcmp(args
->name
, sfe
->name
, args
->namelen
) == 0) {
313 XFS_DIR_SF_GET_DIRINO(&sfe
->inumber
, &args
->inumber
);
314 return(XFS_ERROR(EEXIST
));
316 sfe
= XFS_DIR_SF_NEXTENTRY(sfe
);
318 ASSERT(args
->oknoent
);
319 return(XFS_ERROR(ENOENT
));
323 * Convert from using the shortform to the leaf.
326 xfs_dir_shortform_to_leaf(xfs_da_args_t
*iargs
)
329 xfs_dir_shortform_t
*sf
;
330 xfs_dir_sf_entry_t
*sfe
;
340 * Catch the case where the conversion from shortform to leaf
341 * failed part way through.
343 if (dp
->i_d
.di_size
< sizeof(xfs_dir_sf_hdr_t
)) {
344 ASSERT(XFS_FORCED_SHUTDOWN(dp
->i_mount
));
345 return XFS_ERROR(EIO
);
347 ASSERT(dp
->i_df
.if_bytes
== dp
->i_d
.di_size
);
348 ASSERT(dp
->i_df
.if_u1
.if_data
!= NULL
);
349 size
= dp
->i_df
.if_bytes
;
350 tmpbuffer
= kmem_alloc(size
, KM_SLEEP
);
351 ASSERT(tmpbuffer
!= NULL
);
353 memcpy(tmpbuffer
, dp
->i_df
.if_u1
.if_data
, size
);
355 sf
= (xfs_dir_shortform_t
*)tmpbuffer
;
356 XFS_DIR_SF_GET_DIRINO(&sf
->hdr
.parent
, &inumber
);
358 xfs_idata_realloc(dp
, -size
, XFS_DATA_FORK
);
360 xfs_trans_log_inode(iargs
->trans
, dp
, XFS_ILOG_CORE
);
361 retval
= xfs_da_grow_inode(iargs
, &blkno
);
366 retval
= xfs_dir_leaf_create(iargs
, blkno
, &bp
);
373 args
.hashval
= xfs_dir_hash_dot
;
374 args
.inumber
= dp
->i_ino
;
376 args
.firstblock
= iargs
->firstblock
;
377 args
.flist
= iargs
->flist
;
378 args
.total
= iargs
->total
;
379 args
.whichfork
= XFS_DATA_FORK
;
380 args
.trans
= iargs
->trans
;
382 args
.addname
= args
.oknoent
= 1;
383 retval
= xfs_dir_leaf_addname(&args
);
389 args
.hashval
= xfs_dir_hash_dotdot
;
390 args
.inumber
= inumber
;
391 retval
= xfs_dir_leaf_addname(&args
);
396 for (i
= 0; i
< INT_GET(sf
->hdr
.count
, ARCH_CONVERT
); i
++) {
397 args
.name
= (char *)(sfe
->name
);
398 args
.namelen
= sfe
->namelen
;
399 args
.hashval
= xfs_da_hashname((char *)(sfe
->name
),
401 XFS_DIR_SF_GET_DIRINO(&sfe
->inumber
, &args
.inumber
);
402 retval
= xfs_dir_leaf_addname(&args
);
405 sfe
= XFS_DIR_SF_NEXTENTRY(sfe
);
410 kmem_free(tmpbuffer
, size
);
415 xfs_dir_shortform_compare(const void *a
, const void *b
)
417 xfs_dir_sf_sort_t
*sa
, *sb
;
419 sa
= (xfs_dir_sf_sort_t
*)a
;
420 sb
= (xfs_dir_sf_sort_t
*)b
;
421 if (sa
->hash
< sb
->hash
)
423 else if (sa
->hash
> sb
->hash
)
426 return sa
->entno
- sb
->entno
;
430 * Copy out directory entries for getdents(), for shortform directories.
434 xfs_dir_shortform_getdents(xfs_inode_t
*dp
, uio_t
*uio
, int *eofp
,
435 xfs_dirent_t
*dbp
, xfs_dir_put_t put
)
437 xfs_dir_shortform_t
*sf
;
438 xfs_dir_sf_entry_t
*sfe
;
439 int retval
, i
, sbsize
, nsbuf
, lastresid
=0, want_entno
;
441 xfs_dahash_t cookhash
, hash
;
442 xfs_dir_put_args_t p
;
443 xfs_dir_sf_sort_t
*sbuf
, *sbp
;
446 sf
= (xfs_dir_shortform_t
*)dp
->i_df
.if_u1
.if_data
;
447 cookhash
= XFS_DA_COOKIE_HASH(mp
, uio
->uio_offset
);
448 want_entno
= XFS_DA_COOKIE_ENTRY(mp
, uio
->uio_offset
);
449 nsbuf
= INT_GET(sf
->hdr
.count
, ARCH_CONVERT
) + 2;
450 sbsize
= (nsbuf
+ 1) * sizeof(*sbuf
);
451 sbp
= sbuf
= kmem_alloc(sbsize
, KM_SLEEP
);
453 xfs_dir_trace_g_du("sf: start", dp
, uio
);
456 * Collect all the entries into the buffer.
461 sbp
->hash
= xfs_dir_hash_dot
;
462 sbp
->ino
= dp
->i_ino
;
472 sbp
->hash
= xfs_dir_hash_dotdot
;
473 sbp
->ino
= XFS_GET_DIR_INO8(sf
->hdr
.parent
);
479 * Scan the directory data for the rest of the entries.
481 for (i
= 0, sfe
= &sf
->list
[0];
482 i
< INT_GET(sf
->hdr
.count
, ARCH_CONVERT
); i
++) {
485 ((char *)sfe
< (char *)sf
) ||
486 ((char *)sfe
>= ((char *)sf
+ dp
->i_df
.if_bytes
)))) {
487 xfs_dir_trace_g_du("sf: corrupted", dp
, uio
);
488 XFS_CORRUPTION_ERROR("xfs_dir_shortform_getdents",
489 XFS_ERRLEVEL_LOW
, mp
, sfe
);
490 kmem_free(sbuf
, sbsize
);
491 return XFS_ERROR(EFSCORRUPTED
);
496 sbp
->hash
= xfs_da_hashname((char *)sfe
->name
, sfe
->namelen
);
497 sbp
->ino
= XFS_GET_DIR_INO8(sfe
->inumber
);
498 sbp
->name
= (char *)sfe
->name
;
499 sbp
->namelen
= sfe
->namelen
;
500 sfe
= XFS_DIR_SF_NEXTENTRY(sfe
);
505 * Sort the entries on hash then entno.
507 qsort(sbuf
, nsbuf
, sizeof(*sbuf
), xfs_dir_shortform_compare
);
509 * Stuff in last entry.
512 sbp
->hash
= XFS_DA_MAXHASH
;
515 * Figure out the sequence numbers in case there's a hash duplicate.
517 for (hash
= sbuf
->hash
, sbp
= sbuf
+ 1;
518 sbp
< &sbuf
[nsbuf
+ 1]; sbp
++) {
519 if (sbp
->hash
== hash
)
520 sbp
->seqno
= sbp
[-1].seqno
+ 1;
526 * Set up put routine.
535 for (sbp
= sbuf
; sbp
< &sbuf
[nsbuf
+ 1]; sbp
++) {
536 if (sbp
->hash
> cookhash
||
537 (sbp
->hash
== cookhash
&& sbp
->seqno
>= want_entno
))
542 * Did we fail to find anything? We stop at the last entry,
543 * the one we put maxhash into.
545 if (sbp
== &sbuf
[nsbuf
]) {
546 kmem_free(sbuf
, sbsize
);
547 xfs_dir_trace_g_du("sf: hash beyond end", dp
, uio
);
548 uio
->uio_offset
= XFS_DA_MAKE_COOKIE(mp
, 0, 0, XFS_DA_MAXHASH
);
554 * Loop putting entries into the user buffer.
556 while (sbp
< &sbuf
[nsbuf
]) {
558 * Save the first resid in a run of equal-hashval entries
559 * so that we can back them out if they don't all fit.
561 if (sbp
->seqno
== 0 || sbp
== sbuf
)
562 lastresid
= uio
->uio_resid
;
563 XFS_PUT_COOKIE(p
.cook
, mp
, 0, sbp
[1].seqno
, sbp
[1].hash
);
566 p
.ino
+= mp
->m_inoadd
;
569 p
.namelen
= sbp
->namelen
;
573 XFS_DA_MAKE_COOKIE(mp
, 0, 0, sbp
->hash
);
574 kmem_free(sbuf
, sbsize
);
575 uio
->uio_resid
= lastresid
;
576 xfs_dir_trace_g_du("sf: E-O-B", dp
, uio
);
581 kmem_free(sbuf
, sbsize
);
582 uio
->uio_offset
= p
.cook
.o
;
584 xfs_dir_trace_g_du("sf: E-O-F", dp
, uio
);
589 * Look up a name in a shortform directory structure, replace the inode number.
592 xfs_dir_shortform_replace(xfs_da_args_t
*args
)
594 xfs_dir_shortform_t
*sf
;
595 xfs_dir_sf_entry_t
*sfe
;
600 ASSERT(dp
->i_df
.if_flags
& XFS_IFINLINE
);
602 * Catch the case where the conversion from shortform to leaf
603 * failed part way through.
605 if (dp
->i_d
.di_size
< sizeof(xfs_dir_sf_hdr_t
)) {
606 ASSERT(XFS_FORCED_SHUTDOWN(dp
->i_mount
));
607 return XFS_ERROR(EIO
);
609 ASSERT(dp
->i_df
.if_bytes
== dp
->i_d
.di_size
);
610 ASSERT(dp
->i_df
.if_u1
.if_data
!= NULL
);
611 sf
= (xfs_dir_shortform_t
*)dp
->i_df
.if_u1
.if_data
;
612 if (args
->namelen
== 2 &&
613 args
->name
[0] == '.' && args
->name
[1] == '.') {
614 /* XXX - replace assert? */
615 XFS_DIR_SF_PUT_DIRINO(&args
->inumber
, &sf
->hdr
.parent
);
616 xfs_trans_log_inode(args
->trans
, dp
, XFS_ILOG_DDATA
);
619 ASSERT(args
->namelen
!= 1 || args
->name
[0] != '.');
621 for (i
= INT_GET(sf
->hdr
.count
, ARCH_CONVERT
)-1; i
>= 0; i
--) {
622 if (sfe
->namelen
== args
->namelen
&&
623 sfe
->name
[0] == args
->name
[0] &&
624 memcmp(args
->name
, sfe
->name
, args
->namelen
) == 0) {
625 ASSERT(memcmp((char *)&args
->inumber
,
626 (char *)&sfe
->inumber
, sizeof(xfs_ino_t
)));
627 XFS_DIR_SF_PUT_DIRINO(&args
->inumber
, &sfe
->inumber
);
628 xfs_trans_log_inode(args
->trans
, dp
, XFS_ILOG_DDATA
);
631 sfe
= XFS_DIR_SF_NEXTENTRY(sfe
);
633 ASSERT(args
->oknoent
);
634 return(XFS_ERROR(ENOENT
));
638 * Convert a leaf directory to shortform structure
641 xfs_dir_leaf_to_shortform(xfs_da_args_t
*iargs
)
643 xfs_dir_leafblock_t
*leaf
;
644 xfs_dir_leaf_hdr_t
*hdr
;
645 xfs_dir_leaf_entry_t
*entry
;
646 xfs_dir_leaf_name_t
*namest
;
655 tmpbuffer
= kmem_alloc(XFS_LBSIZE(dp
->i_mount
), KM_SLEEP
);
656 ASSERT(tmpbuffer
!= NULL
);
658 retval
= xfs_da_read_buf(iargs
->trans
, iargs
->dp
, 0, -1, &bp
,
663 memcpy(tmpbuffer
, bp
->data
, XFS_LBSIZE(dp
->i_mount
));
664 leaf
= (xfs_dir_leafblock_t
*)tmpbuffer
;
665 ASSERT(INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
) == XFS_DIR_LEAF_MAGIC
);
666 memset(bp
->data
, 0, XFS_LBSIZE(dp
->i_mount
));
669 * Find and special case the parent inode number
672 entry
= &leaf
->entries
[0];
673 for (i
= INT_GET(hdr
->count
, ARCH_CONVERT
)-1; i
>= 0; entry
++, i
--) {
674 namest
= XFS_DIR_LEAF_NAMESTRUCT(leaf
, INT_GET(entry
->nameidx
, ARCH_CONVERT
));
675 if ((entry
->namelen
== 2) &&
676 (namest
->name
[0] == '.') &&
677 (namest
->name
[1] == '.')) {
678 XFS_DIR_SF_GET_DIRINO(&namest
->inumber
, &parent
);
680 } else if ((entry
->namelen
== 1) && (namest
->name
[0] == '.')) {
684 retval
= xfs_da_shrink_inode(iargs
, 0, bp
);
687 retval
= xfs_dir_shortform_create(iargs
, parent
);
692 * Copy the rest of the filenames
694 entry
= &leaf
->entries
[0];
696 args
.firstblock
= iargs
->firstblock
;
697 args
.flist
= iargs
->flist
;
698 args
.total
= iargs
->total
;
699 args
.whichfork
= XFS_DATA_FORK
;
700 args
.trans
= iargs
->trans
;
702 args
.addname
= args
.oknoent
= 1;
703 for (i
= 0; i
< INT_GET(hdr
->count
, ARCH_CONVERT
); entry
++, i
++) {
706 namest
= XFS_DIR_LEAF_NAMESTRUCT(leaf
, INT_GET(entry
->nameidx
, ARCH_CONVERT
));
707 args
.name
= (char *)(namest
->name
);
708 args
.namelen
= entry
->namelen
;
709 args
.hashval
= INT_GET(entry
->hashval
, ARCH_CONVERT
);
710 XFS_DIR_SF_GET_DIRINO(&namest
->inumber
, &args
.inumber
);
711 xfs_dir_shortform_addname(&args
);
715 kmem_free(tmpbuffer
, XFS_LBSIZE(dp
->i_mount
));
720 * Convert from using a single leaf to a root node and a leaf.
723 xfs_dir_leaf_to_node(xfs_da_args_t
*args
)
725 xfs_dir_leafblock_t
*leaf
;
726 xfs_da_intnode_t
*node
;
728 xfs_dabuf_t
*bp1
, *bp2
;
733 retval
= xfs_da_grow_inode(args
, &blkno
);
737 retval
= xfs_da_read_buf(args
->trans
, args
->dp
, 0, -1, &bp1
,
742 retval
= xfs_da_get_buf(args
->trans
, args
->dp
, 1, -1, &bp2
,
745 xfs_da_buf_done(bp1
);
749 memcpy(bp2
->data
, bp1
->data
, XFS_LBSIZE(dp
->i_mount
));
750 xfs_da_buf_done(bp1
);
751 xfs_da_log_buf(args
->trans
, bp2
, 0, XFS_LBSIZE(dp
->i_mount
) - 1);
754 * Set up the new root node.
756 retval
= xfs_da_node_create(args
, 0, 1, &bp1
, XFS_DATA_FORK
);
758 xfs_da_buf_done(bp2
);
763 ASSERT(INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
) == XFS_DIR_LEAF_MAGIC
);
764 INT_SET(node
->btree
[0].hashval
, ARCH_CONVERT
, INT_GET(leaf
->entries
[ INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
)-1 ].hashval
, ARCH_CONVERT
));
765 xfs_da_buf_done(bp2
);
766 INT_SET(node
->btree
[0].before
, ARCH_CONVERT
, blkno
);
767 INT_SET(node
->hdr
.count
, ARCH_CONVERT
, 1);
768 xfs_da_log_buf(args
->trans
, bp1
,
769 XFS_DA_LOGRANGE(node
, &node
->btree
[0], sizeof(node
->btree
[0])));
770 xfs_da_buf_done(bp1
);
776 /*========================================================================
777 * Routines used for growing the Btree.
778 *========================================================================*/
781 * Create the initial contents of a leaf directory
782 * or a leaf in a node directory.
785 xfs_dir_leaf_create(xfs_da_args_t
*args
, xfs_dablk_t blkno
, xfs_dabuf_t
**bpp
)
787 xfs_dir_leafblock_t
*leaf
;
788 xfs_dir_leaf_hdr_t
*hdr
;
795 retval
= xfs_da_get_buf(args
->trans
, dp
, blkno
, -1, &bp
, XFS_DATA_FORK
);
800 memset((char *)leaf
, 0, XFS_LBSIZE(dp
->i_mount
));
802 INT_SET(hdr
->info
.magic
, ARCH_CONVERT
, XFS_DIR_LEAF_MAGIC
);
803 INT_SET(hdr
->firstused
, ARCH_CONVERT
, XFS_LBSIZE(dp
->i_mount
));
805 INT_SET(hdr
->firstused
, ARCH_CONVERT
, XFS_LBSIZE(dp
->i_mount
) - 1);
806 INT_SET(hdr
->freemap
[0].base
, ARCH_CONVERT
, sizeof(xfs_dir_leaf_hdr_t
));
807 INT_SET(hdr
->freemap
[0].size
, ARCH_CONVERT
, INT_GET(hdr
->firstused
, ARCH_CONVERT
) - INT_GET(hdr
->freemap
[0].base
, ARCH_CONVERT
));
809 xfs_da_log_buf(args
->trans
, bp
, 0, XFS_LBSIZE(dp
->i_mount
) - 1);
816 * Split the leaf node, rebalance, then add the new entry.
819 xfs_dir_leaf_split(xfs_da_state_t
*state
, xfs_da_state_blk_t
*oldblk
,
820 xfs_da_state_blk_t
*newblk
)
827 * Allocate space for a new leaf node.
830 ASSERT(args
!= NULL
);
831 ASSERT(oldblk
->magic
== XFS_DIR_LEAF_MAGIC
);
832 error
= xfs_da_grow_inode(args
, &blkno
);
835 error
= xfs_dir_leaf_create(args
, blkno
, &newblk
->bp
);
838 newblk
->blkno
= blkno
;
839 newblk
->magic
= XFS_DIR_LEAF_MAGIC
;
842 * Rebalance the entries across the two leaves.
844 xfs_dir_leaf_rebalance(state
, oldblk
, newblk
);
845 error
= xfs_da_blk_link(state
, oldblk
, newblk
);
850 * Insert the new entry in the correct block.
853 error
= xfs_dir_leaf_add(oldblk
->bp
, args
, oldblk
->index
);
855 error
= xfs_dir_leaf_add(newblk
->bp
, args
, newblk
->index
);
859 * Update last hashval in each block since we added the name.
861 oldblk
->hashval
= xfs_dir_leaf_lasthash(oldblk
->bp
, NULL
);
862 newblk
->hashval
= xfs_dir_leaf_lasthash(newblk
->bp
, NULL
);
867 * Add a name to the leaf directory structure.
869 * Must take into account fragmented leaves and leaves where spacemap has
870 * lost some freespace information (ie: holes).
873 xfs_dir_leaf_add(xfs_dabuf_t
*bp
, xfs_da_args_t
*args
, int index
)
875 xfs_dir_leafblock_t
*leaf
;
876 xfs_dir_leaf_hdr_t
*hdr
;
877 xfs_dir_leaf_map_t
*map
;
878 int tablesize
, entsize
, sum
, i
, tmp
, error
;
881 ASSERT(INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
) == XFS_DIR_LEAF_MAGIC
);
882 ASSERT((index
>= 0) && (index
<= INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
)));
884 entsize
= XFS_DIR_LEAF_ENTSIZE_BYNAME(args
->namelen
);
887 * Search through freemap for first-fit on new name length.
888 * (may need to figure in size of entry struct too)
890 tablesize
= (INT_GET(hdr
->count
, ARCH_CONVERT
) + 1) * (uint
)sizeof(xfs_dir_leaf_entry_t
)
891 + (uint
)sizeof(xfs_dir_leaf_hdr_t
);
892 map
= &hdr
->freemap
[XFS_DIR_LEAF_MAPSIZE
-1];
893 for (sum
= 0, i
= XFS_DIR_LEAF_MAPSIZE
-1; i
>= 0; map
--, i
--) {
894 if (tablesize
> INT_GET(hdr
->firstused
, ARCH_CONVERT
)) {
895 sum
+= INT_GET(map
->size
, ARCH_CONVERT
);
899 continue; /* no space in this map */
901 if (INT_GET(map
->base
, ARCH_CONVERT
) < INT_GET(hdr
->firstused
, ARCH_CONVERT
))
902 tmp
+= (uint
)sizeof(xfs_dir_leaf_entry_t
);
903 if (INT_GET(map
->size
, ARCH_CONVERT
) >= tmp
) {
904 if (!args
->justcheck
)
905 xfs_dir_leaf_add_work(bp
, args
, index
, i
);
908 sum
+= INT_GET(map
->size
, ARCH_CONVERT
);
912 * If there are no holes in the address space of the block,
913 * and we don't have enough freespace, then compaction will do us
914 * no good and we should just give up.
916 if (!hdr
->holes
&& (sum
< entsize
))
917 return(XFS_ERROR(ENOSPC
));
920 * Compact the entries to coalesce free space.
921 * Pass the justcheck flag so the checking pass can return
922 * an error, without changing anything, if it won't fit.
924 error
= xfs_dir_leaf_compact(args
->trans
, bp
,
927 (uint
)sizeof(xfs_dir_leaf_entry_t
) : 0,
932 * After compaction, the block is guaranteed to have only one
933 * free region, in freemap[0]. If it is not big enough, give up.
935 if (INT_GET(hdr
->freemap
[0].size
, ARCH_CONVERT
) <
936 (entsize
+ (uint
)sizeof(xfs_dir_leaf_entry_t
)))
937 return(XFS_ERROR(ENOSPC
));
939 if (!args
->justcheck
)
940 xfs_dir_leaf_add_work(bp
, args
, index
, 0);
945 * Add a name to a leaf directory structure.
948 xfs_dir_leaf_add_work(xfs_dabuf_t
*bp
, xfs_da_args_t
*args
, int index
,
951 xfs_dir_leafblock_t
*leaf
;
952 xfs_dir_leaf_hdr_t
*hdr
;
953 xfs_dir_leaf_entry_t
*entry
;
954 xfs_dir_leaf_name_t
*namest
;
955 xfs_dir_leaf_map_t
*map
;
961 ASSERT(INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
) == XFS_DIR_LEAF_MAGIC
);
963 ASSERT((mapindex
>= 0) && (mapindex
< XFS_DIR_LEAF_MAPSIZE
));
964 ASSERT((index
>= 0) && (index
<= INT_GET(hdr
->count
, ARCH_CONVERT
)));
967 * Force open some space in the entry array and fill it in.
969 entry
= &leaf
->entries
[index
];
970 if (index
< INT_GET(hdr
->count
, ARCH_CONVERT
)) {
971 tmp
= INT_GET(hdr
->count
, ARCH_CONVERT
) - index
;
972 tmp
*= (uint
)sizeof(xfs_dir_leaf_entry_t
);
973 memmove(entry
+ 1, entry
, tmp
);
974 xfs_da_log_buf(args
->trans
, bp
,
975 XFS_DA_LOGRANGE(leaf
, entry
, tmp
+ (uint
)sizeof(*entry
)));
977 INT_MOD(hdr
->count
, ARCH_CONVERT
, +1);
980 * Allocate space for the new string (at the end of the run).
982 map
= &hdr
->freemap
[mapindex
];
983 mp
= args
->trans
->t_mountp
;
984 ASSERT(INT_GET(map
->base
, ARCH_CONVERT
) < XFS_LBSIZE(mp
));
985 ASSERT(INT_GET(map
->size
, ARCH_CONVERT
) >= XFS_DIR_LEAF_ENTSIZE_BYNAME(args
->namelen
));
986 ASSERT(INT_GET(map
->size
, ARCH_CONVERT
) < XFS_LBSIZE(mp
));
987 INT_MOD(map
->size
, ARCH_CONVERT
, -(XFS_DIR_LEAF_ENTSIZE_BYNAME(args
->namelen
)));
988 INT_SET(entry
->nameidx
, ARCH_CONVERT
, INT_GET(map
->base
, ARCH_CONVERT
) + INT_GET(map
->size
, ARCH_CONVERT
));
989 INT_SET(entry
->hashval
, ARCH_CONVERT
, args
->hashval
);
990 entry
->namelen
= args
->namelen
;
991 xfs_da_log_buf(args
->trans
, bp
,
992 XFS_DA_LOGRANGE(leaf
, entry
, sizeof(*entry
)));
995 * Copy the string and inode number into the new space.
997 namest
= XFS_DIR_LEAF_NAMESTRUCT(leaf
, INT_GET(entry
->nameidx
, ARCH_CONVERT
));
998 XFS_DIR_SF_PUT_DIRINO(&args
->inumber
, &namest
->inumber
);
999 memcpy(namest
->name
, args
->name
, args
->namelen
);
1000 xfs_da_log_buf(args
->trans
, bp
,
1001 XFS_DA_LOGRANGE(leaf
, namest
, XFS_DIR_LEAF_ENTSIZE_BYENTRY(entry
)));
1004 * Update the control info for this leaf node
1006 if (INT_GET(entry
->nameidx
, ARCH_CONVERT
) < INT_GET(hdr
->firstused
, ARCH_CONVERT
))
1007 INT_COPY(hdr
->firstused
, entry
->nameidx
, ARCH_CONVERT
);
1008 ASSERT(INT_GET(hdr
->firstused
, ARCH_CONVERT
) >= ((INT_GET(hdr
->count
, ARCH_CONVERT
)*sizeof(*entry
))+sizeof(*hdr
)));
1009 tmp
= (INT_GET(hdr
->count
, ARCH_CONVERT
)-1) * (uint
)sizeof(xfs_dir_leaf_entry_t
)
1010 + (uint
)sizeof(xfs_dir_leaf_hdr_t
);
1011 map
= &hdr
->freemap
[0];
1012 for (i
= 0; i
< XFS_DIR_LEAF_MAPSIZE
; map
++, i
++) {
1013 if (INT_GET(map
->base
, ARCH_CONVERT
) == tmp
) {
1014 INT_MOD(map
->base
, ARCH_CONVERT
, (uint
)sizeof(xfs_dir_leaf_entry_t
));
1015 INT_MOD(map
->size
, ARCH_CONVERT
, -((uint
)sizeof(xfs_dir_leaf_entry_t
)));
1018 INT_MOD(hdr
->namebytes
, ARCH_CONVERT
, args
->namelen
);
1019 xfs_da_log_buf(args
->trans
, bp
,
1020 XFS_DA_LOGRANGE(leaf
, hdr
, sizeof(*hdr
)));
1024 * Garbage collect a leaf directory block by copying it to a new buffer.
1027 xfs_dir_leaf_compact(xfs_trans_t
*trans
, xfs_dabuf_t
*bp
, int musthave
,
1030 xfs_dir_leafblock_t
*leaf_s
, *leaf_d
;
1031 xfs_dir_leaf_hdr_t
*hdr_s
, *hdr_d
;
1034 char *tmpbuffer2
=NULL
;
1038 mp
= trans
->t_mountp
;
1039 lbsize
= XFS_LBSIZE(mp
);
1040 tmpbuffer
= kmem_alloc(lbsize
, KM_SLEEP
);
1041 ASSERT(tmpbuffer
!= NULL
);
1042 memcpy(tmpbuffer
, bp
->data
, lbsize
);
1045 * Make a second copy in case xfs_dir_leaf_moveents()
1046 * below destroys the original.
1048 if (musthave
|| justcheck
) {
1049 tmpbuffer2
= kmem_alloc(lbsize
, KM_SLEEP
);
1050 memcpy(tmpbuffer2
, bp
->data
, lbsize
);
1052 memset(bp
->data
, 0, lbsize
);
1055 * Copy basic information
1057 leaf_s
= (xfs_dir_leafblock_t
*)tmpbuffer
;
1059 hdr_s
= &leaf_s
->hdr
;
1060 hdr_d
= &leaf_d
->hdr
;
1061 hdr_d
->info
= hdr_s
->info
; /* struct copy */
1062 INT_SET(hdr_d
->firstused
, ARCH_CONVERT
, lbsize
);
1063 if (!hdr_d
->firstused
)
1064 INT_SET(hdr_d
->firstused
, ARCH_CONVERT
, lbsize
- 1);
1065 hdr_d
->namebytes
= 0;
1068 INT_SET(hdr_d
->freemap
[0].base
, ARCH_CONVERT
, sizeof(xfs_dir_leaf_hdr_t
));
1069 INT_SET(hdr_d
->freemap
[0].size
, ARCH_CONVERT
, INT_GET(hdr_d
->firstused
, ARCH_CONVERT
) - INT_GET(hdr_d
->freemap
[0].base
, ARCH_CONVERT
));
1072 * Copy all entry's in the same (sorted) order,
1073 * but allocate filenames packed and in sequence.
1074 * This changes the source (leaf_s) as well.
1076 xfs_dir_leaf_moveents(leaf_s
, 0, leaf_d
, 0, (int)INT_GET(hdr_s
->count
, ARCH_CONVERT
), mp
);
1078 if (musthave
&& INT_GET(hdr_d
->freemap
[0].size
, ARCH_CONVERT
) < musthave
)
1079 rval
= XFS_ERROR(ENOSPC
);
1083 if (justcheck
|| rval
== ENOSPC
) {
1085 memcpy(bp
->data
, tmpbuffer2
, lbsize
);
1087 xfs_da_log_buf(trans
, bp
, 0, lbsize
- 1);
1090 kmem_free(tmpbuffer
, lbsize
);
1091 if (musthave
|| justcheck
)
1092 kmem_free(tmpbuffer2
, lbsize
);
1097 * Redistribute the directory entries between two leaf nodes,
1098 * taking into account the size of the new entry.
1100 * NOTE: if new block is empty, then it will get the upper half of old block.
1103 xfs_dir_leaf_rebalance(xfs_da_state_t
*state
, xfs_da_state_blk_t
*blk1
,
1104 xfs_da_state_blk_t
*blk2
)
1106 xfs_da_state_blk_t
*tmp_blk
;
1107 xfs_dir_leafblock_t
*leaf1
, *leaf2
;
1108 xfs_dir_leaf_hdr_t
*hdr1
, *hdr2
;
1109 int count
, totallen
, max
, space
, swap
;
1112 * Set up environment.
1114 ASSERT(blk1
->magic
== XFS_DIR_LEAF_MAGIC
);
1115 ASSERT(blk2
->magic
== XFS_DIR_LEAF_MAGIC
);
1116 leaf1
= blk1
->bp
->data
;
1117 leaf2
= blk2
->bp
->data
;
1118 ASSERT(INT_GET(leaf1
->hdr
.info
.magic
, ARCH_CONVERT
) == XFS_DIR_LEAF_MAGIC
);
1119 ASSERT(INT_GET(leaf2
->hdr
.info
.magic
, ARCH_CONVERT
) == XFS_DIR_LEAF_MAGIC
);
1122 * Check ordering of blocks, reverse if it makes things simpler.
1125 if (xfs_dir_leaf_order(blk1
->bp
, blk2
->bp
)) {
1129 leaf1
= blk1
->bp
->data
;
1130 leaf2
= blk2
->bp
->data
;
1137 * Examine entries until we reduce the absolute difference in
1138 * byte usage between the two blocks to a minimum. Then get
1139 * the direction to copy and the number of elements to move.
1141 state
->inleaf
= xfs_dir_leaf_figure_balance(state
, blk1
, blk2
,
1144 state
->inleaf
= !state
->inleaf
;
1147 * Move any entries required from leaf to leaf:
1149 if (count
< INT_GET(hdr1
->count
, ARCH_CONVERT
)) {
1151 * Figure the total bytes to be added to the destination leaf.
1153 count
= INT_GET(hdr1
->count
, ARCH_CONVERT
) - count
; /* number entries being moved */
1154 space
= INT_GET(hdr1
->namebytes
, ARCH_CONVERT
) - totallen
;
1155 space
+= count
* ((uint
)sizeof(xfs_dir_leaf_name_t
)-1);
1156 space
+= count
* (uint
)sizeof(xfs_dir_leaf_entry_t
);
1159 * leaf2 is the destination, compact it if it looks tight.
1161 max
= INT_GET(hdr2
->firstused
, ARCH_CONVERT
) - (uint
)sizeof(xfs_dir_leaf_hdr_t
);
1162 max
-= INT_GET(hdr2
->count
, ARCH_CONVERT
) * (uint
)sizeof(xfs_dir_leaf_entry_t
);
1164 xfs_dir_leaf_compact(state
->args
->trans
, blk2
->bp
,
1169 * Move high entries from leaf1 to low end of leaf2.
1171 xfs_dir_leaf_moveents(leaf1
, INT_GET(hdr1
->count
, ARCH_CONVERT
) - count
,
1172 leaf2
, 0, count
, state
->mp
);
1174 xfs_da_log_buf(state
->args
->trans
, blk1
->bp
, 0,
1175 state
->blocksize
-1);
1176 xfs_da_log_buf(state
->args
->trans
, blk2
->bp
, 0,
1177 state
->blocksize
-1);
1179 } else if (count
> INT_GET(hdr1
->count
, ARCH_CONVERT
)) {
1181 * Figure the total bytes to be added to the destination leaf.
1183 count
-= INT_GET(hdr1
->count
, ARCH_CONVERT
); /* number entries being moved */
1184 space
= totallen
- INT_GET(hdr1
->namebytes
, ARCH_CONVERT
);
1185 space
+= count
* ((uint
)sizeof(xfs_dir_leaf_name_t
)-1);
1186 space
+= count
* (uint
)sizeof(xfs_dir_leaf_entry_t
);
1189 * leaf1 is the destination, compact it if it looks tight.
1191 max
= INT_GET(hdr1
->firstused
, ARCH_CONVERT
) - (uint
)sizeof(xfs_dir_leaf_hdr_t
);
1192 max
-= INT_GET(hdr1
->count
, ARCH_CONVERT
) * (uint
)sizeof(xfs_dir_leaf_entry_t
);
1194 xfs_dir_leaf_compact(state
->args
->trans
, blk1
->bp
,
1199 * Move low entries from leaf2 to high end of leaf1.
1201 xfs_dir_leaf_moveents(leaf2
, 0, leaf1
, (int)INT_GET(hdr1
->count
, ARCH_CONVERT
),
1204 xfs_da_log_buf(state
->args
->trans
, blk1
->bp
, 0,
1205 state
->blocksize
-1);
1206 xfs_da_log_buf(state
->args
->trans
, blk2
->bp
, 0,
1207 state
->blocksize
-1);
1211 * Copy out last hashval in each block for B-tree code.
1213 blk1
->hashval
= INT_GET(leaf1
->entries
[ INT_GET(leaf1
->hdr
.count
, ARCH_CONVERT
)-1 ].hashval
, ARCH_CONVERT
);
1214 blk2
->hashval
= INT_GET(leaf2
->entries
[ INT_GET(leaf2
->hdr
.count
, ARCH_CONVERT
)-1 ].hashval
, ARCH_CONVERT
);
1217 * Adjust the expected index for insertion.
1218 * GROT: this doesn't work unless blk2 was originally empty.
1220 if (!state
->inleaf
) {
1221 blk2
->index
= blk1
->index
- INT_GET(leaf1
->hdr
.count
, ARCH_CONVERT
);
1226 * Examine entries until we reduce the absolute difference in
1227 * byte usage between the two blocks to a minimum.
1228 * GROT: Is this really necessary? With other than a 512 byte blocksize,
1229 * GROT: there will always be enough room in either block for a new entry.
1230 * GROT: Do a double-split for this case?
1233 xfs_dir_leaf_figure_balance(xfs_da_state_t
*state
,
1234 xfs_da_state_blk_t
*blk1
,
1235 xfs_da_state_blk_t
*blk2
,
1236 int *countarg
, int *namebytesarg
)
1238 xfs_dir_leafblock_t
*leaf1
, *leaf2
;
1239 xfs_dir_leaf_hdr_t
*hdr1
, *hdr2
;
1240 xfs_dir_leaf_entry_t
*entry
;
1241 int count
, max
, totallen
, half
;
1242 int lastdelta
, foundit
, tmp
;
1245 * Set up environment.
1247 leaf1
= blk1
->bp
->data
;
1248 leaf2
= blk2
->bp
->data
;
1255 * Examine entries until we reduce the absolute difference in
1256 * byte usage between the two blocks to a minimum.
1258 max
= INT_GET(hdr1
->count
, ARCH_CONVERT
) + INT_GET(hdr2
->count
, ARCH_CONVERT
);
1259 half
= (max
+1) * (uint
)(sizeof(*entry
)+sizeof(xfs_dir_leaf_entry_t
)-1);
1260 half
+= INT_GET(hdr1
->namebytes
, ARCH_CONVERT
) + INT_GET(hdr2
->namebytes
, ARCH_CONVERT
) + state
->args
->namelen
;
1262 lastdelta
= state
->blocksize
;
1263 entry
= &leaf1
->entries
[0];
1264 for (count
= 0; count
< max
; entry
++, count
++) {
1266 #define XFS_DIR_ABS(A) (((A) < 0) ? -(A) : (A))
1268 * The new entry is in the first block, account for it.
1270 if (count
== blk1
->index
) {
1271 tmp
= totallen
+ (uint
)sizeof(*entry
)
1272 + XFS_DIR_LEAF_ENTSIZE_BYNAME(state
->args
->namelen
);
1273 if (XFS_DIR_ABS(half
- tmp
) > lastdelta
)
1275 lastdelta
= XFS_DIR_ABS(half
- tmp
);
1281 * Wrap around into the second block if necessary.
1283 if (count
== INT_GET(hdr1
->count
, ARCH_CONVERT
)) {
1285 entry
= &leaf1
->entries
[0];
1289 * Figure out if next leaf entry would be too much.
1291 tmp
= totallen
+ (uint
)sizeof(*entry
)
1292 + XFS_DIR_LEAF_ENTSIZE_BYENTRY(entry
);
1293 if (XFS_DIR_ABS(half
- tmp
) > lastdelta
)
1295 lastdelta
= XFS_DIR_ABS(half
- tmp
);
1301 * Calculate the number of namebytes that will end up in lower block.
1302 * If new entry not in lower block, fix up the count.
1305 count
* (uint
)(sizeof(*entry
)+sizeof(xfs_dir_leaf_entry_t
)-1);
1307 totallen
-= (sizeof(*entry
)+sizeof(xfs_dir_leaf_entry_t
)-1) +
1308 state
->args
->namelen
;
1312 *namebytesarg
= totallen
;
1316 /*========================================================================
1317 * Routines used for shrinking the Btree.
1318 *========================================================================*/
1321 * Check a leaf block and its neighbors to see if the block should be
1322 * collapsed into one or the other neighbor. Always keep the block
1323 * with the smaller block number.
1324 * If the current block is over 50% full, don't try to join it, return 0.
1325 * If the block is empty, fill in the state structure and return 2.
1326 * If it can be collapsed, fill in the state structure and return 1.
1327 * If nothing can be done, return 0.
1330 xfs_dir_leaf_toosmall(xfs_da_state_t
*state
, int *action
)
1332 xfs_dir_leafblock_t
*leaf
;
1333 xfs_da_state_blk_t
*blk
;
1334 xfs_da_blkinfo_t
*info
;
1335 int count
, bytes
, forward
, error
, retval
, i
;
1340 * Check for the degenerate case of the block being over 50% full.
1341 * If so, it's not worth even looking to see if we might be able
1342 * to coalesce with a sibling.
1344 blk
= &state
->path
.blk
[ state
->path
.active
-1 ];
1345 info
= blk
->bp
->data
;
1346 ASSERT(INT_GET(info
->magic
, ARCH_CONVERT
) == XFS_DIR_LEAF_MAGIC
);
1347 leaf
= (xfs_dir_leafblock_t
*)info
;
1348 count
= INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
);
1349 bytes
= (uint
)sizeof(xfs_dir_leaf_hdr_t
) +
1350 count
* (uint
)sizeof(xfs_dir_leaf_entry_t
) +
1351 count
* ((uint
)sizeof(xfs_dir_leaf_name_t
)-1) +
1352 INT_GET(leaf
->hdr
.namebytes
, ARCH_CONVERT
);
1353 if (bytes
> (state
->blocksize
>> 1)) {
1354 *action
= 0; /* blk over 50%, don't try to join */
1359 * Check for the degenerate case of the block being empty.
1360 * If the block is empty, we'll simply delete it, no need to
1361 * coalesce it with a sibling block. We choose (aribtrarily)
1362 * to merge with the forward block unless it is NULL.
1366 * Make altpath point to the block we want to keep and
1367 * path point to the block we want to drop (this one).
1369 forward
= info
->forw
;
1370 memcpy(&state
->altpath
, &state
->path
, sizeof(state
->path
));
1371 error
= xfs_da_path_shift(state
, &state
->altpath
, forward
,
1384 * Examine each sibling block to see if we can coalesce with
1385 * at least 25% free space to spare. We need to figure out
1386 * whether to merge with the forward or the backward block.
1387 * We prefer coalescing with the lower numbered sibling so as
1388 * to shrink a directory over time.
1390 forward
= (INT_GET(info
->forw
, ARCH_CONVERT
) < INT_GET(info
->back
, ARCH_CONVERT
)); /* start with smaller blk num */
1391 for (i
= 0; i
< 2; forward
= !forward
, i
++) {
1393 blkno
= INT_GET(info
->forw
, ARCH_CONVERT
);
1395 blkno
= INT_GET(info
->back
, ARCH_CONVERT
);
1398 error
= xfs_da_read_buf(state
->args
->trans
, state
->args
->dp
,
1405 leaf
= (xfs_dir_leafblock_t
*)info
;
1406 count
= INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
);
1407 bytes
= state
->blocksize
- (state
->blocksize
>>2);
1408 bytes
-= INT_GET(leaf
->hdr
.namebytes
, ARCH_CONVERT
);
1410 ASSERT(INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
) == XFS_DIR_LEAF_MAGIC
);
1411 count
+= INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
);
1412 bytes
-= INT_GET(leaf
->hdr
.namebytes
, ARCH_CONVERT
);
1413 bytes
-= count
* ((uint
)sizeof(xfs_dir_leaf_name_t
) - 1);
1414 bytes
-= count
* (uint
)sizeof(xfs_dir_leaf_entry_t
);
1415 bytes
-= (uint
)sizeof(xfs_dir_leaf_hdr_t
);
1417 break; /* fits with at least 25% to spare */
1419 xfs_da_brelse(state
->args
->trans
, bp
);
1425 xfs_da_buf_done(bp
);
1428 * Make altpath point to the block we want to keep (the lower
1429 * numbered block) and path point to the block we want to drop.
1431 memcpy(&state
->altpath
, &state
->path
, sizeof(state
->path
));
1432 if (blkno
< blk
->blkno
) {
1433 error
= xfs_da_path_shift(state
, &state
->altpath
, forward
,
1436 error
= xfs_da_path_shift(state
, &state
->path
, forward
,
1450 * Remove a name from the leaf directory structure.
1452 * Return 1 if leaf is less than 37% full, 0 if >= 37% full.
1453 * If two leaves are 37% full, when combined they will leave 25% free.
1456 xfs_dir_leaf_remove(xfs_trans_t
*trans
, xfs_dabuf_t
*bp
, int index
)
1458 xfs_dir_leafblock_t
*leaf
;
1459 xfs_dir_leaf_hdr_t
*hdr
;
1460 xfs_dir_leaf_map_t
*map
;
1461 xfs_dir_leaf_entry_t
*entry
;
1462 xfs_dir_leaf_name_t
*namest
;
1463 int before
, after
, smallest
, entsize
;
1464 int tablesize
, tmp
, i
;
1468 ASSERT(INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
) == XFS_DIR_LEAF_MAGIC
);
1470 mp
= trans
->t_mountp
;
1471 ASSERT((INT_GET(hdr
->count
, ARCH_CONVERT
) > 0) && (INT_GET(hdr
->count
, ARCH_CONVERT
) < (XFS_LBSIZE(mp
)/8)));
1472 ASSERT((index
>= 0) && (index
< INT_GET(hdr
->count
, ARCH_CONVERT
)));
1473 ASSERT(INT_GET(hdr
->firstused
, ARCH_CONVERT
) >= ((INT_GET(hdr
->count
, ARCH_CONVERT
)*sizeof(*entry
))+sizeof(*hdr
)));
1474 entry
= &leaf
->entries
[index
];
1475 ASSERT(INT_GET(entry
->nameidx
, ARCH_CONVERT
) >= INT_GET(hdr
->firstused
, ARCH_CONVERT
));
1476 ASSERT(INT_GET(entry
->nameidx
, ARCH_CONVERT
) < XFS_LBSIZE(mp
));
1479 * Scan through free region table:
1480 * check for adjacency of free'd entry with an existing one,
1481 * find smallest free region in case we need to replace it,
1482 * adjust any map that borders the entry table,
1484 tablesize
= INT_GET(hdr
->count
, ARCH_CONVERT
) * (uint
)sizeof(xfs_dir_leaf_entry_t
)
1485 + (uint
)sizeof(xfs_dir_leaf_hdr_t
);
1486 map
= &hdr
->freemap
[0];
1487 tmp
= INT_GET(map
->size
, ARCH_CONVERT
);
1488 before
= after
= -1;
1489 smallest
= XFS_DIR_LEAF_MAPSIZE
- 1;
1490 entsize
= XFS_DIR_LEAF_ENTSIZE_BYENTRY(entry
);
1491 for (i
= 0; i
< XFS_DIR_LEAF_MAPSIZE
; map
++, i
++) {
1492 ASSERT(INT_GET(map
->base
, ARCH_CONVERT
) < XFS_LBSIZE(mp
));
1493 ASSERT(INT_GET(map
->size
, ARCH_CONVERT
) < XFS_LBSIZE(mp
));
1494 if (INT_GET(map
->base
, ARCH_CONVERT
) == tablesize
) {
1495 INT_MOD(map
->base
, ARCH_CONVERT
, -((uint
)sizeof(xfs_dir_leaf_entry_t
)));
1496 INT_MOD(map
->size
, ARCH_CONVERT
, (uint
)sizeof(xfs_dir_leaf_entry_t
));
1499 if ((INT_GET(map
->base
, ARCH_CONVERT
) + INT_GET(map
->size
, ARCH_CONVERT
)) == INT_GET(entry
->nameidx
, ARCH_CONVERT
)) {
1501 } else if (INT_GET(map
->base
, ARCH_CONVERT
) == (INT_GET(entry
->nameidx
, ARCH_CONVERT
) + entsize
)) {
1503 } else if (INT_GET(map
->size
, ARCH_CONVERT
) < tmp
) {
1504 tmp
= INT_GET(map
->size
, ARCH_CONVERT
);
1510 * Coalesce adjacent freemap regions,
1511 * or replace the smallest region.
1513 if ((before
>= 0) || (after
>= 0)) {
1514 if ((before
>= 0) && (after
>= 0)) {
1515 map
= &hdr
->freemap
[before
];
1516 INT_MOD(map
->size
, ARCH_CONVERT
, entsize
);
1517 INT_MOD(map
->size
, ARCH_CONVERT
, INT_GET(hdr
->freemap
[after
].size
, ARCH_CONVERT
));
1518 hdr
->freemap
[after
].base
= 0;
1519 hdr
->freemap
[after
].size
= 0;
1520 } else if (before
>= 0) {
1521 map
= &hdr
->freemap
[before
];
1522 INT_MOD(map
->size
, ARCH_CONVERT
, entsize
);
1524 map
= &hdr
->freemap
[after
];
1525 INT_COPY(map
->base
, entry
->nameidx
, ARCH_CONVERT
);
1526 INT_MOD(map
->size
, ARCH_CONVERT
, entsize
);
1530 * Replace smallest region (if it is smaller than free'd entry)
1532 map
= &hdr
->freemap
[smallest
];
1533 if (INT_GET(map
->size
, ARCH_CONVERT
) < entsize
) {
1534 INT_COPY(map
->base
, entry
->nameidx
, ARCH_CONVERT
);
1535 INT_SET(map
->size
, ARCH_CONVERT
, entsize
);
1540 * Did we remove the first entry?
1542 if (INT_GET(entry
->nameidx
, ARCH_CONVERT
) == INT_GET(hdr
->firstused
, ARCH_CONVERT
))
1548 * Compress the remaining entries and zero out the removed stuff.
1550 namest
= XFS_DIR_LEAF_NAMESTRUCT(leaf
, INT_GET(entry
->nameidx
, ARCH_CONVERT
));
1551 memset((char *)namest
, 0, entsize
);
1552 xfs_da_log_buf(trans
, bp
, XFS_DA_LOGRANGE(leaf
, namest
, entsize
));
1554 INT_MOD(hdr
->namebytes
, ARCH_CONVERT
, -(entry
->namelen
));
1555 tmp
= (INT_GET(hdr
->count
, ARCH_CONVERT
) - index
) * (uint
)sizeof(xfs_dir_leaf_entry_t
);
1556 memmove(entry
, entry
+ 1, tmp
);
1557 INT_MOD(hdr
->count
, ARCH_CONVERT
, -1);
1558 xfs_da_log_buf(trans
, bp
,
1559 XFS_DA_LOGRANGE(leaf
, entry
, tmp
+ (uint
)sizeof(*entry
)));
1560 entry
= &leaf
->entries
[INT_GET(hdr
->count
, ARCH_CONVERT
)];
1561 memset((char *)entry
, 0, sizeof(xfs_dir_leaf_entry_t
));
1564 * If we removed the first entry, re-find the first used byte
1565 * in the name area. Note that if the entry was the "firstused",
1566 * then we don't have a "hole" in our block resulting from
1567 * removing the name.
1570 tmp
= XFS_LBSIZE(mp
);
1571 entry
= &leaf
->entries
[0];
1572 for (i
= INT_GET(hdr
->count
, ARCH_CONVERT
)-1; i
>= 0; entry
++, i
--) {
1573 ASSERT(INT_GET(entry
->nameidx
, ARCH_CONVERT
) >= INT_GET(hdr
->firstused
, ARCH_CONVERT
));
1574 ASSERT(INT_GET(entry
->nameidx
, ARCH_CONVERT
) < XFS_LBSIZE(mp
));
1575 if (INT_GET(entry
->nameidx
, ARCH_CONVERT
) < tmp
)
1576 tmp
= INT_GET(entry
->nameidx
, ARCH_CONVERT
);
1578 INT_SET(hdr
->firstused
, ARCH_CONVERT
, tmp
);
1579 if (!hdr
->firstused
)
1580 INT_SET(hdr
->firstused
, ARCH_CONVERT
, tmp
- 1);
1582 hdr
->holes
= 1; /* mark as needing compaction */
1585 xfs_da_log_buf(trans
, bp
, XFS_DA_LOGRANGE(leaf
, hdr
, sizeof(*hdr
)));
1588 * Check if leaf is less than 50% full, caller may want to
1589 * "join" the leaf with a sibling if so.
1591 tmp
= (uint
)sizeof(xfs_dir_leaf_hdr_t
);
1592 tmp
+= INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
) * (uint
)sizeof(xfs_dir_leaf_entry_t
);
1593 tmp
+= INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
) * ((uint
)sizeof(xfs_dir_leaf_name_t
) - 1);
1594 tmp
+= INT_GET(leaf
->hdr
.namebytes
, ARCH_CONVERT
);
1595 if (tmp
< mp
->m_dir_magicpct
)
1596 return(1); /* leaf is < 37% full */
1601 * Move all the directory entries from drop_leaf into save_leaf.
1604 xfs_dir_leaf_unbalance(xfs_da_state_t
*state
, xfs_da_state_blk_t
*drop_blk
,
1605 xfs_da_state_blk_t
*save_blk
)
1607 xfs_dir_leafblock_t
*drop_leaf
, *save_leaf
, *tmp_leaf
;
1608 xfs_dir_leaf_hdr_t
*drop_hdr
, *save_hdr
, *tmp_hdr
;
1613 * Set up environment.
1616 ASSERT(drop_blk
->magic
== XFS_DIR_LEAF_MAGIC
);
1617 ASSERT(save_blk
->magic
== XFS_DIR_LEAF_MAGIC
);
1618 drop_leaf
= drop_blk
->bp
->data
;
1619 save_leaf
= save_blk
->bp
->data
;
1620 ASSERT(INT_GET(drop_leaf
->hdr
.info
.magic
, ARCH_CONVERT
) == XFS_DIR_LEAF_MAGIC
);
1621 ASSERT(INT_GET(save_leaf
->hdr
.info
.magic
, ARCH_CONVERT
) == XFS_DIR_LEAF_MAGIC
);
1622 drop_hdr
= &drop_leaf
->hdr
;
1623 save_hdr
= &save_leaf
->hdr
;
1626 * Save last hashval from dying block for later Btree fixup.
1628 drop_blk
->hashval
= INT_GET(drop_leaf
->entries
[ drop_leaf
->hdr
.count
-1 ].hashval
, ARCH_CONVERT
);
1631 * Check if we need a temp buffer, or can we do it in place.
1632 * Note that we don't check "leaf" for holes because we will
1633 * always be dropping it, toosmall() decided that for us already.
1635 if (save_hdr
->holes
== 0) {
1637 * dest leaf has no holes, so we add there. May need
1638 * to make some room in the entry array.
1640 if (xfs_dir_leaf_order(save_blk
->bp
, drop_blk
->bp
)) {
1641 xfs_dir_leaf_moveents(drop_leaf
, 0, save_leaf
, 0,
1642 (int)INT_GET(drop_hdr
->count
, ARCH_CONVERT
), mp
);
1644 xfs_dir_leaf_moveents(drop_leaf
, 0,
1645 save_leaf
, INT_GET(save_hdr
->count
, ARCH_CONVERT
),
1646 (int)INT_GET(drop_hdr
->count
, ARCH_CONVERT
), mp
);
1650 * Destination has holes, so we make a temporary copy
1651 * of the leaf and add them both to that.
1653 tmpbuffer
= kmem_alloc(state
->blocksize
, KM_SLEEP
);
1654 ASSERT(tmpbuffer
!= NULL
);
1655 memset(tmpbuffer
, 0, state
->blocksize
);
1656 tmp_leaf
= (xfs_dir_leafblock_t
*)tmpbuffer
;
1657 tmp_hdr
= &tmp_leaf
->hdr
;
1658 tmp_hdr
->info
= save_hdr
->info
; /* struct copy */
1660 INT_SET(tmp_hdr
->firstused
, ARCH_CONVERT
, state
->blocksize
);
1661 if (!tmp_hdr
->firstused
)
1662 INT_SET(tmp_hdr
->firstused
, ARCH_CONVERT
, state
->blocksize
- 1);
1663 tmp_hdr
->namebytes
= 0;
1664 if (xfs_dir_leaf_order(save_blk
->bp
, drop_blk
->bp
)) {
1665 xfs_dir_leaf_moveents(drop_leaf
, 0, tmp_leaf
, 0,
1666 (int)INT_GET(drop_hdr
->count
, ARCH_CONVERT
), mp
);
1667 xfs_dir_leaf_moveents(save_leaf
, 0,
1668 tmp_leaf
, INT_GET(tmp_leaf
->hdr
.count
, ARCH_CONVERT
),
1669 (int)INT_GET(save_hdr
->count
, ARCH_CONVERT
), mp
);
1671 xfs_dir_leaf_moveents(save_leaf
, 0, tmp_leaf
, 0,
1672 (int)INT_GET(save_hdr
->count
, ARCH_CONVERT
), mp
);
1673 xfs_dir_leaf_moveents(drop_leaf
, 0,
1674 tmp_leaf
, INT_GET(tmp_leaf
->hdr
.count
, ARCH_CONVERT
),
1675 (int)INT_GET(drop_hdr
->count
, ARCH_CONVERT
), mp
);
1677 memcpy(save_leaf
, tmp_leaf
, state
->blocksize
);
1678 kmem_free(tmpbuffer
, state
->blocksize
);
1681 xfs_da_log_buf(state
->args
->trans
, save_blk
->bp
, 0,
1682 state
->blocksize
- 1);
1685 * Copy out last hashval in each block for B-tree code.
1687 save_blk
->hashval
= INT_GET(save_leaf
->entries
[ INT_GET(save_leaf
->hdr
.count
, ARCH_CONVERT
)-1 ].hashval
, ARCH_CONVERT
);
1690 /*========================================================================
1691 * Routines used for finding things in the Btree.
1692 *========================================================================*/
1695 * Look up a name in a leaf directory structure.
1696 * This is the internal routine, it uses the caller's buffer.
1698 * Note that duplicate keys are allowed, but only check within the
1699 * current leaf node. The Btree code must check in adjacent leaf nodes.
1701 * Return in *index the index into the entry[] array of either the found
1702 * entry, or where the entry should have been (insert before that entry).
1704 * Don't change the args->inumber unless we find the filename.
1707 xfs_dir_leaf_lookup_int(xfs_dabuf_t
*bp
, xfs_da_args_t
*args
, int *index
)
1709 xfs_dir_leafblock_t
*leaf
;
1710 xfs_dir_leaf_entry_t
*entry
;
1711 xfs_dir_leaf_name_t
*namest
;
1713 xfs_dahash_t hashval
;
1716 ASSERT(INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
) == XFS_DIR_LEAF_MAGIC
);
1717 ASSERT(INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
) < (XFS_LBSIZE(args
->dp
->i_mount
)/8));
1720 * Binary search. (note: small blocks will skip this loop)
1722 hashval
= args
->hashval
;
1723 probe
= span
= INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
) / 2;
1724 for (entry
= &leaf
->entries
[probe
]; span
> 4;
1725 entry
= &leaf
->entries
[probe
]) {
1727 if (INT_GET(entry
->hashval
, ARCH_CONVERT
) < hashval
)
1729 else if (INT_GET(entry
->hashval
, ARCH_CONVERT
) > hashval
)
1734 ASSERT((probe
>= 0) && \
1735 ((!leaf
->hdr
.count
) || (probe
< INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
))));
1736 ASSERT((span
<= 4) || (INT_GET(entry
->hashval
, ARCH_CONVERT
) == hashval
));
1739 * Since we may have duplicate hashval's, find the first matching
1740 * hashval in the leaf.
1742 while ((probe
> 0) && (INT_GET(entry
->hashval
, ARCH_CONVERT
) >= hashval
)) {
1746 while ((probe
< INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
)) && (INT_GET(entry
->hashval
, ARCH_CONVERT
) < hashval
)) {
1750 if ((probe
== INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
)) || (INT_GET(entry
->hashval
, ARCH_CONVERT
) != hashval
)) {
1752 ASSERT(args
->oknoent
);
1753 return(XFS_ERROR(ENOENT
));
1757 * Duplicate keys may be present, so search all of them for a match.
1759 while ((probe
< INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
)) && (INT_GET(entry
->hashval
, ARCH_CONVERT
) == hashval
)) {
1760 namest
= XFS_DIR_LEAF_NAMESTRUCT(leaf
, INT_GET(entry
->nameidx
, ARCH_CONVERT
));
1761 if (entry
->namelen
== args
->namelen
&&
1762 namest
->name
[0] == args
->name
[0] &&
1763 memcmp(args
->name
, namest
->name
, args
->namelen
) == 0) {
1764 XFS_DIR_SF_GET_DIRINO(&namest
->inumber
, &args
->inumber
);
1766 return(XFS_ERROR(EEXIST
));
1772 ASSERT(probe
== INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
) || args
->oknoent
);
1773 return(XFS_ERROR(ENOENT
));
1776 /*========================================================================
1778 *========================================================================*/
1781 * Move the indicated entries from one leaf to another.
1782 * NOTE: this routine modifies both source and destination leaves.
1786 xfs_dir_leaf_moveents(xfs_dir_leafblock_t
*leaf_s
, int start_s
,
1787 xfs_dir_leafblock_t
*leaf_d
, int start_d
,
1788 int count
, xfs_mount_t
*mp
)
1790 xfs_dir_leaf_hdr_t
*hdr_s
, *hdr_d
;
1791 xfs_dir_leaf_entry_t
*entry_s
, *entry_d
;
1795 * Check for nothing to do.
1801 * Set up environment.
1803 ASSERT(INT_GET(leaf_s
->hdr
.info
.magic
, ARCH_CONVERT
) == XFS_DIR_LEAF_MAGIC
);
1804 ASSERT(INT_GET(leaf_d
->hdr
.info
.magic
, ARCH_CONVERT
) == XFS_DIR_LEAF_MAGIC
);
1805 hdr_s
= &leaf_s
->hdr
;
1806 hdr_d
= &leaf_d
->hdr
;
1807 ASSERT((INT_GET(hdr_s
->count
, ARCH_CONVERT
) > 0) && (INT_GET(hdr_s
->count
, ARCH_CONVERT
) < (XFS_LBSIZE(mp
)/8)));
1808 ASSERT(INT_GET(hdr_s
->firstused
, ARCH_CONVERT
) >=
1809 ((INT_GET(hdr_s
->count
, ARCH_CONVERT
)*sizeof(*entry_s
))+sizeof(*hdr_s
)));
1810 ASSERT(INT_GET(hdr_d
->count
, ARCH_CONVERT
) < (XFS_LBSIZE(mp
)/8));
1811 ASSERT(INT_GET(hdr_d
->firstused
, ARCH_CONVERT
) >=
1812 ((INT_GET(hdr_d
->count
, ARCH_CONVERT
)*sizeof(*entry_d
))+sizeof(*hdr_d
)));
1814 ASSERT(start_s
< INT_GET(hdr_s
->count
, ARCH_CONVERT
));
1815 ASSERT(start_d
<= INT_GET(hdr_d
->count
, ARCH_CONVERT
));
1816 ASSERT(count
<= INT_GET(hdr_s
->count
, ARCH_CONVERT
));
1819 * Move the entries in the destination leaf up to make a hole?
1821 if (start_d
< INT_GET(hdr_d
->count
, ARCH_CONVERT
)) {
1822 tmp
= INT_GET(hdr_d
->count
, ARCH_CONVERT
) - start_d
;
1823 tmp
*= (uint
)sizeof(xfs_dir_leaf_entry_t
);
1824 entry_s
= &leaf_d
->entries
[start_d
];
1825 entry_d
= &leaf_d
->entries
[start_d
+ count
];
1826 memcpy(entry_d
, entry_s
, tmp
);
1830 * Copy all entry's in the same (sorted) order,
1831 * but allocate filenames packed and in sequence.
1833 entry_s
= &leaf_s
->entries
[start_s
];
1834 entry_d
= &leaf_d
->entries
[start_d
];
1835 for (i
= 0; i
< count
; entry_s
++, entry_d
++, i
++) {
1836 ASSERT(INT_GET(entry_s
->nameidx
, ARCH_CONVERT
) >= INT_GET(hdr_s
->firstused
, ARCH_CONVERT
));
1837 tmp
= XFS_DIR_LEAF_ENTSIZE_BYENTRY(entry_s
);
1838 INT_MOD(hdr_d
->firstused
, ARCH_CONVERT
, -(tmp
));
1839 entry_d
->hashval
= entry_s
->hashval
; /* INT_: direct copy */
1840 INT_COPY(entry_d
->nameidx
, hdr_d
->firstused
, ARCH_CONVERT
);
1841 entry_d
->namelen
= entry_s
->namelen
;
1842 ASSERT(INT_GET(entry_d
->nameidx
, ARCH_CONVERT
) + tmp
<= XFS_LBSIZE(mp
));
1843 memcpy(XFS_DIR_LEAF_NAMESTRUCT(leaf_d
, INT_GET(entry_d
->nameidx
, ARCH_CONVERT
)),
1844 XFS_DIR_LEAF_NAMESTRUCT(leaf_s
, INT_GET(entry_s
->nameidx
, ARCH_CONVERT
)), tmp
);
1845 ASSERT(INT_GET(entry_s
->nameidx
, ARCH_CONVERT
) + tmp
<= XFS_LBSIZE(mp
));
1846 memset((char *)XFS_DIR_LEAF_NAMESTRUCT(leaf_s
, INT_GET(entry_s
->nameidx
, ARCH_CONVERT
)),
1848 INT_MOD(hdr_s
->namebytes
, ARCH_CONVERT
, -(entry_d
->namelen
));
1849 INT_MOD(hdr_d
->namebytes
, ARCH_CONVERT
, entry_d
->namelen
);
1850 INT_MOD(hdr_s
->count
, ARCH_CONVERT
, -1);
1851 INT_MOD(hdr_d
->count
, ARCH_CONVERT
, +1);
1852 tmp
= INT_GET(hdr_d
->count
, ARCH_CONVERT
) * (uint
)sizeof(xfs_dir_leaf_entry_t
)
1853 + (uint
)sizeof(xfs_dir_leaf_hdr_t
);
1854 ASSERT(INT_GET(hdr_d
->firstused
, ARCH_CONVERT
) >= tmp
);
1859 * Zero out the entries we just copied.
1861 if (start_s
== INT_GET(hdr_s
->count
, ARCH_CONVERT
)) {
1862 tmp
= count
* (uint
)sizeof(xfs_dir_leaf_entry_t
);
1863 entry_s
= &leaf_s
->entries
[start_s
];
1864 ASSERT((char *)entry_s
+ tmp
<= (char *)leaf_s
+ XFS_LBSIZE(mp
));
1865 memset((char *)entry_s
, 0, tmp
);
1868 * Move the remaining entries down to fill the hole,
1869 * then zero the entries at the top.
1871 tmp
= INT_GET(hdr_s
->count
, ARCH_CONVERT
) - count
;
1872 tmp
*= (uint
)sizeof(xfs_dir_leaf_entry_t
);
1873 entry_s
= &leaf_s
->entries
[start_s
+ count
];
1874 entry_d
= &leaf_s
->entries
[start_s
];
1875 memcpy(entry_d
, entry_s
, tmp
);
1877 tmp
= count
* (uint
)sizeof(xfs_dir_leaf_entry_t
);
1878 entry_s
= &leaf_s
->entries
[INT_GET(hdr_s
->count
, ARCH_CONVERT
)];
1879 ASSERT((char *)entry_s
+ tmp
<= (char *)leaf_s
+ XFS_LBSIZE(mp
));
1880 memset((char *)entry_s
, 0, tmp
);
1884 * Fill in the freemap information
1886 INT_SET(hdr_d
->freemap
[0].base
, ARCH_CONVERT
, (uint
)sizeof(xfs_dir_leaf_hdr_t
));
1887 INT_MOD(hdr_d
->freemap
[0].base
, ARCH_CONVERT
, INT_GET(hdr_d
->count
, ARCH_CONVERT
) * (uint
)sizeof(xfs_dir_leaf_entry_t
));
1888 INT_SET(hdr_d
->freemap
[0].size
, ARCH_CONVERT
, INT_GET(hdr_d
->firstused
, ARCH_CONVERT
) - INT_GET(hdr_d
->freemap
[0].base
, ARCH_CONVERT
));
1889 INT_SET(hdr_d
->freemap
[1].base
, ARCH_CONVERT
, (hdr_d
->freemap
[2].base
= 0));
1890 INT_SET(hdr_d
->freemap
[1].size
, ARCH_CONVERT
, (hdr_d
->freemap
[2].size
= 0));
1891 hdr_s
->holes
= 1; /* leaf may not be compact */
1895 * Compare two leaf blocks "order".
1898 xfs_dir_leaf_order(xfs_dabuf_t
*leaf1_bp
, xfs_dabuf_t
*leaf2_bp
)
1900 xfs_dir_leafblock_t
*leaf1
, *leaf2
;
1902 leaf1
= leaf1_bp
->data
;
1903 leaf2
= leaf2_bp
->data
;
1904 ASSERT((INT_GET(leaf1
->hdr
.info
.magic
, ARCH_CONVERT
) == XFS_DIR_LEAF_MAGIC
) &&
1905 (INT_GET(leaf2
->hdr
.info
.magic
, ARCH_CONVERT
) == XFS_DIR_LEAF_MAGIC
));
1906 if ((INT_GET(leaf1
->hdr
.count
, ARCH_CONVERT
) > 0) && (INT_GET(leaf2
->hdr
.count
, ARCH_CONVERT
) > 0) &&
1907 ((INT_GET(leaf2
->entries
[ 0 ].hashval
, ARCH_CONVERT
) <
1908 INT_GET(leaf1
->entries
[ 0 ].hashval
, ARCH_CONVERT
)) ||
1909 (INT_GET(leaf2
->entries
[ INT_GET(leaf2
->hdr
.count
, ARCH_CONVERT
)-1 ].hashval
, ARCH_CONVERT
) <
1910 INT_GET(leaf1
->entries
[ INT_GET(leaf1
->hdr
.count
, ARCH_CONVERT
)-1 ].hashval
, ARCH_CONVERT
)))) {
1917 * Pick up the last hashvalue from a leaf block.
1920 xfs_dir_leaf_lasthash(xfs_dabuf_t
*bp
, int *count
)
1922 xfs_dir_leafblock_t
*leaf
;
1925 ASSERT(INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
) == XFS_DIR_LEAF_MAGIC
);
1927 *count
= INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
);
1928 if (!leaf
->hdr
.count
)
1930 return(INT_GET(leaf
->entries
[ INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
)-1 ].hashval
, ARCH_CONVERT
));
1934 * Copy out directory entries for getdents(), for leaf directories.
1937 xfs_dir_leaf_getdents_int(
1947 xfs_dir_leafblock_t
*leaf
;
1948 xfs_dir_leaf_entry_t
*entry
;
1949 xfs_dir_leaf_name_t
*namest
;
1950 int entno
, want_entno
, i
, nextentno
;
1952 xfs_dahash_t cookhash
;
1953 xfs_dahash_t nexthash
= 0;
1954 #if (BITS_PER_LONG == 32)
1955 xfs_dahash_t lasthash
= XFS_DA_MAXHASH
;
1957 xfs_dir_put_args_t p
;
1961 if (INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
) != XFS_DIR_LEAF_MAGIC
) {
1963 return(XFS_ERROR(ENOENT
)); /* XXX wrong code */
1966 want_entno
= XFS_DA_COOKIE_ENTRY(mp
, uio
->uio_offset
);
1968 cookhash
= XFS_DA_COOKIE_HASH(mp
, uio
->uio_offset
);
1970 xfs_dir_trace_g_dul("leaf: start", dp
, uio
, leaf
);
1973 * Re-find our place.
1975 for (i
= entno
= 0, entry
= &leaf
->entries
[0];
1976 i
< INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
);
1979 namest
= XFS_DIR_LEAF_NAMESTRUCT(leaf
,
1980 INT_GET(entry
->nameidx
, ARCH_CONVERT
));
1983 ((char *)namest
< (char *)leaf
) ||
1984 ((char *)namest
>= (char *)leaf
+ XFS_LBSIZE(mp
)))) {
1985 XFS_CORRUPTION_ERROR("xfs_dir_leaf_getdents_int(1)",
1986 XFS_ERRLEVEL_LOW
, mp
, leaf
);
1987 xfs_dir_trace_g_du("leaf: corrupted", dp
, uio
);
1988 return XFS_ERROR(EFSCORRUPTED
);
1990 if (INT_GET(entry
->hashval
, ARCH_CONVERT
) >= cookhash
) {
1991 if ( entno
< want_entno
1992 && INT_GET(entry
->hashval
, ARCH_CONVERT
)
1995 * Trying to get to a particular offset in a
1996 * run of equal-hashval entries.
1999 } else if ( want_entno
> 0
2000 && entno
== want_entno
2001 && INT_GET(entry
->hashval
, ARCH_CONVERT
)
2011 if (i
== INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
)) {
2012 xfs_dir_trace_g_du("leaf: hash not found", dp
, uio
);
2013 if (!INT_GET(leaf
->hdr
.info
.forw
, ARCH_CONVERT
))
2015 XFS_DA_MAKE_COOKIE(mp
, 0, 0, XFS_DA_MAXHASH
);
2017 * Don't set uio_offset if there's another block:
2018 * the node code will be setting uio_offset anyway.
2023 xfs_dir_trace_g_due("leaf: hash found", dp
, uio
, entry
);
2030 * We're synchronized, start copying entries out to the user.
2032 for (; entno
>= 0 && i
< INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
);
2033 entry
++, i
++, (entno
= nextentno
)) {
2034 int lastresid
=0, retval
;
2035 xfs_dircook_t lastoffset
;
2036 xfs_dahash_t thishash
;
2039 * Check for a damaged directory leaf block and pick up
2040 * the inode number from this entry.
2042 namest
= XFS_DIR_LEAF_NAMESTRUCT(leaf
,
2043 INT_GET(entry
->nameidx
, ARCH_CONVERT
));
2046 ((char *)namest
< (char *)leaf
) ||
2047 ((char *)namest
>= (char *)leaf
+ XFS_LBSIZE(mp
)))) {
2048 XFS_CORRUPTION_ERROR("xfs_dir_leaf_getdents_int(2)",
2049 XFS_ERRLEVEL_LOW
, mp
, leaf
);
2050 xfs_dir_trace_g_du("leaf: corrupted", dp
, uio
);
2051 return XFS_ERROR(EFSCORRUPTED
);
2054 xfs_dir_trace_g_duc("leaf: middle cookie ",
2057 if (i
< (INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
) - 1)) {
2058 nexthash
= INT_GET(entry
[1].hashval
, ARCH_CONVERT
);
2060 if (nexthash
== INT_GET(entry
->hashval
, ARCH_CONVERT
))
2061 nextentno
= entno
+ 1;
2064 XFS_PUT_COOKIE(p
.cook
, mp
, bno
, nextentno
, nexthash
);
2065 xfs_dir_trace_g_duc("leaf: middle cookie ",
2068 } else if ((thishash
= INT_GET(leaf
->hdr
.info
.forw
,
2071 xfs_dir_leafblock_t
*leaf2
;
2073 ASSERT(nextda
!= -1);
2075 retval
= xfs_da_read_buf(dp
->i_transp
, dp
, thishash
,
2076 nextda
, &bp2
, XFS_DATA_FORK
);
2080 ASSERT(bp2
!= NULL
);
2085 (INT_GET(leaf2
->hdr
.info
.magic
, ARCH_CONVERT
)
2086 != XFS_DIR_LEAF_MAGIC
)
2087 || (INT_GET(leaf2
->hdr
.info
.back
, ARCH_CONVERT
)
2088 != bno
))) { /* GROT */
2089 XFS_CORRUPTION_ERROR("xfs_dir_leaf_getdents_int(3)",
2090 XFS_ERRLEVEL_LOW
, mp
,
2092 xfs_da_brelse(dp
->i_transp
, bp2
);
2094 return(XFS_ERROR(EFSCORRUPTED
));
2097 nexthash
= INT_GET(leaf2
->entries
[0].hashval
,
2100 XFS_PUT_COOKIE(p
.cook
, mp
, thishash
, 0, nexthash
);
2101 xfs_da_brelse(dp
->i_transp
, bp2
);
2102 xfs_dir_trace_g_duc("leaf: next blk cookie",
2106 XFS_PUT_COOKIE(p
.cook
, mp
, 0, 0, XFS_DA_MAXHASH
);
2110 * Save off the cookie so we can fall back should the
2111 * 'put' into the outgoing buffer fails. To handle a run
2112 * of equal-hashvals, the off_t structure on 64bit
2113 * builds has entno built into the cookie to ID the
2114 * entry. On 32bit builds, we only have space for the
2115 * hashval so we can't ID specific entries within a group
2116 * of same hashval entries. For this, lastoffset is set
2117 * to the first in the run of equal hashvals so we don't
2118 * include any entries unless we can include all entries
2119 * that share the same hashval. Hopefully the buffer
2120 * provided is big enough to handle it (see pv763517).
2122 #if (BITS_PER_LONG == 32)
2123 if ((thishash
= INT_GET(entry
->hashval
, ARCH_CONVERT
))
2125 XFS_PUT_COOKIE(lastoffset
, mp
, bno
, entno
, thishash
);
2126 lastresid
= uio
->uio_resid
;
2127 lasthash
= thishash
;
2129 xfs_dir_trace_g_duc("leaf: DUP COOKIES, skipped",
2133 thishash
= INT_GET(entry
->hashval
, ARCH_CONVERT
);
2134 XFS_PUT_COOKIE(lastoffset
, mp
, bno
, entno
, thishash
);
2135 lastresid
= uio
->uio_resid
;
2136 #endif /* BITS_PER_LONG == 32 */
2139 * Put the current entry into the outgoing buffer. If we fail
2140 * then restore the UIO to the first entry in the current
2141 * run of equal-hashval entries (probably one 1 entry long).
2143 p
.ino
= XFS_GET_DIR_INO8(namest
->inumber
);
2145 p
.ino
+= mp
->m_inoadd
;
2147 p
.name
= (char *)namest
->name
;
2148 p
.namelen
= entry
->namelen
;
2153 uio
->uio_offset
= lastoffset
.o
;
2154 uio
->uio_resid
= lastresid
;
2158 xfs_dir_trace_g_du("leaf: E-O-B", dp
, uio
);
2164 uio
->uio_offset
= p
.cook
.o
;
2168 xfs_dir_trace_g_du("leaf: E-O-F", dp
, uio
);
2174 * Format a dirent64 structure and copy it out the the user's buffer.
2177 xfs_dir_put_dirent64_direct(xfs_dir_put_args_t
*pa
)
2180 int reclen
, namelen
;
2184 namelen
= pa
->namelen
;
2185 reclen
= DIRENTSIZE(namelen
);
2187 if (reclen
> uio
->uio_resid
) {
2191 iovp
= uio
->uio_iov
;
2192 idbp
= (xfs_dirent_t
*)iovp
->iov_base
;
2193 iovp
->iov_base
= (char *)idbp
+ reclen
;
2194 iovp
->iov_len
-= reclen
;
2195 uio
->uio_resid
-= reclen
;
2196 idbp
->d_reclen
= reclen
;
2197 idbp
->d_ino
= pa
->ino
;
2198 idbp
->d_off
= pa
->cook
.o
;
2199 idbp
->d_name
[namelen
] = '\0';
2201 memcpy(idbp
->d_name
, pa
->name
, namelen
);
2206 * Format a dirent64 structure and copy it out the the user's buffer.
2209 xfs_dir_put_dirent64_uio(xfs_dir_put_args_t
*pa
)
2211 int retval
, reclen
, namelen
;
2215 namelen
= pa
->namelen
;
2216 reclen
= DIRENTSIZE(namelen
);
2218 if (reclen
> uio
->uio_resid
) {
2223 idbp
->d_reclen
= reclen
;
2224 idbp
->d_ino
= pa
->ino
;
2225 idbp
->d_off
= pa
->cook
.o
;
2226 idbp
->d_name
[namelen
] = '\0';
2227 memcpy(idbp
->d_name
, pa
->name
, namelen
);
2228 retval
= uio_read((caddr_t
)idbp
, reclen
, uio
);
2229 pa
->done
= (retval
== 0);