1/* 2 * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. 3 * All Rights Reserved. 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU General Public License as 7 * published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it would be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write the Free Software Foundation, 16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 */ 18#include "xfs.h" 19#include "xfs_fs.h" 20#include "xfs_types.h" 21#include "xfs_log.h" 22#include "xfs_inum.h" 23#include "xfs_trans.h" 24#include "xfs_sb.h" 25#include "xfs_dir.h" 26#include "xfs_dir2.h" 27#include "xfs_dmapi.h" 28#include "xfs_mount.h" 29#include "xfs_da_btree.h" 30#include "xfs_bmap_btree.h" 31#include "xfs_alloc_btree.h" 32#include "xfs_ialloc_btree.h" 33#include "xfs_dir_sf.h" 34#include "xfs_dir2_sf.h" 35#include "xfs_attr_sf.h" 36#include "xfs_dinode.h" 37#include "xfs_inode.h" 38#include "xfs_inode_item.h" 39#include "xfs_alloc.h" 40#include "xfs_btree.h" 41#include "xfs_bmap.h" 42#include "xfs_dir_leaf.h" 43#include "xfs_error.h" 44 45/* 46 * xfs_dir_leaf.c 47 * 48 * Routines to implement leaf blocks of directories as Btrees of hashed names. 49 */ 50 51/*======================================================================== 52 * Function prototypes for the kernel. 53 *========================================================================*/ 54 55/* 56 * Routines used for growing the Btree. 57 */ 58STATIC void xfs_dir_leaf_add_work(xfs_dabuf_t *leaf_buffer, xfs_da_args_t *args, 59 int insertion_index, 60 int freemap_index); 61STATIC int xfs_dir_leaf_compact(xfs_trans_t *trans, xfs_dabuf_t *leaf_buffer, 62 int musthave, int justcheck); 63STATIC void xfs_dir_leaf_rebalance(xfs_da_state_t *state, 64 xfs_da_state_blk_t *blk1, 65 xfs_da_state_blk_t *blk2); 66STATIC int xfs_dir_leaf_figure_balance(xfs_da_state_t *state, 67 xfs_da_state_blk_t *leaf_blk_1, 68 xfs_da_state_blk_t *leaf_blk_2, 69 int *number_entries_in_blk1, 70 int *number_namebytes_in_blk1); 71 72STATIC int xfs_dir_leaf_create(struct xfs_da_args *args, 73 xfs_dablk_t which_block, 74 struct xfs_dabuf **bpp); 75 76/* 77 * Utility routines. 78 */ 79STATIC void xfs_dir_leaf_moveents(xfs_dir_leafblock_t *src_leaf, 80 int src_start, 81 xfs_dir_leafblock_t *dst_leaf, 82 int dst_start, int move_count, 83 xfs_mount_t *mp); 84 85 86/*======================================================================== 87 * External routines when dirsize < XFS_IFORK_DSIZE(dp). 88 *========================================================================*/ 89 90 91/* 92 * Validate a given inode number. 93 */ 94int 95xfs_dir_ino_validate(xfs_mount_t *mp, xfs_ino_t ino) 96{ 97 xfs_agblock_t agblkno; 98 xfs_agino_t agino; 99 xfs_agnumber_t agno; 100 int ino_ok; 101 int ioff; 102 103 agno = XFS_INO_TO_AGNO(mp, ino); 104 agblkno = XFS_INO_TO_AGBNO(mp, ino); 105 ioff = XFS_INO_TO_OFFSET(mp, ino); 106 agino = XFS_OFFBNO_TO_AGINO(mp, agblkno, ioff); 107 ino_ok = 108 agno < mp->m_sb.sb_agcount && 109 agblkno < mp->m_sb.sb_agblocks && 110 agblkno != 0 && 111 ioff < (1 << mp->m_sb.sb_inopblog) && 112 XFS_AGINO_TO_INO(mp, agno, agino) == ino; 113 if (unlikely(XFS_TEST_ERROR(!ino_ok, mp, XFS_ERRTAG_DIR_INO_VALIDATE, 114 XFS_RANDOM_DIR_INO_VALIDATE))) { 115 xfs_fs_cmn_err(CE_WARN, mp, "Invalid inode number 0x%Lx", 116 (unsigned long long) ino); 117 XFS_ERROR_REPORT("xfs_dir_ino_validate", XFS_ERRLEVEL_LOW, mp); 118 return XFS_ERROR(EFSCORRUPTED); 119 } 120 return 0; 121} 122 123/* 124 * Create the initial contents of a shortform directory. 125 */ 126int 127xfs_dir_shortform_create(xfs_da_args_t *args, xfs_ino_t parent) 128{ 129 xfs_dir_sf_hdr_t *hdr; 130 xfs_inode_t *dp; 131 132 dp = args->dp; 133 ASSERT(dp != NULL); 134 ASSERT(dp->i_d.di_size == 0); 135 if (dp->i_d.di_format == XFS_DINODE_FMT_EXTENTS) { 136 dp->i_df.if_flags &= ~XFS_IFEXTENTS; /* just in case */ 137 dp->i_d.di_format = XFS_DINODE_FMT_LOCAL; 138 xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE); 139 dp->i_df.if_flags |= XFS_IFINLINE; 140 } 141 ASSERT(dp->i_df.if_flags & XFS_IFINLINE); 142 ASSERT(dp->i_df.if_bytes == 0); 143 xfs_idata_realloc(dp, sizeof(*hdr), XFS_DATA_FORK); 144 hdr = (xfs_dir_sf_hdr_t *)dp->i_df.if_u1.if_data; 145 XFS_DIR_SF_PUT_DIRINO(&parent, &hdr->parent); 146 147 hdr->count = 0; 148 dp->i_d.di_size = sizeof(*hdr); 149 xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA); 150 return 0; 151} 152 153/* 154 * Add a name to the shortform directory structure. 155 * Overflow from the inode has already been checked for. 156 */ 157int 158xfs_dir_shortform_addname(xfs_da_args_t *args) 159{ 160 xfs_dir_shortform_t *sf; 161 xfs_dir_sf_entry_t *sfe; 162 int i, offset, size; 163 xfs_inode_t *dp; 164 165 dp = args->dp; 166 ASSERT(dp->i_df.if_flags & XFS_IFINLINE); 167 /* 168 * Catch the case where the conversion from shortform to leaf 169 * failed part way through. 170 */ 171 if (dp->i_d.di_size < sizeof(xfs_dir_sf_hdr_t)) { 172 ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount)); 173 return XFS_ERROR(EIO); 174 } 175 ASSERT(dp->i_df.if_bytes == dp->i_d.di_size); 176 ASSERT(dp->i_df.if_u1.if_data != NULL); 177 sf = (xfs_dir_shortform_t *)dp->i_df.if_u1.if_data; 178 sfe = &sf->list[0]; 179 for (i = sf->hdr.count-1; i >= 0; i--) { 180 if (sfe->namelen == args->namelen && 181 args->name[0] == sfe->name[0] && 182 memcmp(args->name, sfe->name, args->namelen) == 0) 183 return XFS_ERROR(EEXIST); 184 sfe = XFS_DIR_SF_NEXTENTRY(sfe); 185 } 186 187 offset = (int)((char *)sfe - (char *)sf); 188 size = XFS_DIR_SF_ENTSIZE_BYNAME(args->namelen); 189 xfs_idata_realloc(dp, size, XFS_DATA_FORK); 190 sf = (xfs_dir_shortform_t *)dp->i_df.if_u1.if_data; 191 sfe = (xfs_dir_sf_entry_t *)((char *)sf + offset); 192 193 XFS_DIR_SF_PUT_DIRINO(&args->inumber, &sfe->inumber); 194 sfe->namelen = args->namelen; 195 memcpy(sfe->name, args->name, sfe->namelen); 196 sf->hdr.count++; 197 198 dp->i_d.di_size += size; 199 xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA); 200 201 return 0; 202} 203 204/* 205 * Remove a name from the shortform directory structure. 206 */ 207int 208xfs_dir_shortform_removename(xfs_da_args_t *args) 209{ 210 xfs_dir_shortform_t *sf; 211 xfs_dir_sf_entry_t *sfe; 212 int base, size = 0, i; 213 xfs_inode_t *dp; 214 215 dp = args->dp; 216 ASSERT(dp->i_df.if_flags & XFS_IFINLINE); 217 /* 218 * Catch the case where the conversion from shortform to leaf 219 * failed part way through. 220 */ 221 if (dp->i_d.di_size < sizeof(xfs_dir_sf_hdr_t)) { 222 ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount)); 223 return XFS_ERROR(EIO); 224 } 225 ASSERT(dp->i_df.if_bytes == dp->i_d.di_size); 226 ASSERT(dp->i_df.if_u1.if_data != NULL); 227 base = sizeof(xfs_dir_sf_hdr_t); 228 sf = (xfs_dir_shortform_t *)dp->i_df.if_u1.if_data; 229 sfe = &sf->list[0]; 230 for (i = sf->hdr.count-1; i >= 0; i--) { 231 size = XFS_DIR_SF_ENTSIZE_BYENTRY(sfe); 232 if (sfe->namelen == args->namelen && 233 sfe->name[0] == args->name[0] && 234 memcmp(sfe->name, args->name, args->namelen) == 0) 235 break; 236 base += size; 237 sfe = XFS_DIR_SF_NEXTENTRY(sfe); 238 } 239 if (i < 0) { 240 ASSERT(args->oknoent); 241 return XFS_ERROR(ENOENT); 242 } 243 244 if ((base + size) != dp->i_d.di_size) { 245 memmove(&((char *)sf)[base], &((char *)sf)[base+size], 246 dp->i_d.di_size - (base+size)); 247 } 248 sf->hdr.count--; 249 250 xfs_idata_realloc(dp, -size, XFS_DATA_FORK); 251 dp->i_d.di_size -= size; 252 xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA); 253 254 return 0; 255} 256 257/* 258 * Look up a name in a shortform directory structure. 259 */ 260int 261xfs_dir_shortform_lookup(xfs_da_args_t *args) 262{ 263 xfs_dir_shortform_t *sf; 264 xfs_dir_sf_entry_t *sfe; 265 int i; 266 xfs_inode_t *dp; 267 268 dp = args->dp; 269 ASSERT(dp->i_df.if_flags & XFS_IFINLINE); 270 /* 271 * Catch the case where the conversion from shortform to leaf 272 * failed part way through. 273 */ 274 if (dp->i_d.di_size < sizeof(xfs_dir_sf_hdr_t)) { 275 ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount)); 276 return XFS_ERROR(EIO); 277 } 278 ASSERT(dp->i_df.if_bytes == dp->i_d.di_size); 279 ASSERT(dp->i_df.if_u1.if_data != NULL); 280 sf = (xfs_dir_shortform_t *)dp->i_df.if_u1.if_data; 281 if (args->namelen == 2 && 282 args->name[0] == '.' && args->name[1] == '.') { 283 XFS_DIR_SF_GET_DIRINO(&sf->hdr.parent, &args->inumber); 284 return(XFS_ERROR(EEXIST)); 285 } 286 if (args->namelen == 1 && args->name[0] == '.') { 287 args->inumber = dp->i_ino; 288 return(XFS_ERROR(EEXIST)); 289 } 290 sfe = &sf->list[0]; 291 for (i = sf->hdr.count-1; i >= 0; i--) { 292 if (sfe->namelen == args->namelen && 293 sfe->name[0] == args->name[0] && 294 memcmp(args->name, sfe->name, args->namelen) == 0) { 295 XFS_DIR_SF_GET_DIRINO(&sfe->inumber, &args->inumber); 296 return(XFS_ERROR(EEXIST)); 297 } 298 sfe = XFS_DIR_SF_NEXTENTRY(sfe); 299 } 300 ASSERT(args->oknoent); 301 return(XFS_ERROR(ENOENT)); 302} 303 304/* 305 * Convert from using the shortform to the leaf. 306 */ 307int 308xfs_dir_shortform_to_leaf(xfs_da_args_t *iargs) 309{ 310 xfs_inode_t *dp; 311 xfs_dir_shortform_t *sf; 312 xfs_dir_sf_entry_t *sfe; 313 xfs_da_args_t args; 314 xfs_ino_t inumber; 315 char *tmpbuffer; 316 int retval, i, size; 317 xfs_dablk_t blkno; 318 xfs_dabuf_t *bp; 319 320 dp = iargs->dp; 321 /* 322 * Catch the case where the conversion from shortform to leaf 323 * failed part way through. 324 */ 325 if (dp->i_d.di_size < sizeof(xfs_dir_sf_hdr_t)) { 326 ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount)); 327 return XFS_ERROR(EIO); 328 } 329 ASSERT(dp->i_df.if_bytes == dp->i_d.di_size); 330 ASSERT(dp->i_df.if_u1.if_data != NULL); 331 size = dp->i_df.if_bytes; 332 tmpbuffer = kmem_alloc(size, KM_SLEEP); 333 ASSERT(tmpbuffer != NULL); 334 335 memcpy(tmpbuffer, dp->i_df.if_u1.if_data, size); 336 337 sf = (xfs_dir_shortform_t *)tmpbuffer; 338 XFS_DIR_SF_GET_DIRINO(&sf->hdr.parent, &inumber); 339 340 xfs_idata_realloc(dp, -size, XFS_DATA_FORK); 341 dp->i_d.di_size = 0; 342 xfs_trans_log_inode(iargs->trans, dp, XFS_ILOG_CORE); 343 retval = xfs_da_grow_inode(iargs, &blkno); 344 if (retval) 345 goto out; 346 347 ASSERT(blkno == 0); 348 retval = xfs_dir_leaf_create(iargs, blkno, &bp); 349 if (retval) 350 goto out; 351 xfs_da_buf_done(bp); 352 353 args.name = "."; 354 args.namelen = 1; 355 args.hashval = xfs_dir_hash_dot; 356 args.inumber = dp->i_ino; 357 args.dp = dp; 358 args.firstblock = iargs->firstblock; 359 args.flist = iargs->flist; 360 args.total = iargs->total; 361 args.whichfork = XFS_DATA_FORK; 362 args.trans = iargs->trans; 363 args.justcheck = 0; 364 args.addname = args.oknoent = 1; 365 retval = xfs_dir_leaf_addname(&args); 366 if (retval) 367 goto out; 368 369 args.name = ".."; 370 args.namelen = 2; 371 args.hashval = xfs_dir_hash_dotdot; 372 args.inumber = inumber; 373 retval = xfs_dir_leaf_addname(&args); 374 if (retval) 375 goto out; 376 377 sfe = &sf->list[0]; 378 for (i = 0; i < sf->hdr.count; i++) { 379 args.name = (char *)(sfe->name); 380 args.namelen = sfe->namelen; 381 args.hashval = xfs_da_hashname((char *)(sfe->name), 382 sfe->namelen); 383 XFS_DIR_SF_GET_DIRINO(&sfe->inumber, &args.inumber); 384 retval = xfs_dir_leaf_addname(&args); 385 if (retval) 386 goto out; 387 sfe = XFS_DIR_SF_NEXTENTRY(sfe); 388 } 389 retval = 0; 390 391out: 392 kmem_free(tmpbuffer, size); 393 return retval; 394} 395 396STATIC int 397xfs_dir_shortform_compare(const void *a, const void *b) 398{ 399 const xfs_dir_sf_sort_t *sa, *sb; 400 401 sa = (const xfs_dir_sf_sort_t *)a; 402 sb = (const xfs_dir_sf_sort_t *)b; 403 if (sa->hash < sb->hash) 404 return -1; 405 else if (sa->hash > sb->hash) 406 return 1; 407 else 408 return sa->entno - sb->entno; 409} 410 411/* 412 * Copy out directory entries for getdents(), for shortform directories. 413 */ 414/*ARGSUSED*/ 415int 416xfs_dir_shortform_getdents(xfs_inode_t *dp, uio_t *uio, int *eofp, 417 xfs_dirent_t *dbp, xfs_dir_put_t put) 418{ 419 xfs_dir_shortform_t *sf; 420 xfs_dir_sf_entry_t *sfe; 421 int retval, i, sbsize, nsbuf, lastresid=0, want_entno; 422 xfs_mount_t *mp; 423 xfs_dahash_t cookhash, hash; 424 xfs_dir_put_args_t p; 425 xfs_dir_sf_sort_t *sbuf, *sbp; 426 427 mp = dp->i_mount; 428 sf = (xfs_dir_shortform_t *)dp->i_df.if_u1.if_data; 429 cookhash = XFS_DA_COOKIE_HASH(mp, uio->uio_offset); 430 want_entno = XFS_DA_COOKIE_ENTRY(mp, uio->uio_offset); 431 nsbuf = sf->hdr.count + 2; 432 sbsize = (nsbuf + 1) * sizeof(*sbuf); 433 sbp = sbuf = kmem_alloc(sbsize, KM_SLEEP); 434 435 xfs_dir_trace_g_du("sf: start", dp, uio); 436 437 /* 438 * Collect all the entries into the buffer. 439 * Entry 0 is . 440 */ 441 sbp->entno = 0; 442 sbp->seqno = 0; 443 sbp->hash = xfs_dir_hash_dot; 444 sbp->ino = dp->i_ino; 445 sbp->name = "."; 446 sbp->namelen = 1; 447 sbp++; 448 449 /* 450 * Entry 1 is .. 451 */ 452 sbp->entno = 1; 453 sbp->seqno = 0; 454 sbp->hash = xfs_dir_hash_dotdot; 455 sbp->ino = XFS_GET_DIR_INO8(sf->hdr.parent); 456 sbp->name = ".."; 457 sbp->namelen = 2; 458 sbp++; 459 460 /* 461 * Scan the directory data for the rest of the entries. 462 */ 463 for (i = 0, sfe = &sf->list[0]; i < sf->hdr.count; i++) { 464 465 if (unlikely( 466 ((char *)sfe < (char *)sf) || 467 ((char *)sfe >= ((char *)sf + dp->i_df.if_bytes)))) { 468 xfs_dir_trace_g_du("sf: corrupted", dp, uio); 469 XFS_CORRUPTION_ERROR("xfs_dir_shortform_getdents", 470 XFS_ERRLEVEL_LOW, mp, sfe); 471 kmem_free(sbuf, sbsize); 472 return XFS_ERROR(EFSCORRUPTED); 473 } 474 475 sbp->entno = i + 2; 476 sbp->seqno = 0; 477 sbp->hash = xfs_da_hashname((char *)sfe->name, sfe->namelen); 478 sbp->ino = XFS_GET_DIR_INO8(sfe->inumber); 479 sbp->name = (char *)sfe->name; 480 sbp->namelen = sfe->namelen; 481 sfe = XFS_DIR_SF_NEXTENTRY(sfe); 482 sbp++; 483 } 484 485 /* 486 * Sort the entries on hash then entno. 487 */ 488 xfs_sort(sbuf, nsbuf, sizeof(*sbuf), xfs_dir_shortform_compare); 489 /* 490 * Stuff in last entry. 491 */ 492 sbp->entno = nsbuf; 493 sbp->hash = XFS_DA_MAXHASH; 494 sbp->seqno = 0; 495 /* 496 * Figure out the sequence numbers in case there's a hash duplicate. 497 */ 498 for (hash = sbuf->hash, sbp = sbuf + 1; 499 sbp < &sbuf[nsbuf + 1]; sbp++) { 500 if (sbp->hash == hash) 501 sbp->seqno = sbp[-1].seqno + 1; 502 else 503 hash = sbp->hash; 504 } 505 506 /* 507 * Set up put routine. 508 */ 509 p.dbp = dbp; 510 p.put = put; 511 p.uio = uio; 512 513 /* 514 * Find our place. 515 */ 516 for (sbp = sbuf; sbp < &sbuf[nsbuf + 1]; sbp++) { 517 if (sbp->hash > cookhash || 518 (sbp->hash == cookhash && sbp->seqno >= want_entno)) 519 break; 520 } 521 522 /* 523 * Did we fail to find anything? We stop at the last entry, 524 * the one we put maxhash into. 525 */ 526 if (sbp == &sbuf[nsbuf]) { 527 kmem_free(sbuf, sbsize); 528 xfs_dir_trace_g_du("sf: hash beyond end", dp, uio); 529 uio->uio_offset = XFS_DA_MAKE_COOKIE(mp, 0, 0, XFS_DA_MAXHASH); 530 *eofp = 1; 531 return 0; 532 } 533 534 /* 535 * Loop putting entries into the user buffer. 536 */ 537 while (sbp < &sbuf[nsbuf]) { 538 /* 539 * Save the first resid in a run of equal-hashval entries 540 * so that we can back them out if they don't all fit. 541 */ 542 if (sbp->seqno == 0 || sbp == sbuf) 543 lastresid = uio->uio_resid; 544 XFS_PUT_COOKIE(p.cook, mp, 0, sbp[1].seqno, sbp[1].hash); 545 p.ino = sbp->ino; 546#if XFS_BIG_INUMS 547 p.ino += mp->m_inoadd; 548#endif 549 p.name = sbp->name; 550 p.namelen = sbp->namelen; 551 retval = p.put(&p); 552 if (!p.done) { 553 uio->uio_offset = 554 XFS_DA_MAKE_COOKIE(mp, 0, 0, sbp->hash); 555 kmem_free(sbuf, sbsize); 556 uio->uio_resid = lastresid; 557 xfs_dir_trace_g_du("sf: E-O-B", dp, uio); 558 return retval; 559 } 560 sbp++; 561 } 562 kmem_free(sbuf, sbsize); 563 uio->uio_offset = p.cook.o; 564 *eofp = 1; 565 xfs_dir_trace_g_du("sf: E-O-F", dp, uio); 566 return 0; 567} 568 569/* 570 * Look up a name in a shortform directory structure, replace the inode number. 571 */ 572int 573xfs_dir_shortform_replace(xfs_da_args_t *args) 574{ 575 xfs_dir_shortform_t *sf; 576 xfs_dir_sf_entry_t *sfe; 577 xfs_inode_t *dp; 578 int i; 579 580 dp = args->dp; 581 ASSERT(dp->i_df.if_flags & XFS_IFINLINE); 582 /* 583 * Catch the case where the conversion from shortform to leaf 584 * failed part way through. 585 */ 586 if (dp->i_d.di_size < sizeof(xfs_dir_sf_hdr_t)) { 587 ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount)); 588 return XFS_ERROR(EIO); 589 } 590 ASSERT(dp->i_df.if_bytes == dp->i_d.di_size); 591 ASSERT(dp->i_df.if_u1.if_data != NULL); 592 sf = (xfs_dir_shortform_t *)dp->i_df.if_u1.if_data; 593 if (args->namelen == 2 && 594 args->name[0] == '.' && args->name[1] == '.') { 595 /* XXX - replace assert? */ 596 XFS_DIR_SF_PUT_DIRINO(&args->inumber, &sf->hdr.parent); 597 xfs_trans_log_inode(args->trans, dp, XFS_ILOG_DDATA); 598 return 0; 599 } 600 ASSERT(args->namelen != 1 || args->name[0] != '.'); 601 sfe = &sf->list[0]; 602 for (i = sf->hdr.count-1; i >= 0; i--) { 603 if (sfe->namelen == args->namelen && 604 sfe->name[0] == args->name[0] && 605 memcmp(args->name, sfe->name, args->namelen) == 0) { 606 ASSERT(memcmp((char *)&args->inumber, 607 (char *)&sfe->inumber, sizeof(xfs_ino_t))); 608 XFS_DIR_SF_PUT_DIRINO(&args->inumber, &sfe->inumber); 609 xfs_trans_log_inode(args->trans, dp, XFS_ILOG_DDATA); 610 return 0; 611 } 612 sfe = XFS_DIR_SF_NEXTENTRY(sfe); 613 } 614 ASSERT(args->oknoent); 615 return XFS_ERROR(ENOENT); 616} 617 618/* 619 * Convert a leaf directory to shortform structure 620 */ 621int 622xfs_dir_leaf_to_shortform(xfs_da_args_t *iargs) 623{ 624 xfs_dir_leafblock_t *leaf; 625 xfs_dir_leaf_hdr_t *hdr; 626 xfs_dir_leaf_entry_t *entry; 627 xfs_dir_leaf_name_t *namest; 628 xfs_da_args_t args; 629 xfs_inode_t *dp; 630 xfs_ino_t parent = 0; 631 char *tmpbuffer; 632 int retval, i; 633 xfs_dabuf_t *bp; 634 635 dp = iargs->dp; 636 tmpbuffer = kmem_alloc(XFS_LBSIZE(dp->i_mount), KM_SLEEP); 637 ASSERT(tmpbuffer != NULL); 638 639 retval = xfs_da_read_buf(iargs->trans, iargs->dp, 0, -1, &bp, 640 XFS_DATA_FORK); 641 if (retval) 642 goto out; 643 ASSERT(bp != NULL); 644 memcpy(tmpbuffer, bp->data, XFS_LBSIZE(dp->i_mount)); 645 leaf = (xfs_dir_leafblock_t *)tmpbuffer; 646 ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); 647 memset(bp->data, 0, XFS_LBSIZE(dp->i_mount)); 648 649 /* 650 * Find and special case the parent inode number 651 */ 652 hdr = &leaf->hdr; 653 entry = &leaf->entries[0]; 654 for (i = INT_GET(hdr->count, ARCH_CONVERT)-1; i >= 0; entry++, i--) { 655 namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT)); 656 if ((entry->namelen == 2) && 657 (namest->name[0] == '.') && 658 (namest->name[1] == '.')) { 659 XFS_DIR_SF_GET_DIRINO(&namest->inumber, &parent); 660 entry->nameidx = 0; 661 } else if ((entry->namelen == 1) && (namest->name[0] == '.')) { 662 entry->nameidx = 0; 663 } 664 } 665 retval = xfs_da_shrink_inode(iargs, 0, bp); 666 if (retval) 667 goto out; 668 retval = xfs_dir_shortform_create(iargs, parent); 669 if (retval) 670 goto out; 671 672 /* 673 * Copy the rest of the filenames 674 */ 675 entry = &leaf->entries[0]; 676 args.dp = dp; 677 args.firstblock = iargs->firstblock; 678 args.flist = iargs->flist; 679 args.total = iargs->total; 680 args.whichfork = XFS_DATA_FORK; 681 args.trans = iargs->trans; 682 args.justcheck = 0; 683 args.addname = args.oknoent = 1; 684 for (i = 0; i < INT_GET(hdr->count, ARCH_CONVERT); entry++, i++) { 685 if (!entry->nameidx) 686 continue; 687 namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT)); 688 args.name = (char *)(namest->name); 689 args.namelen = entry->namelen; 690 args.hashval = INT_GET(entry->hashval, ARCH_CONVERT); 691 XFS_DIR_SF_GET_DIRINO(&namest->inumber, &args.inumber); 692 xfs_dir_shortform_addname(&args); 693 } 694 695out: 696 kmem_free(tmpbuffer, XFS_LBSIZE(dp->i_mount)); 697 return retval; 698} 699 700/* 701 * Convert from using a single leaf to a root node and a leaf. 702 */ 703int 704xfs_dir_leaf_to_node(xfs_da_args_t *args) 705{ 706 xfs_dir_leafblock_t *leaf; 707 xfs_da_intnode_t *node; 708 xfs_inode_t *dp; 709 xfs_dabuf_t *bp1, *bp2; 710 xfs_dablk_t blkno; 711 int retval; 712 713 dp = args->dp; 714 retval = xfs_da_grow_inode(args, &blkno); 715 ASSERT(blkno == 1); 716 if (retval) 717 return retval; 718 retval = xfs_da_read_buf(args->trans, args->dp, 0, -1, &bp1, 719 XFS_DATA_FORK); 720 if (retval) 721 return retval; 722 ASSERT(bp1 != NULL); 723 retval = xfs_da_get_buf(args->trans, args->dp, 1, -1, &bp2, 724 XFS_DATA_FORK); 725 if (retval) { 726 xfs_da_buf_done(bp1); 727 return retval; 728 } 729 ASSERT(bp2 != NULL); 730 memcpy(bp2->data, bp1->data, XFS_LBSIZE(dp->i_mount)); 731 xfs_da_buf_done(bp1); 732 xfs_da_log_buf(args->trans, bp2, 0, XFS_LBSIZE(dp->i_mount) - 1); 733 734 /* 735 * Set up the new root node. 736 */ 737 retval = xfs_da_node_create(args, 0, 1, &bp1, XFS_DATA_FORK); 738 if (retval) { 739 xfs_da_buf_done(bp2); 740 return retval; 741 } 742 node = bp1->data; 743 leaf = bp2->data; 744 ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); 745 node->btree[0].hashval = cpu_to_be32( 746 INT_GET(leaf->entries[ 747 INT_GET(leaf->hdr.count, ARCH_CONVERT)-1].hashval, ARCH_CONVERT)); 748 xfs_da_buf_done(bp2); 749 node->btree[0].before = cpu_to_be32(blkno); 750 node->hdr.count = cpu_to_be16(1); 751 xfs_da_log_buf(args->trans, bp1, 752 XFS_DA_LOGRANGE(node, &node->btree[0], sizeof(node->btree[0]))); 753 xfs_da_buf_done(bp1); 754 755 return retval; 756} 757 758 759/*======================================================================== 760 * Routines used for growing the Btree. 761 *========================================================================*/ 762 763/* 764 * Create the initial contents of a leaf directory 765 * or a leaf in a node directory. 766 */ 767STATIC int 768xfs_dir_leaf_create(xfs_da_args_t *args, xfs_dablk_t blkno, xfs_dabuf_t **bpp) 769{ 770 xfs_dir_leafblock_t *leaf; 771 xfs_dir_leaf_hdr_t *hdr; 772 xfs_inode_t *dp; 773 xfs_dabuf_t *bp; 774 int retval; 775 776 dp = args->dp; 777 ASSERT(dp != NULL); 778 retval = xfs_da_get_buf(args->trans, dp, blkno, -1, &bp, XFS_DATA_FORK); 779 if (retval) 780 return retval; 781 ASSERT(bp != NULL); 782 leaf = bp->data; 783 memset((char *)leaf, 0, XFS_LBSIZE(dp->i_mount)); 784 hdr = &leaf->hdr; 785 hdr->info.magic = cpu_to_be16(XFS_DIR_LEAF_MAGIC); 786 INT_SET(hdr->firstused, ARCH_CONVERT, XFS_LBSIZE(dp->i_mount)); 787 if (!hdr->firstused) 788 INT_SET(hdr->firstused, ARCH_CONVERT, XFS_LBSIZE(dp->i_mount) - 1); 789 INT_SET(hdr->freemap[0].base, ARCH_CONVERT, sizeof(xfs_dir_leaf_hdr_t)); 790 INT_SET(hdr->freemap[0].size, ARCH_CONVERT, INT_GET(hdr->firstused, ARCH_CONVERT) - INT_GET(hdr->freemap[0].base, ARCH_CONVERT)); 791 792 xfs_da_log_buf(args->trans, bp, 0, XFS_LBSIZE(dp->i_mount) - 1); 793 794 *bpp = bp; 795 return 0; 796} 797 798/* 799 * Split the leaf node, rebalance, then add the new entry. 800 */ 801int 802xfs_dir_leaf_split(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk, 803 xfs_da_state_blk_t *newblk) 804{ 805 xfs_dablk_t blkno; 806 xfs_da_args_t *args; 807 int error; 808 809 /* 810 * Allocate space for a new leaf node. 811 */ 812 args = state->args; 813 ASSERT(args != NULL); 814 ASSERT(oldblk->magic == XFS_DIR_LEAF_MAGIC); 815 error = xfs_da_grow_inode(args, &blkno); 816 if (error) 817 return error; 818 error = xfs_dir_leaf_create(args, blkno, &newblk->bp); 819 if (error) 820 return error; 821 newblk->blkno = blkno; 822 newblk->magic = XFS_DIR_LEAF_MAGIC; 823 824 /* 825 * Rebalance the entries across the two leaves. 826 */ 827 xfs_dir_leaf_rebalance(state, oldblk, newblk); 828 error = xfs_da_blk_link(state, oldblk, newblk); 829 if (error) 830 return error; 831 832 /* 833 * Insert the new entry in the correct block. 834 */ 835 if (state->inleaf) { 836 error = xfs_dir_leaf_add(oldblk->bp, args, oldblk->index); 837 } else { 838 error = xfs_dir_leaf_add(newblk->bp, args, newblk->index); 839 } 840 841 /* 842 * Update last hashval in each block since we added the name. 843 */ 844 oldblk->hashval = xfs_dir_leaf_lasthash(oldblk->bp, NULL); 845 newblk->hashval = xfs_dir_leaf_lasthash(newblk->bp, NULL); 846 return error; 847} 848 849/* 850 * Add a name to the leaf directory structure. 851 * 852 * Must take into account fragmented leaves and leaves where spacemap has 853 * lost some freespace information (ie: holes). 854 */ 855int 856xfs_dir_leaf_add(xfs_dabuf_t *bp, xfs_da_args_t *args, int index) 857{ 858 xfs_dir_leafblock_t *leaf; 859 xfs_dir_leaf_hdr_t *hdr; 860 xfs_dir_leaf_map_t *map; 861 int tablesize, entsize, sum, i, tmp, error; 862 863 leaf = bp->data; 864 ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); 865 ASSERT((index >= 0) && (index <= INT_GET(leaf->hdr.count, ARCH_CONVERT))); 866 hdr = &leaf->hdr; 867 entsize = XFS_DIR_LEAF_ENTSIZE_BYNAME(args->namelen); 868 869 /* 870 * Search through freemap for first-fit on new name length. 871 * (may need to figure in size of entry struct too) 872 */ 873 tablesize = (INT_GET(hdr->count, ARCH_CONVERT) + 1) * (uint)sizeof(xfs_dir_leaf_entry_t) 874 + (uint)sizeof(xfs_dir_leaf_hdr_t); 875 map = &hdr->freemap[XFS_DIR_LEAF_MAPSIZE-1]; 876 for (sum = 0, i = XFS_DIR_LEAF_MAPSIZE-1; i >= 0; map--, i--) { 877 if (tablesize > INT_GET(hdr->firstused, ARCH_CONVERT)) { 878 sum += INT_GET(map->size, ARCH_CONVERT); 879 continue; 880 } 881 if (!map->size) 882 continue; /* no space in this map */ 883 tmp = entsize; 884 if (INT_GET(map->base, ARCH_CONVERT) < INT_GET(hdr->firstused, ARCH_CONVERT)) 885 tmp += (uint)sizeof(xfs_dir_leaf_entry_t); 886 if (INT_GET(map->size, ARCH_CONVERT) >= tmp) { 887 if (!args->justcheck) 888 xfs_dir_leaf_add_work(bp, args, index, i); 889 return 0; 890 } 891 sum += INT_GET(map->size, ARCH_CONVERT); 892 } 893 894 /* 895 * If there are no holes in the address space of the block, 896 * and we don't have enough freespace, then compaction will do us 897 * no good and we should just give up. 898 */ 899 if (!hdr->holes && (sum < entsize)) 900 return XFS_ERROR(ENOSPC); 901 902 /* 903 * Compact the entries to coalesce free space. 904 * Pass the justcheck flag so the checking pass can return 905 * an error, without changing anything, if it won't fit. 906 */ 907 error = xfs_dir_leaf_compact(args->trans, bp, 908 args->total == 0 ? 909 entsize + 910 (uint)sizeof(xfs_dir_leaf_entry_t) : 0, 911 args->justcheck); 912 if (error) 913 return error; 914 /* 915 * After compaction, the block is guaranteed to have only one 916 * free region, in freemap[0]. If it is not big enough, give up. 917 */ 918 if (INT_GET(hdr->freemap[0].size, ARCH_CONVERT) < 919 (entsize + (uint)sizeof(xfs_dir_leaf_entry_t))) 920 return XFS_ERROR(ENOSPC); 921 922 if (!args->justcheck) 923 xfs_dir_leaf_add_work(bp, args, index, 0); 924 return 0; 925} 926 927/* 928 * Add a name to a leaf directory structure. 929 */ 930STATIC void 931xfs_dir_leaf_add_work(xfs_dabuf_t *bp, xfs_da_args_t *args, int index, 932 int mapindex) 933{ 934 xfs_dir_leafblock_t *leaf; 935 xfs_dir_leaf_hdr_t *hdr; 936 xfs_dir_leaf_entry_t *entry; 937 xfs_dir_leaf_name_t *namest; 938 xfs_dir_leaf_map_t *map; 939 /* REFERENCED */ 940 xfs_mount_t *mp; 941 int tmp, i; 942 943 leaf = bp->data; 944 ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); 945 hdr = &leaf->hdr; 946 ASSERT((mapindex >= 0) && (mapindex < XFS_DIR_LEAF_MAPSIZE)); 947 ASSERT((index >= 0) && (index <= INT_GET(hdr->count, ARCH_CONVERT))); 948 949 /* 950 * Force open some space in the entry array and fill it in. 951 */ 952 entry = &leaf->entries[index]; 953 if (index < INT_GET(hdr->count, ARCH_CONVERT)) { 954 tmp = INT_GET(hdr->count, ARCH_CONVERT) - index; 955 tmp *= (uint)sizeof(xfs_dir_leaf_entry_t); 956 memmove(entry + 1, entry, tmp); 957 xfs_da_log_buf(args->trans, bp, 958 XFS_DA_LOGRANGE(leaf, entry, tmp + (uint)sizeof(*entry))); 959 } 960 INT_MOD(hdr->count, ARCH_CONVERT, +1); 961 962 /* 963 * Allocate space for the new string (at the end of the run). 964 */ 965 map = &hdr->freemap[mapindex]; 966 mp = args->trans->t_mountp; 967 ASSERT(INT_GET(map->base, ARCH_CONVERT) < XFS_LBSIZE(mp)); 968 ASSERT(INT_GET(map->size, ARCH_CONVERT) >= XFS_DIR_LEAF_ENTSIZE_BYNAME(args->namelen)); 969 ASSERT(INT_GET(map->size, ARCH_CONVERT) < XFS_LBSIZE(mp)); 970 INT_MOD(map->size, ARCH_CONVERT, -(XFS_DIR_LEAF_ENTSIZE_BYNAME(args->namelen))); 971 INT_SET(entry->nameidx, ARCH_CONVERT, INT_GET(map->base, ARCH_CONVERT) + INT_GET(map->size, ARCH_CONVERT)); 972 INT_SET(entry->hashval, ARCH_CONVERT, args->hashval); 973 entry->namelen = args->namelen; 974 xfs_da_log_buf(args->trans, bp, 975 XFS_DA_LOGRANGE(leaf, entry, sizeof(*entry))); 976 977 /* 978 * Copy the string and inode number into the new space. 979 */ 980 namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT)); 981 XFS_DIR_SF_PUT_DIRINO(&args->inumber, &namest->inumber); 982 memcpy(namest->name, args->name, args->namelen); 983 xfs_da_log_buf(args->trans, bp, 984 XFS_DA_LOGRANGE(leaf, namest, XFS_DIR_LEAF_ENTSIZE_BYENTRY(entry))); 985 986 /* 987 * Update the control info for this leaf node 988 */ 989 if (INT_GET(entry->nameidx, ARCH_CONVERT) < INT_GET(hdr->firstused, ARCH_CONVERT)) 990 INT_COPY(hdr->firstused, entry->nameidx, ARCH_CONVERT); 991 ASSERT(INT_GET(hdr->firstused, ARCH_CONVERT) >= ((INT_GET(hdr->count, ARCH_CONVERT)*sizeof(*entry))+sizeof(*hdr))); 992 tmp = (INT_GET(hdr->count, ARCH_CONVERT)-1) * (uint)sizeof(xfs_dir_leaf_entry_t) 993 + (uint)sizeof(xfs_dir_leaf_hdr_t); 994 map = &hdr->freemap[0]; 995 for (i = 0; i < XFS_DIR_LEAF_MAPSIZE; map++, i++) { 996 if (INT_GET(map->base, ARCH_CONVERT) == tmp) { 997 INT_MOD(map->base, ARCH_CONVERT, (uint)sizeof(xfs_dir_leaf_entry_t)); 998 INT_MOD(map->size, ARCH_CONVERT, -((uint)sizeof(xfs_dir_leaf_entry_t))); 999 } 1000 } 1001 INT_MOD(hdr->namebytes, ARCH_CONVERT, args->namelen); 1002 xfs_da_log_buf(args->trans, bp, 1003 XFS_DA_LOGRANGE(leaf, hdr, sizeof(*hdr))); 1004} 1005 1006/* 1007 * Garbage collect a leaf directory block by copying it to a new buffer. 1008 */ 1009STATIC int 1010xfs_dir_leaf_compact(xfs_trans_t *trans, xfs_dabuf_t *bp, int musthave, 1011 int justcheck) 1012{ 1013 xfs_dir_leafblock_t *leaf_s, *leaf_d; 1014 xfs_dir_leaf_hdr_t *hdr_s, *hdr_d; 1015 xfs_mount_t *mp; 1016 char *tmpbuffer; 1017 char *tmpbuffer2=NULL; 1018 int rval; 1019 int lbsize; 1020 1021 mp = trans->t_mountp; 1022 lbsize = XFS_LBSIZE(mp); 1023 tmpbuffer = kmem_alloc(lbsize, KM_SLEEP); 1024 ASSERT(tmpbuffer != NULL); 1025 memcpy(tmpbuffer, bp->data, lbsize); 1026 1027 /* 1028 * Make a second copy in case xfs_dir_leaf_moveents() 1029 * below destroys the original. 1030 */ 1031 if (musthave || justcheck) { 1032 tmpbuffer2 = kmem_alloc(lbsize, KM_SLEEP); 1033 memcpy(tmpbuffer2, bp->data, lbsize); 1034 } 1035 memset(bp->data, 0, lbsize); 1036 1037 /* 1038 * Copy basic information 1039 */ 1040 leaf_s = (xfs_dir_leafblock_t *)tmpbuffer; 1041 leaf_d = bp->data; 1042 hdr_s = &leaf_s->hdr; 1043 hdr_d = &leaf_d->hdr; 1044 hdr_d->info = hdr_s->info; /* struct copy */ 1045 INT_SET(hdr_d->firstused, ARCH_CONVERT, lbsize); 1046 if (!hdr_d->firstused) 1047 INT_SET(hdr_d->firstused, ARCH_CONVERT, lbsize - 1); 1048 hdr_d->namebytes = 0; 1049 hdr_d->count = 0; 1050 hdr_d->holes = 0; 1051 INT_SET(hdr_d->freemap[0].base, ARCH_CONVERT, sizeof(xfs_dir_leaf_hdr_t)); 1052 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)); 1053 1054 /* 1055 * Copy all entry's in the same (sorted) order, 1056 * but allocate filenames packed and in sequence. 1057 * This changes the source (leaf_s) as well. 1058 */ 1059 xfs_dir_leaf_moveents(leaf_s, 0, leaf_d, 0, (int)INT_GET(hdr_s->count, ARCH_CONVERT), mp); 1060 1061 if (musthave && INT_GET(hdr_d->freemap[0].size, ARCH_CONVERT) < musthave) 1062 rval = XFS_ERROR(ENOSPC); 1063 else 1064 rval = 0; 1065 1066 if (justcheck || rval == ENOSPC) { 1067 ASSERT(tmpbuffer2); 1068 memcpy(bp->data, tmpbuffer2, lbsize); 1069 } else { 1070 xfs_da_log_buf(trans, bp, 0, lbsize - 1); 1071 } 1072 1073 kmem_free(tmpbuffer, lbsize); 1074 if (musthave || justcheck) 1075 kmem_free(tmpbuffer2, lbsize); 1076 return rval; 1077} 1078 1079/* 1080 * Redistribute the directory entries between two leaf nodes, 1081 * taking into account the size of the new entry. 1082 * 1083 * NOTE: if new block is empty, then it will get the upper half of old block. 1084 */ 1085STATIC void 1086xfs_dir_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, 1087 xfs_da_state_blk_t *blk2) 1088{ 1089 xfs_da_state_blk_t *tmp_blk; 1090 xfs_dir_leafblock_t *leaf1, *leaf2; 1091 xfs_dir_leaf_hdr_t *hdr1, *hdr2; 1092 int count, totallen, max, space, swap; 1093 1094 /* 1095 * Set up environment. 1096 */ 1097 ASSERT(blk1->magic == XFS_DIR_LEAF_MAGIC); 1098 ASSERT(blk2->magic == XFS_DIR_LEAF_MAGIC); 1099 leaf1 = blk1->bp->data; 1100 leaf2 = blk2->bp->data; 1101 ASSERT(be16_to_cpu(leaf1->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); 1102 ASSERT(be16_to_cpu(leaf2->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); 1103 1104 /* 1105 * Check ordering of blocks, reverse if it makes things simpler. 1106 */ 1107 swap = 0; 1108 if (xfs_dir_leaf_order(blk1->bp, blk2->bp)) { 1109 tmp_blk = blk1; 1110 blk1 = blk2; 1111 blk2 = tmp_blk; 1112 leaf1 = blk1->bp->data; 1113 leaf2 = blk2->bp->data; 1114 swap = 1; 1115 } 1116 hdr1 = &leaf1->hdr; 1117 hdr2 = &leaf2->hdr; 1118 1119 /* 1120 * Examine entries until we reduce the absolute difference in 1121 * byte usage between the two blocks to a minimum. Then get 1122 * the direction to copy and the number of elements to move. 1123 */ 1124 state->inleaf = xfs_dir_leaf_figure_balance(state, blk1, blk2, 1125 &count, &totallen); 1126 if (swap) 1127 state->inleaf = !state->inleaf; 1128 1129 /* 1130 * Move any entries required from leaf to leaf: 1131 */ 1132 if (count < INT_GET(hdr1->count, ARCH_CONVERT)) { 1133 /* 1134 * Figure the total bytes to be added to the destination leaf. 1135 */ 1136 count = INT_GET(hdr1->count, ARCH_CONVERT) - count; /* number entries being moved */ 1137 space = INT_GET(hdr1->namebytes, ARCH_CONVERT) - totallen; 1138 space += count * ((uint)sizeof(xfs_dir_leaf_name_t)-1); 1139 space += count * (uint)sizeof(xfs_dir_leaf_entry_t); 1140 1141 /* 1142 * leaf2 is the destination, compact it if it looks tight. 1143 */ 1144 max = INT_GET(hdr2->firstused, ARCH_CONVERT) - (uint)sizeof(xfs_dir_leaf_hdr_t); 1145 max -= INT_GET(hdr2->count, ARCH_CONVERT) * (uint)sizeof(xfs_dir_leaf_entry_t); 1146 if (space > max) { 1147 xfs_dir_leaf_compact(state->args->trans, blk2->bp, 1148 0, 0); 1149 } 1150 1151 /* 1152 * Move high entries from leaf1 to low end of leaf2. 1153 */ 1154 xfs_dir_leaf_moveents(leaf1, INT_GET(hdr1->count, ARCH_CONVERT) - count, 1155 leaf2, 0, count, state->mp); 1156 1157 xfs_da_log_buf(state->args->trans, blk1->bp, 0, 1158 state->blocksize-1); 1159 xfs_da_log_buf(state->args->trans, blk2->bp, 0, 1160 state->blocksize-1); 1161 1162 } else if (count > INT_GET(hdr1->count, ARCH_CONVERT)) { 1163 /* 1164 * Figure the total bytes to be added to the destination leaf. 1165 */ 1166 count -= INT_GET(hdr1->count, ARCH_CONVERT); /* number entries being moved */ 1167 space = totallen - INT_GET(hdr1->namebytes, ARCH_CONVERT); 1168 space += count * ((uint)sizeof(xfs_dir_leaf_name_t)-1); 1169 space += count * (uint)sizeof(xfs_dir_leaf_entry_t); 1170 1171 /* 1172 * leaf1 is the destination, compact it if it looks tight. 1173 */ 1174 max = INT_GET(hdr1->firstused, ARCH_CONVERT) - (uint)sizeof(xfs_dir_leaf_hdr_t); 1175 max -= INT_GET(hdr1->count, ARCH_CONVERT) * (uint)sizeof(xfs_dir_leaf_entry_t); 1176 if (space > max) { 1177 xfs_dir_leaf_compact(state->args->trans, blk1->bp, 1178 0, 0); 1179 } 1180 1181 /* 1182 * Move low entries from leaf2 to high end of leaf1. 1183 */ 1184 xfs_dir_leaf_moveents(leaf2, 0, leaf1, (int)INT_GET(hdr1->count, ARCH_CONVERT), 1185 count, state->mp); 1186 1187 xfs_da_log_buf(state->args->trans, blk1->bp, 0, 1188 state->blocksize-1); 1189 xfs_da_log_buf(state->args->trans, blk2->bp, 0, 1190 state->blocksize-1); 1191 } 1192 1193 /* 1194 * Copy out last hashval in each block for B-tree code. 1195 */ 1196 blk1->hashval = INT_GET(leaf1->entries[ INT_GET(leaf1->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT); 1197 blk2->hashval = INT_GET(leaf2->entries[ INT_GET(leaf2->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT); 1198 1199 /* 1200 * Adjust the expected index for insertion. 1201 * GROT: this doesn't work unless blk2 was originally empty. 1202 */ 1203 if (!state->inleaf) { 1204 blk2->index = blk1->index - INT_GET(leaf1->hdr.count, ARCH_CONVERT); 1205 } 1206} 1207 1208/* 1209 * Examine entries until we reduce the absolute difference in 1210 * byte usage between the two blocks to a minimum. 1211 * GROT: Is this really necessary? With other than a 512 byte blocksize, 1212 * GROT: there will always be enough room in either block for a new entry. 1213 * GROT: Do a double-split for this case? 1214 */ 1215STATIC int 1216xfs_dir_leaf_figure_balance(xfs_da_state_t *state, 1217 xfs_da_state_blk_t *blk1, 1218 xfs_da_state_blk_t *blk2, 1219 int *countarg, int *namebytesarg) 1220{ 1221 xfs_dir_leafblock_t *leaf1, *leaf2; 1222 xfs_dir_leaf_hdr_t *hdr1, *hdr2; 1223 xfs_dir_leaf_entry_t *entry; 1224 int count, max, totallen, half; 1225 int lastdelta, foundit, tmp; 1226 1227 /* 1228 * Set up environment. 1229 */ 1230 leaf1 = blk1->bp->data; 1231 leaf2 = blk2->bp->data; 1232 hdr1 = &leaf1->hdr; 1233 hdr2 = &leaf2->hdr; 1234 foundit = 0; 1235 totallen = 0; 1236 1237 /* 1238 * Examine entries until we reduce the absolute difference in 1239 * byte usage between the two blocks to a minimum. 1240 */ 1241 max = INT_GET(hdr1->count, ARCH_CONVERT) + INT_GET(hdr2->count, ARCH_CONVERT); 1242 half = (max+1) * (uint)(sizeof(*entry)+sizeof(xfs_dir_leaf_entry_t)-1); 1243 half += INT_GET(hdr1->namebytes, ARCH_CONVERT) + INT_GET(hdr2->namebytes, ARCH_CONVERT) + state->args->namelen; 1244 half /= 2; 1245 lastdelta = state->blocksize; 1246 entry = &leaf1->entries[0]; 1247 for (count = 0; count < max; entry++, count++) { 1248 1249#define XFS_DIR_ABS(A) (((A) < 0) ? -(A) : (A)) 1250 /* 1251 * The new entry is in the first block, account for it. 1252 */ 1253 if (count == blk1->index) { 1254 tmp = totallen + (uint)sizeof(*entry) 1255 + XFS_DIR_LEAF_ENTSIZE_BYNAME(state->args->namelen); 1256 if (XFS_DIR_ABS(half - tmp) > lastdelta) 1257 break; 1258 lastdelta = XFS_DIR_ABS(half - tmp); 1259 totallen = tmp; 1260 foundit = 1; 1261 } 1262 1263 /* 1264 * Wrap around into the second block if necessary. 1265 */ 1266 if (count == INT_GET(hdr1->count, ARCH_CONVERT)) { 1267 leaf1 = leaf2; 1268 entry = &leaf1->entries[0]; 1269 } 1270 1271 /* 1272 * Figure out if next leaf entry would be too much. 1273 */ 1274 tmp = totallen + (uint)sizeof(*entry) 1275 + XFS_DIR_LEAF_ENTSIZE_BYENTRY(entry); 1276 if (XFS_DIR_ABS(half - tmp) > lastdelta) 1277 break; 1278 lastdelta = XFS_DIR_ABS(half - tmp); 1279 totallen = tmp; 1280#undef XFS_DIR_ABS 1281 } 1282 1283 /* 1284 * Calculate the number of namebytes that will end up in lower block. 1285 * If new entry not in lower block, fix up the count. 1286 */ 1287 totallen -= 1288 count * (uint)(sizeof(*entry)+sizeof(xfs_dir_leaf_entry_t)-1); 1289 if (foundit) { 1290 totallen -= (sizeof(*entry)+sizeof(xfs_dir_leaf_entry_t)-1) + 1291 state->args->namelen; 1292 } 1293 1294 *countarg = count; 1295 *namebytesarg = totallen; 1296 return foundit; 1297} 1298 1299/*======================================================================== 1300 * Routines used for shrinking the Btree. 1301 *========================================================================*/ 1302 1303/* 1304 * Check a leaf block and its neighbors to see if the block should be 1305 * collapsed into one or the other neighbor. Always keep the block 1306 * with the smaller block number. 1307 * If the current block is over 50% full, don't try to join it, return 0. 1308 * If the block is empty, fill in the state structure and return 2. 1309 * If it can be collapsed, fill in the state structure and return 1. 1310 * If nothing can be done, return 0. 1311 */ 1312int 1313xfs_dir_leaf_toosmall(xfs_da_state_t *state, int *action) 1314{ 1315 xfs_dir_leafblock_t *leaf; 1316 xfs_da_state_blk_t *blk; 1317 xfs_da_blkinfo_t *info; 1318 int count, bytes, forward, error, retval, i; 1319 xfs_dablk_t blkno; 1320 xfs_dabuf_t *bp; 1321 1322 /* 1323 * Check for the degenerate case of the block being over 50% full. 1324 * If so, it's not worth even looking to see if we might be able 1325 * to coalesce with a sibling. 1326 */ 1327 blk = &state->path.blk[ state->path.active-1 ]; 1328 info = blk->bp->data; 1329 ASSERT(be16_to_cpu(info->magic) == XFS_DIR_LEAF_MAGIC); 1330 leaf = (xfs_dir_leafblock_t *)info; 1331 count = INT_GET(leaf->hdr.count, ARCH_CONVERT); 1332 bytes = (uint)sizeof(xfs_dir_leaf_hdr_t) + 1333 count * (uint)sizeof(xfs_dir_leaf_entry_t) + 1334 count * ((uint)sizeof(xfs_dir_leaf_name_t)-1) + 1335 INT_GET(leaf->hdr.namebytes, ARCH_CONVERT); 1336 if (bytes > (state->blocksize >> 1)) { 1337 *action = 0; /* blk over 50%, don't try to join */ 1338 return 0; 1339 } 1340 1341 /* 1342 * Check for the degenerate case of the block being empty. 1343 * If the block is empty, we'll simply delete it, no need to 1344 * coalesce it with a sibling block. We choose (arbitrarily) 1345 * to merge with the forward block unless it is NULL. 1346 */ 1347 if (count == 0) { 1348 /* 1349 * Make altpath point to the block we want to keep and 1350 * path point to the block we want to drop (this one). 1351 */ 1352 forward = (info->forw != 0); 1353 memcpy(&state->altpath, &state->path, sizeof(state->path)); 1354 error = xfs_da_path_shift(state, &state->altpath, forward, 1355 0, &retval); 1356 if (error) 1357 return error; 1358 if (retval) { 1359 *action = 0; 1360 } else { 1361 *action = 2; 1362 } 1363 return 0; 1364 } 1365 1366 /* 1367 * Examine each sibling block to see if we can coalesce with 1368 * at least 25% free space to spare. We need to figure out 1369 * whether to merge with the forward or the backward block. 1370 * We prefer coalescing with the lower numbered sibling so as 1371 * to shrink a directory over time. 1372 */ 1373 forward = (be32_to_cpu(info->forw) < be32_to_cpu(info->back)); /* start with smaller blk num */ 1374 for (i = 0; i < 2; forward = !forward, i++) { 1375 if (forward) 1376 blkno = be32_to_cpu(info->forw); 1377 else 1378 blkno = be32_to_cpu(info->back); 1379 if (blkno == 0) 1380 continue; 1381 error = xfs_da_read_buf(state->args->trans, state->args->dp, 1382 blkno, -1, &bp, 1383 XFS_DATA_FORK); 1384 if (error) 1385 return error; 1386 ASSERT(bp != NULL); 1387 1388 leaf = (xfs_dir_leafblock_t *)info; 1389 count = INT_GET(leaf->hdr.count, ARCH_CONVERT); 1390 bytes = state->blocksize - (state->blocksize>>2); 1391 bytes -= INT_GET(leaf->hdr.namebytes, ARCH_CONVERT); 1392 leaf = bp->data; 1393 ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); 1394 count += INT_GET(leaf->hdr.count, ARCH_CONVERT); 1395 bytes -= INT_GET(leaf->hdr.namebytes, ARCH_CONVERT); 1396 bytes -= count * ((uint)sizeof(xfs_dir_leaf_name_t) - 1); 1397 bytes -= count * (uint)sizeof(xfs_dir_leaf_entry_t); 1398 bytes -= (uint)sizeof(xfs_dir_leaf_hdr_t); 1399 if (bytes >= 0) 1400 break; /* fits with at least 25% to spare */ 1401 1402 xfs_da_brelse(state->args->trans, bp); 1403 } 1404 if (i >= 2) { 1405 *action = 0; 1406 return 0; 1407 } 1408 xfs_da_buf_done(bp); 1409 1410 /* 1411 * Make altpath point to the block we want to keep (the lower 1412 * numbered block) and path point to the block we want to drop. 1413 */ 1414 memcpy(&state->altpath, &state->path, sizeof(state->path)); 1415 if (blkno < blk->blkno) { 1416 error = xfs_da_path_shift(state, &state->altpath, forward, 1417 0, &retval); 1418 } else { 1419 error = xfs_da_path_shift(state, &state->path, forward, 1420 0, &retval); 1421 } 1422 if (error) 1423 return error; 1424 if (retval) { 1425 *action = 0; 1426 } else { 1427 *action = 1; 1428 } 1429 return 0; 1430} 1431 1432/* 1433 * Remove a name from the leaf directory structure. 1434 * 1435 * Return 1 if leaf is less than 37% full, 0 if >= 37% full. 1436 * If two leaves are 37% full, when combined they will leave 25% free. 1437 */ 1438int 1439xfs_dir_leaf_remove(xfs_trans_t *trans, xfs_dabuf_t *bp, int index) 1440{ 1441 xfs_dir_leafblock_t *leaf; 1442 xfs_dir_leaf_hdr_t *hdr; 1443 xfs_dir_leaf_map_t *map; 1444 xfs_dir_leaf_entry_t *entry; 1445 xfs_dir_leaf_name_t *namest; 1446 int before, after, smallest, entsize; 1447 int tablesize, tmp, i; 1448 xfs_mount_t *mp; 1449 1450 leaf = bp->data; 1451 ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); 1452 hdr = &leaf->hdr; 1453 mp = trans->t_mountp; 1454 ASSERT((INT_GET(hdr->count, ARCH_CONVERT) > 0) && (INT_GET(hdr->count, ARCH_CONVERT) < (XFS_LBSIZE(mp)/8))); 1455 ASSERT((index >= 0) && (index < INT_GET(hdr->count, ARCH_CONVERT))); 1456 ASSERT(INT_GET(hdr->firstused, ARCH_CONVERT) >= ((INT_GET(hdr->count, ARCH_CONVERT)*sizeof(*entry))+sizeof(*hdr))); 1457 entry = &leaf->entries[index]; 1458 ASSERT(INT_GET(entry->nameidx, ARCH_CONVERT) >= INT_GET(hdr->firstused, ARCH_CONVERT)); 1459 ASSERT(INT_GET(entry->nameidx, ARCH_CONVERT) < XFS_LBSIZE(mp)); 1460 1461 /* 1462 * Scan through free region table: 1463 * check for adjacency of free'd entry with an existing one, 1464 * find smallest free region in case we need to replace it, 1465 * adjust any map that borders the entry table, 1466 */ 1467 tablesize = INT_GET(hdr->count, ARCH_CONVERT) * (uint)sizeof(xfs_dir_leaf_entry_t) 1468 + (uint)sizeof(xfs_dir_leaf_hdr_t); 1469 map = &hdr->freemap[0]; 1470 tmp = INT_GET(map->size, ARCH_CONVERT); 1471 before = after = -1; 1472 smallest = XFS_DIR_LEAF_MAPSIZE - 1; 1473 entsize = XFS_DIR_LEAF_ENTSIZE_BYENTRY(entry); 1474 for (i = 0; i < XFS_DIR_LEAF_MAPSIZE; map++, i++) { 1475 ASSERT(INT_GET(map->base, ARCH_CONVERT) < XFS_LBSIZE(mp)); 1476 ASSERT(INT_GET(map->size, ARCH_CONVERT) < XFS_LBSIZE(mp)); 1477 if (INT_GET(map->base, ARCH_CONVERT) == tablesize) { 1478 INT_MOD(map->base, ARCH_CONVERT, -((uint)sizeof(xfs_dir_leaf_entry_t))); 1479 INT_MOD(map->size, ARCH_CONVERT, (uint)sizeof(xfs_dir_leaf_entry_t)); 1480 } 1481 1482 if ((INT_GET(map->base, ARCH_CONVERT) + INT_GET(map->size, ARCH_CONVERT)) == INT_GET(entry->nameidx, ARCH_CONVERT)) { 1483 before = i; 1484 } else if (INT_GET(map->base, ARCH_CONVERT) == (INT_GET(entry->nameidx, ARCH_CONVERT) + entsize)) { 1485 after = i; 1486 } else if (INT_GET(map->size, ARCH_CONVERT) < tmp) { 1487 tmp = INT_GET(map->size, ARCH_CONVERT); 1488 smallest = i; 1489 } 1490 } 1491 1492 /* 1493 * Coalesce adjacent freemap regions, 1494 * or replace the smallest region. 1495 */ 1496 if ((before >= 0) || (after >= 0)) { 1497 if ((before >= 0) && (after >= 0)) { 1498 map = &hdr->freemap[before]; 1499 INT_MOD(map->size, ARCH_CONVERT, entsize); 1500 INT_MOD(map->size, ARCH_CONVERT, INT_GET(hdr->freemap[after].size, ARCH_CONVERT)); 1501 hdr->freemap[after].base = 0; 1502 hdr->freemap[after].size = 0; 1503 } else if (before >= 0) { 1504 map = &hdr->freemap[before]; 1505 INT_MOD(map->size, ARCH_CONVERT, entsize); 1506 } else { 1507 map = &hdr->freemap[after]; 1508 INT_COPY(map->base, entry->nameidx, ARCH_CONVERT); 1509 INT_MOD(map->size, ARCH_CONVERT, entsize); 1510 } 1511 } else { 1512 /* 1513 * Replace smallest region (if it is smaller than free'd entry) 1514 */ 1515 map = &hdr->freemap[smallest]; 1516 if (INT_GET(map->size, ARCH_CONVERT) < entsize) { 1517 INT_COPY(map->base, entry->nameidx, ARCH_CONVERT); 1518 INT_SET(map->size, ARCH_CONVERT, entsize); 1519 } 1520 } 1521 1522 /* 1523 * Did we remove the first entry? 1524 */ 1525 if (INT_GET(entry->nameidx, ARCH_CONVERT) == INT_GET(hdr->firstused, ARCH_CONVERT)) 1526 smallest = 1; 1527 else 1528 smallest = 0; 1529 1530 /* 1531 * Compress the remaining entries and zero out the removed stuff. 1532 */ 1533 namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT)); 1534 memset((char *)namest, 0, entsize); 1535 xfs_da_log_buf(trans, bp, XFS_DA_LOGRANGE(leaf, namest, entsize)); 1536 1537 INT_MOD(hdr->namebytes, ARCH_CONVERT, -(entry->namelen)); 1538 tmp = (INT_GET(hdr->count, ARCH_CONVERT) - index) * (uint)sizeof(xfs_dir_leaf_entry_t); 1539 memmove(entry, entry + 1, tmp); 1540 INT_MOD(hdr->count, ARCH_CONVERT, -1); 1541 xfs_da_log_buf(trans, bp, 1542 XFS_DA_LOGRANGE(leaf, entry, tmp + (uint)sizeof(*entry))); 1543 entry = &leaf->entries[INT_GET(hdr->count, ARCH_CONVERT)]; 1544 memset((char *)entry, 0, sizeof(xfs_dir_leaf_entry_t)); 1545 1546 /* 1547 * If we removed the first entry, re-find the first used byte 1548 * in the name area. Note that if the entry was the "firstused", 1549 * then we don't have a "hole" in our block resulting from 1550 * removing the name. 1551 */ 1552 if (smallest) { 1553 tmp = XFS_LBSIZE(mp); 1554 entry = &leaf->entries[0]; 1555 for (i = INT_GET(hdr->count, ARCH_CONVERT)-1; i >= 0; entry++, i--) { 1556 ASSERT(INT_GET(entry->nameidx, ARCH_CONVERT) >= INT_GET(hdr->firstused, ARCH_CONVERT)); 1557 ASSERT(INT_GET(entry->nameidx, ARCH_CONVERT) < XFS_LBSIZE(mp)); 1558 if (INT_GET(entry->nameidx, ARCH_CONVERT) < tmp) 1559 tmp = INT_GET(entry->nameidx, ARCH_CONVERT); 1560 } 1561 INT_SET(hdr->firstused, ARCH_CONVERT, tmp); 1562 if (!hdr->firstused) 1563 INT_SET(hdr->firstused, ARCH_CONVERT, tmp - 1); 1564 } else { 1565 hdr->holes = 1; /* mark as needing compaction */ 1566 } 1567 1568 xfs_da_log_buf(trans, bp, XFS_DA_LOGRANGE(leaf, hdr, sizeof(*hdr))); 1569 1570 /* 1571 * Check if leaf is less than 50% full, caller may want to 1572 * "join" the leaf with a sibling if so. 1573 */ 1574 tmp = (uint)sizeof(xfs_dir_leaf_hdr_t); 1575 tmp += INT_GET(leaf->hdr.count, ARCH_CONVERT) * (uint)sizeof(xfs_dir_leaf_entry_t); 1576 tmp += INT_GET(leaf->hdr.count, ARCH_CONVERT) * ((uint)sizeof(xfs_dir_leaf_name_t) - 1); 1577 tmp += INT_GET(leaf->hdr.namebytes, ARCH_CONVERT); 1578 if (tmp < mp->m_dir_magicpct) 1579 return 1; /* leaf is < 37% full */ 1580 return 0; 1581} 1582 1583/* 1584 * Move all the directory entries from drop_leaf into save_leaf. 1585 */ 1586void 1587xfs_dir_leaf_unbalance(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk, 1588 xfs_da_state_blk_t *save_blk) 1589{ 1590 xfs_dir_leafblock_t *drop_leaf, *save_leaf, *tmp_leaf; 1591 xfs_dir_leaf_hdr_t *drop_hdr, *save_hdr, *tmp_hdr; 1592 xfs_mount_t *mp; 1593 char *tmpbuffer; 1594 1595 /* 1596 * Set up environment. 1597 */ 1598 mp = state->mp; 1599 ASSERT(drop_blk->magic == XFS_DIR_LEAF_MAGIC); 1600 ASSERT(save_blk->magic == XFS_DIR_LEAF_MAGIC); 1601 drop_leaf = drop_blk->bp->data; 1602 save_leaf = save_blk->bp->data; 1603 ASSERT(be16_to_cpu(drop_leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); 1604 ASSERT(be16_to_cpu(save_leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); 1605 drop_hdr = &drop_leaf->hdr; 1606 save_hdr = &save_leaf->hdr; 1607 1608 /* 1609 * Save last hashval from dying block for later Btree fixup. 1610 */ 1611 drop_blk->hashval = INT_GET(drop_leaf->entries[ drop_leaf->hdr.count-1 ].hashval, ARCH_CONVERT); 1612 1613 /* 1614 * Check if we need a temp buffer, or can we do it in place. 1615 * Note that we don't check "leaf" for holes because we will 1616 * always be dropping it, toosmall() decided that for us already. 1617 */ 1618 if (save_hdr->holes == 0) { 1619 /* 1620 * dest leaf has no holes, so we add there. May need 1621 * to make some room in the entry array. 1622 */ 1623 if (xfs_dir_leaf_order(save_blk->bp, drop_blk->bp)) { 1624 xfs_dir_leaf_moveents(drop_leaf, 0, save_leaf, 0, 1625 (int)INT_GET(drop_hdr->count, ARCH_CONVERT), mp); 1626 } else { 1627 xfs_dir_leaf_moveents(drop_leaf, 0, 1628 save_leaf, INT_GET(save_hdr->count, ARCH_CONVERT), 1629 (int)INT_GET(drop_hdr->count, ARCH_CONVERT), mp); 1630 } 1631 } else { 1632 /* 1633 * Destination has holes, so we make a temporary copy 1634 * of the leaf and add them both to that. 1635 */ 1636 tmpbuffer = kmem_alloc(state->blocksize, KM_SLEEP); 1637 ASSERT(tmpbuffer != NULL); 1638 memset(tmpbuffer, 0, state->blocksize); 1639 tmp_leaf = (xfs_dir_leafblock_t *)tmpbuffer; 1640 tmp_hdr = &tmp_leaf->hdr; 1641 tmp_hdr->info = save_hdr->info; /* struct copy */ 1642 tmp_hdr->count = 0; 1643 INT_SET(tmp_hdr->firstused, ARCH_CONVERT, state->blocksize); 1644 if (!tmp_hdr->firstused) 1645 INT_SET(tmp_hdr->firstused, ARCH_CONVERT, state->blocksize - 1); 1646 tmp_hdr->namebytes = 0; 1647 if (xfs_dir_leaf_order(save_blk->bp, drop_blk->bp)) { 1648 xfs_dir_leaf_moveents(drop_leaf, 0, tmp_leaf, 0, 1649 (int)INT_GET(drop_hdr->count, ARCH_CONVERT), mp); 1650 xfs_dir_leaf_moveents(save_leaf, 0, 1651 tmp_leaf, INT_GET(tmp_leaf->hdr.count, ARCH_CONVERT), 1652 (int)INT_GET(save_hdr->count, ARCH_CONVERT), mp); 1653 } else { 1654 xfs_dir_leaf_moveents(save_leaf, 0, tmp_leaf, 0, 1655 (int)INT_GET(save_hdr->count, ARCH_CONVERT), mp); 1656 xfs_dir_leaf_moveents(drop_leaf, 0, 1657 tmp_leaf, INT_GET(tmp_leaf->hdr.count, ARCH_CONVERT), 1658 (int)INT_GET(drop_hdr->count, ARCH_CONVERT), mp); 1659 } 1660 memcpy(save_leaf, tmp_leaf, state->blocksize); 1661 kmem_free(tmpbuffer, state->blocksize); 1662 } 1663 1664 xfs_da_log_buf(state->args->trans, save_blk->bp, 0, 1665 state->blocksize - 1); 1666 1667 /* 1668 * Copy out last hashval in each block for B-tree code. 1669 */ 1670 save_blk->hashval = INT_GET(save_leaf->entries[ INT_GET(save_leaf->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT); 1671} 1672 1673/*======================================================================== 1674 * Routines used for finding things in the Btree. 1675 *========================================================================*/ 1676 1677/* 1678 * Look up a name in a leaf directory structure. 1679 * This is the internal routine, it uses the caller's buffer. 1680 * 1681 * Note that duplicate keys are allowed, but only check within the 1682 * current leaf node. The Btree code must check in adjacent leaf nodes. 1683 * 1684 * Return in *index the index into the entry[] array of either the found 1685 * entry, or where the entry should have been (insert before that entry). 1686 * 1687 * Don't change the args->inumber unless we find the filename. 1688 */ 1689int 1690xfs_dir_leaf_lookup_int(xfs_dabuf_t *bp, xfs_da_args_t *args, int *index) 1691{ 1692 xfs_dir_leafblock_t *leaf; 1693 xfs_dir_leaf_entry_t *entry; 1694 xfs_dir_leaf_name_t *namest; 1695 int probe, span; 1696 xfs_dahash_t hashval; 1697 1698 leaf = bp->data; 1699 ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); 1700 ASSERT(INT_GET(leaf->hdr.count, ARCH_CONVERT) < (XFS_LBSIZE(args->dp->i_mount)/8)); 1701 1702 /* 1703 * Binary search. (note: small blocks will skip this loop) 1704 */ 1705 hashval = args->hashval; 1706 probe = span = INT_GET(leaf->hdr.count, ARCH_CONVERT) / 2; 1707 for (entry = &leaf->entries[probe]; span > 4; 1708 entry = &leaf->entries[probe]) { 1709 span /= 2; 1710 if (INT_GET(entry->hashval, ARCH_CONVERT) < hashval) 1711 probe += span; 1712 else if (INT_GET(entry->hashval, ARCH_CONVERT) > hashval) 1713 probe -= span; 1714 else 1715 break; 1716 } 1717 ASSERT((probe >= 0) && \ 1718 ((!leaf->hdr.count) || (probe < INT_GET(leaf->hdr.count, ARCH_CONVERT)))); 1719 ASSERT((span <= 4) || (INT_GET(entry->hashval, ARCH_CONVERT) == hashval)); 1720 1721 /* 1722 * Since we may have duplicate hashval's, find the first matching 1723 * hashval in the leaf. 1724 */ 1725 while ((probe > 0) && (INT_GET(entry->hashval, ARCH_CONVERT) >= hashval)) { 1726 entry--; 1727 probe--; 1728 } 1729 while ((probe < INT_GET(leaf->hdr.count, ARCH_CONVERT)) && (INT_GET(entry->hashval, ARCH_CONVERT) < hashval)) { 1730 entry++; 1731 probe++; 1732 } 1733 if ((probe == INT_GET(leaf->hdr.count, ARCH_CONVERT)) || (INT_GET(entry->hashval, ARCH_CONVERT) != hashval)) { 1734 *index = probe; 1735 ASSERT(args->oknoent); 1736 return XFS_ERROR(ENOENT); 1737 } 1738 1739 /* 1740 * Duplicate keys may be present, so search all of them for a match. 1741 */ 1742 while ((probe < INT_GET(leaf->hdr.count, ARCH_CONVERT)) && (INT_GET(entry->hashval, ARCH_CONVERT) == hashval)) { 1743 namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT)); 1744 if (entry->namelen == args->namelen && 1745 namest->name[0] == args->name[0] && 1746 memcmp(args->name, namest->name, args->namelen) == 0) { 1747 XFS_DIR_SF_GET_DIRINO(&namest->inumber, &args->inumber); 1748 *index = probe; 1749 return XFS_ERROR(EEXIST); 1750 } 1751 entry++; 1752 probe++; 1753 } 1754 *index = probe; 1755 ASSERT(probe == INT_GET(leaf->hdr.count, ARCH_CONVERT) || args->oknoent); 1756 return XFS_ERROR(ENOENT); 1757} 1758 1759/*======================================================================== 1760 * Utility routines. 1761 *========================================================================*/ 1762 1763/* 1764 * Move the indicated entries from one leaf to another. 1765 * NOTE: this routine modifies both source and destination leaves. 1766 */ 1767/* ARGSUSED */ 1768STATIC void 1769xfs_dir_leaf_moveents(xfs_dir_leafblock_t *leaf_s, int start_s, 1770 xfs_dir_leafblock_t *leaf_d, int start_d, 1771 int count, xfs_mount_t *mp) 1772{ 1773 xfs_dir_leaf_hdr_t *hdr_s, *hdr_d; 1774 xfs_dir_leaf_entry_t *entry_s, *entry_d; 1775 int tmp, i; 1776 1777 /* 1778 * Check for nothing to do. 1779 */ 1780 if (count == 0) 1781 return; 1782 1783 /* 1784 * Set up environment. 1785 */ 1786 ASSERT(be16_to_cpu(leaf_s->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); 1787 ASSERT(be16_to_cpu(leaf_d->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); 1788 hdr_s = &leaf_s->hdr; 1789 hdr_d = &leaf_d->hdr; 1790 ASSERT((INT_GET(hdr_s->count, ARCH_CONVERT) > 0) && (INT_GET(hdr_s->count, ARCH_CONVERT) < (XFS_LBSIZE(mp)/8))); 1791 ASSERT(INT_GET(hdr_s->firstused, ARCH_CONVERT) >= 1792 ((INT_GET(hdr_s->count, ARCH_CONVERT)*sizeof(*entry_s))+sizeof(*hdr_s))); 1793 ASSERT(INT_GET(hdr_d->count, ARCH_CONVERT) < (XFS_LBSIZE(mp)/8)); 1794 ASSERT(INT_GET(hdr_d->firstused, ARCH_CONVERT) >= 1795 ((INT_GET(hdr_d->count, ARCH_CONVERT)*sizeof(*entry_d))+sizeof(*hdr_d))); 1796 1797 ASSERT(start_s < INT_GET(hdr_s->count, ARCH_CONVERT)); 1798 ASSERT(start_d <= INT_GET(hdr_d->count, ARCH_CONVERT)); 1799 ASSERT(count <= INT_GET(hdr_s->count, ARCH_CONVERT)); 1800 1801 /* 1802 * Move the entries in the destination leaf up to make a hole? 1803 */ 1804 if (start_d < INT_GET(hdr_d->count, ARCH_CONVERT)) { 1805 tmp = INT_GET(hdr_d->count, ARCH_CONVERT) - start_d; 1806 tmp *= (uint)sizeof(xfs_dir_leaf_entry_t); 1807 entry_s = &leaf_d->entries[start_d]; 1808 entry_d = &leaf_d->entries[start_d + count]; 1809 memcpy(entry_d, entry_s, tmp); 1810 } 1811 1812 /* 1813 * Copy all entry's in the same (sorted) order, 1814 * but allocate filenames packed and in sequence. 1815 */ 1816 entry_s = &leaf_s->entries[start_s]; 1817 entry_d = &leaf_d->entries[start_d]; 1818 for (i = 0; i < count; entry_s++, entry_d++, i++) { 1819 ASSERT(INT_GET(entry_s->nameidx, ARCH_CONVERT) >= INT_GET(hdr_s->firstused, ARCH_CONVERT)); 1820 tmp = XFS_DIR_LEAF_ENTSIZE_BYENTRY(entry_s); 1821 INT_MOD(hdr_d->firstused, ARCH_CONVERT, -(tmp)); 1822 entry_d->hashval = entry_s->hashval; /* INT_: direct copy */ 1823 INT_COPY(entry_d->nameidx, hdr_d->firstused, ARCH_CONVERT); 1824 entry_d->namelen = entry_s->namelen; 1825 ASSERT(INT_GET(entry_d->nameidx, ARCH_CONVERT) + tmp <= XFS_LBSIZE(mp)); 1826 memcpy(XFS_DIR_LEAF_NAMESTRUCT(leaf_d, INT_GET(entry_d->nameidx, ARCH_CONVERT)), 1827 XFS_DIR_LEAF_NAMESTRUCT(leaf_s, INT_GET(entry_s->nameidx, ARCH_CONVERT)), tmp); 1828 ASSERT(INT_GET(entry_s->nameidx, ARCH_CONVERT) + tmp <= XFS_LBSIZE(mp)); 1829 memset((char *)XFS_DIR_LEAF_NAMESTRUCT(leaf_s, INT_GET(entry_s->nameidx, ARCH_CONVERT)), 1830 0, tmp); 1831 INT_MOD(hdr_s->namebytes, ARCH_CONVERT, -(entry_d->namelen)); 1832 INT_MOD(hdr_d->namebytes, ARCH_CONVERT, entry_d->namelen); 1833 INT_MOD(hdr_s->count, ARCH_CONVERT, -1); 1834 INT_MOD(hdr_d->count, ARCH_CONVERT, +1); 1835 tmp = INT_GET(hdr_d->count, ARCH_CONVERT) * (uint)sizeof(xfs_dir_leaf_entry_t) 1836 + (uint)sizeof(xfs_dir_leaf_hdr_t); 1837 ASSERT(INT_GET(hdr_d->firstused, ARCH_CONVERT) >= tmp); 1838 1839 } 1840 1841 /* 1842 * Zero out the entries we just copied. 1843 */ 1844 if (start_s == INT_GET(hdr_s->count, ARCH_CONVERT)) { 1845 tmp = count * (uint)sizeof(xfs_dir_leaf_entry_t); 1846 entry_s = &leaf_s->entries[start_s]; 1847 ASSERT((char *)entry_s + tmp <= (char *)leaf_s + XFS_LBSIZE(mp)); 1848 memset((char *)entry_s, 0, tmp); 1849 } else { 1850 /* 1851 * Move the remaining entries down to fill the hole, 1852 * then zero the entries at the top. 1853 */ 1854 tmp = INT_GET(hdr_s->count, ARCH_CONVERT) - count; 1855 tmp *= (uint)sizeof(xfs_dir_leaf_entry_t); 1856 entry_s = &leaf_s->entries[start_s + count]; 1857 entry_d = &leaf_s->entries[start_s]; 1858 memcpy(entry_d, entry_s, tmp); 1859 1860 tmp = count * (uint)sizeof(xfs_dir_leaf_entry_t); 1861 entry_s = &leaf_s->entries[INT_GET(hdr_s->count, ARCH_CONVERT)]; 1862 ASSERT((char *)entry_s + tmp <= (char *)leaf_s + XFS_LBSIZE(mp)); 1863 memset((char *)entry_s, 0, tmp); 1864 } 1865 1866 /* 1867 * Fill in the freemap information 1868 */ 1869 INT_SET(hdr_d->freemap[0].base, ARCH_CONVERT, (uint)sizeof(xfs_dir_leaf_hdr_t)); 1870 INT_MOD(hdr_d->freemap[0].base, ARCH_CONVERT, INT_GET(hdr_d->count, ARCH_CONVERT) * (uint)sizeof(xfs_dir_leaf_entry_t)); 1871 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)); 1872 INT_SET(hdr_d->freemap[1].base, ARCH_CONVERT, (hdr_d->freemap[2].base = 0)); 1873 INT_SET(hdr_d->freemap[1].size, ARCH_CONVERT, (hdr_d->freemap[2].size = 0)); 1874 hdr_s->holes = 1; /* leaf may not be compact */ 1875} 1876 1877/* 1878 * Compare two leaf blocks "order". 1879 */ 1880int 1881xfs_dir_leaf_order(xfs_dabuf_t *leaf1_bp, xfs_dabuf_t *leaf2_bp) 1882{ 1883 xfs_dir_leafblock_t *leaf1, *leaf2; 1884 1885 leaf1 = leaf1_bp->data; 1886 leaf2 = leaf2_bp->data; 1887 ASSERT((be16_to_cpu(leaf1->hdr.info.magic) == XFS_DIR_LEAF_MAGIC) && 1888 (be16_to_cpu(leaf2->hdr.info.magic) == XFS_DIR_LEAF_MAGIC)); 1889 if ((INT_GET(leaf1->hdr.count, ARCH_CONVERT) > 0) && (INT_GET(leaf2->hdr.count, ARCH_CONVERT) > 0) && 1890 ((INT_GET(leaf2->entries[ 0 ].hashval, ARCH_CONVERT) < 1891 INT_GET(leaf1->entries[ 0 ].hashval, ARCH_CONVERT)) || 1892 (INT_GET(leaf2->entries[ INT_GET(leaf2->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT) < 1893 INT_GET(leaf1->entries[ INT_GET(leaf1->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT)))) { 1894 return 1; 1895 } 1896 return 0; 1897} 1898 1899/* 1900 * Pick up the last hashvalue from a leaf block. 1901 */ 1902xfs_dahash_t 1903xfs_dir_leaf_lasthash(xfs_dabuf_t *bp, int *count) 1904{ 1905 xfs_dir_leafblock_t *leaf; 1906 1907 leaf = bp->data; 1908 ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); 1909 if (count) 1910 *count = INT_GET(leaf->hdr.count, ARCH_CONVERT); 1911 if (!leaf->hdr.count) 1912 return(0); 1913 return(INT_GET(leaf->entries[ INT_GET(leaf->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT)); 1914} 1915 1916/* 1917 * Copy out directory entries for getdents(), for leaf directories. 1918 */ 1919int 1920xfs_dir_leaf_getdents_int( 1921 xfs_dabuf_t *bp, 1922 xfs_inode_t *dp, 1923 xfs_dablk_t bno, 1924 uio_t *uio, 1925 int *eobp, 1926 xfs_dirent_t *dbp, 1927 xfs_dir_put_t put, 1928 xfs_daddr_t nextda) 1929{ 1930 xfs_dir_leafblock_t *leaf; 1931 xfs_dir_leaf_entry_t *entry; 1932 xfs_dir_leaf_name_t *namest; 1933 int entno, want_entno, i, nextentno; 1934 xfs_mount_t *mp; 1935 xfs_dahash_t cookhash; 1936 xfs_dahash_t nexthash = 0; 1937#if (BITS_PER_LONG == 32) 1938 xfs_dahash_t lasthash = XFS_DA_MAXHASH; 1939#endif 1940 xfs_dir_put_args_t p; 1941 1942 mp = dp->i_mount; 1943 leaf = bp->data; 1944 if (be16_to_cpu(leaf->hdr.info.magic) != XFS_DIR_LEAF_MAGIC) { 1945 *eobp = 1; 1946 return XFS_ERROR(ENOENT); /* XXX wrong code */ 1947 } 1948 1949 want_entno = XFS_DA_COOKIE_ENTRY(mp, uio->uio_offset); 1950 1951 cookhash = XFS_DA_COOKIE_HASH(mp, uio->uio_offset); 1952 1953 xfs_dir_trace_g_dul("leaf: start", dp, uio, leaf); 1954 1955 /* 1956 * Re-find our place. 1957 */ 1958 for (i = entno = 0, entry = &leaf->entries[0]; 1959 i < INT_GET(leaf->hdr.count, ARCH_CONVERT); 1960 entry++, i++) { 1961 1962 namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, 1963 INT_GET(entry->nameidx, ARCH_CONVERT)); 1964 1965 if (unlikely( 1966 ((char *)namest < (char *)leaf) || 1967 ((char *)namest >= (char *)leaf + XFS_LBSIZE(mp)))) { 1968 XFS_CORRUPTION_ERROR("xfs_dir_leaf_getdents_int(1)", 1969 XFS_ERRLEVEL_LOW, mp, leaf); 1970 xfs_dir_trace_g_du("leaf: corrupted", dp, uio); 1971 return XFS_ERROR(EFSCORRUPTED); 1972 } 1973 if (INT_GET(entry->hashval, ARCH_CONVERT) >= cookhash) { 1974 if ( entno < want_entno 1975 && INT_GET(entry->hashval, ARCH_CONVERT) 1976 == cookhash) { 1977 /* 1978 * Trying to get to a particular offset in a 1979 * run of equal-hashval entries. 1980 */ 1981 entno++; 1982 } else if ( want_entno > 0 1983 && entno == want_entno 1984 && INT_GET(entry->hashval, ARCH_CONVERT) 1985 == cookhash) { 1986 break; 1987 } else { 1988 entno = 0; 1989 break; 1990 } 1991 } 1992 } 1993 1994 if (i == INT_GET(leaf->hdr.count, ARCH_CONVERT)) { 1995 xfs_dir_trace_g_du("leaf: hash not found", dp, uio); 1996 if (!leaf->hdr.info.forw) 1997 uio->uio_offset = 1998 XFS_DA_MAKE_COOKIE(mp, 0, 0, XFS_DA_MAXHASH); 1999 /* 2000 * Don't set uio_offset if there's another block: 2001 * the node code will be setting uio_offset anyway. 2002 */ 2003 *eobp = 0; 2004 return 0; 2005 } 2006 xfs_dir_trace_g_due("leaf: hash found", dp, uio, entry); 2007 2008 p.dbp = dbp; 2009 p.put = put; 2010 p.uio = uio; 2011 2012 /* 2013 * We're synchronized, start copying entries out to the user. 2014 */ 2015 for (; entno >= 0 && i < INT_GET(leaf->hdr.count, ARCH_CONVERT); 2016 entry++, i++, (entno = nextentno)) { 2017 int lastresid=0, retval; 2018 xfs_dircook_t lastoffset; 2019 xfs_dahash_t thishash; 2020 2021 /* 2022 * Check for a damaged directory leaf block and pick up 2023 * the inode number from this entry. 2024 */ 2025 namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, 2026 INT_GET(entry->nameidx, ARCH_CONVERT)); 2027 2028 if (unlikely( 2029 ((char *)namest < (char *)leaf) || 2030 ((char *)namest >= (char *)leaf + XFS_LBSIZE(mp)))) { 2031 XFS_CORRUPTION_ERROR("xfs_dir_leaf_getdents_int(2)", 2032 XFS_ERRLEVEL_LOW, mp, leaf); 2033 xfs_dir_trace_g_du("leaf: corrupted", dp, uio); 2034 return XFS_ERROR(EFSCORRUPTED); 2035 } 2036 2037 xfs_dir_trace_g_duc("leaf: middle cookie ", 2038 dp, uio, p.cook.o); 2039 2040 if (i < (INT_GET(leaf->hdr.count, ARCH_CONVERT) - 1)) { 2041 nexthash = INT_GET(entry[1].hashval, ARCH_CONVERT); 2042 2043 if (nexthash == INT_GET(entry->hashval, ARCH_CONVERT)) 2044 nextentno = entno + 1; 2045 else 2046 nextentno = 0; 2047 XFS_PUT_COOKIE(p.cook, mp, bno, nextentno, nexthash); 2048 xfs_dir_trace_g_duc("leaf: middle cookie ", 2049 dp, uio, p.cook.o); 2050 2051 } else if ((thishash = be32_to_cpu(leaf->hdr.info.forw))) { 2052 xfs_dabuf_t *bp2; 2053 xfs_dir_leafblock_t *leaf2; 2054 2055 ASSERT(nextda != -1); 2056 2057 retval = xfs_da_read_buf(dp->i_transp, dp, thishash, 2058 nextda, &bp2, XFS_DATA_FORK); 2059 if (retval) 2060 return retval; 2061 2062 ASSERT(bp2 != NULL); 2063 2064 leaf2 = bp2->data; 2065 2066 if (unlikely( 2067 (be16_to_cpu(leaf2->hdr.info.magic) 2068 != XFS_DIR_LEAF_MAGIC) 2069 || (be32_to_cpu(leaf2->hdr.info.back) 2070 != bno))) { /* GROT */ 2071 XFS_CORRUPTION_ERROR("xfs_dir_leaf_getdents_int(3)", 2072 XFS_ERRLEVEL_LOW, mp, 2073 leaf2); 2074 xfs_da_brelse(dp->i_transp, bp2); 2075 2076 return XFS_ERROR(EFSCORRUPTED); 2077 } 2078 2079 nexthash = INT_GET(leaf2->entries[0].hashval, 2080 ARCH_CONVERT); 2081 nextentno = -1; 2082 XFS_PUT_COOKIE(p.cook, mp, thishash, 0, nexthash); 2083 xfs_da_brelse(dp->i_transp, bp2); 2084 xfs_dir_trace_g_duc("leaf: next blk cookie", 2085 dp, uio, p.cook.o); 2086 } else { 2087 nextentno = -1; 2088 XFS_PUT_COOKIE(p.cook, mp, 0, 0, XFS_DA_MAXHASH); 2089 } 2090 2091 /* 2092 * Save off the cookie so we can fall back should the 2093 * 'put' into the outgoing buffer fails. To handle a run 2094 * of equal-hashvals, the off_t structure on 64bit 2095 * builds has entno built into the cookie to ID the 2096 * entry. On 32bit builds, we only have space for the 2097 * hashval so we can't ID specific entries within a group 2098 * of same hashval entries. For this, lastoffset is set 2099 * to the first in the run of equal hashvals so we don't 2100 * include any entries unless we can include all entries 2101 * that share the same hashval. Hopefully the buffer 2102 * provided is big enough to handle it (see pv763517). 2103 */ 2104#if (BITS_PER_LONG == 32) 2105 if ((thishash = INT_GET(entry->hashval, ARCH_CONVERT)) 2106 != lasthash) { 2107 XFS_PUT_COOKIE(lastoffset, mp, bno, entno, thishash); 2108 lastresid = uio->uio_resid; 2109 lasthash = thishash; 2110 } else { 2111 xfs_dir_trace_g_duc("leaf: DUP COOKIES, skipped", 2112 dp, uio, p.cook.o); 2113 } 2114#else 2115 thishash = INT_GET(entry->hashval, ARCH_CONVERT); 2116 XFS_PUT_COOKIE(lastoffset, mp, bno, entno, thishash); 2117 lastresid = uio->uio_resid; 2118#endif /* BITS_PER_LONG == 32 */ 2119 2120 /* 2121 * Put the current entry into the outgoing buffer. If we fail 2122 * then restore the UIO to the first entry in the current 2123 * run of equal-hashval entries (probably one 1 entry long). 2124 */ 2125 p.ino = XFS_GET_DIR_INO8(namest->inumber); 2126#if XFS_BIG_INUMS 2127 p.ino += mp->m_inoadd; 2128#endif 2129 p.name = (char *)namest->name; 2130 p.namelen = entry->namelen; 2131 2132 retval = p.put(&p); 2133 2134 if (!p.done) { 2135 uio->uio_offset = lastoffset.o; 2136 uio->uio_resid = lastresid; 2137 2138 *eobp = 1; 2139 2140 xfs_dir_trace_g_du("leaf: E-O-B", dp, uio); 2141 2142 return retval; 2143 } 2144 } 2145 2146 uio->uio_offset = p.cook.o; 2147 2148 *eobp = 0; 2149 2150 xfs_dir_trace_g_du("leaf: E-O-F", dp, uio); 2151 2152 return 0; 2153} 2154 2155/* 2156 * Format a dirent64 structure and copy it out the user's buffer. 2157 */ 2158int 2159xfs_dir_put_dirent64_direct(xfs_dir_put_args_t *pa) 2160{ 2161 iovec_t *iovp; 2162 int reclen, namelen; 2163 xfs_dirent_t *idbp; 2164 uio_t *uio; 2165 2166 namelen = pa->namelen; 2167 reclen = DIRENTSIZE(namelen); 2168 uio = pa->uio; 2169 if (reclen > uio->uio_resid) { 2170 pa->done = 0; 2171 return 0; 2172 } 2173 iovp = uio->uio_iov; 2174 idbp = (xfs_dirent_t *)iovp->iov_base; 2175 iovp->iov_base = (char *)idbp + reclen; 2176 iovp->iov_len -= reclen; 2177 uio->uio_resid -= reclen; 2178 idbp->d_reclen = reclen; 2179 idbp->d_ino = pa->ino; 2180 idbp->d_off = pa->cook.o; 2181 idbp->d_name[namelen] = '\0'; 2182 pa->done = 1; 2183 memcpy(idbp->d_name, pa->name, namelen); 2184 return 0; 2185} 2186 2187/* 2188 * Format a dirent64 structure and copy it out the user's buffer. 2189 */ 2190int 2191xfs_dir_put_dirent64_uio(xfs_dir_put_args_t *pa) 2192{ 2193 int retval, reclen, namelen; 2194 xfs_dirent_t *idbp; 2195 uio_t *uio; 2196 2197 namelen = pa->namelen; 2198 reclen = DIRENTSIZE(namelen); 2199 uio = pa->uio; 2200 if (reclen > uio->uio_resid) { 2201 pa->done = 0; 2202 return 0; 2203 } 2204 idbp = pa->dbp; 2205 idbp->d_reclen = reclen; 2206 idbp->d_ino = pa->ino; 2207 idbp->d_off = pa->cook.o; 2208 idbp->d_name[namelen] = '\0'; 2209 memcpy(idbp->d_name, pa->name, namelen); 2210 retval = uio_read((caddr_t)idbp, reclen, uio); 2211 pa->done = (retval == 0); 2212 return retval; 2213} 2214 2215 2216