1/* 2 * Copyright (c) 2000-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_bit.h" 22#include "xfs_log.h" 23#include "xfs_inum.h" 24#include "xfs_trans.h" 25#include "xfs_sb.h" 26#include "xfs_ag.h" 27#include "xfs_mount.h" 28#include "xfs_da_btree.h" 29#include "xfs_bmap_btree.h" 30#include "xfs_alloc_btree.h" 31#include "xfs_ialloc_btree.h" 32#include "xfs_alloc.h" 33#include "xfs_btree.h" 34#include "xfs_attr_sf.h" 35#include "xfs_dinode.h" 36#include "xfs_inode.h" 37#include "xfs_inode_item.h" 38#include "xfs_bmap.h" 39#include "xfs_attr.h" 40#include "xfs_attr_leaf.h" 41#include "xfs_error.h" 42#include "xfs_trace.h" 43 44/* 45 * xfs_attr_leaf.c 46 * 47 * Routines to implement leaf blocks of attributes as Btrees of hashed names. 48 */ 49 50/*======================================================================== 51 * Function prototypes for the kernel. 52 *========================================================================*/ 53 54/* 55 * Routines used for growing the Btree. 56 */ 57STATIC int xfs_attr_leaf_create(xfs_da_args_t *args, xfs_dablk_t which_block, 58 xfs_dabuf_t **bpp); 59STATIC int xfs_attr_leaf_add_work(xfs_dabuf_t *leaf_buffer, xfs_da_args_t *args, 60 int freemap_index); 61STATIC void xfs_attr_leaf_compact(xfs_trans_t *trans, xfs_dabuf_t *leaf_buffer); 62STATIC void xfs_attr_leaf_rebalance(xfs_da_state_t *state, 63 xfs_da_state_blk_t *blk1, 64 xfs_da_state_blk_t *blk2); 65STATIC int xfs_attr_leaf_figure_balance(xfs_da_state_t *state, 66 xfs_da_state_blk_t *leaf_blk_1, 67 xfs_da_state_blk_t *leaf_blk_2, 68 int *number_entries_in_blk1, 69 int *number_usedbytes_in_blk1); 70 71/* 72 * Routines used for shrinking the Btree. 73 */ 74STATIC int xfs_attr_node_inactive(xfs_trans_t **trans, xfs_inode_t *dp, 75 xfs_dabuf_t *bp, int level); 76STATIC int xfs_attr_leaf_inactive(xfs_trans_t **trans, xfs_inode_t *dp, 77 xfs_dabuf_t *bp); 78STATIC int xfs_attr_leaf_freextent(xfs_trans_t **trans, xfs_inode_t *dp, 79 xfs_dablk_t blkno, int blkcnt); 80 81/* 82 * Utility routines. 83 */ 84STATIC void xfs_attr_leaf_moveents(xfs_attr_leafblock_t *src_leaf, 85 int src_start, 86 xfs_attr_leafblock_t *dst_leaf, 87 int dst_start, int move_count, 88 xfs_mount_t *mp); 89STATIC int xfs_attr_leaf_entsize(xfs_attr_leafblock_t *leaf, int index); 90 91/*======================================================================== 92 * Namespace helper routines 93 *========================================================================*/ 94 95/* 96 * If namespace bits don't match return 0. 97 * If all match then return 1. 98 */ 99STATIC int 100xfs_attr_namesp_match(int arg_flags, int ondisk_flags) 101{ 102 return XFS_ATTR_NSP_ONDISK(ondisk_flags) == XFS_ATTR_NSP_ARGS_TO_ONDISK(arg_flags); 103} 104 105 106/*======================================================================== 107 * External routines when attribute fork size < XFS_LITINO(mp). 108 *========================================================================*/ 109 110/* 111 * Query whether the requested number of additional bytes of extended 112 * attribute space will be able to fit inline. 113 * Returns zero if not, else the di_forkoff fork offset to be used in the 114 * literal area for attribute data once the new bytes have been added. 115 * 116 * di_forkoff must be 8 byte aligned, hence is stored as a >>3 value; 117 * special case for dev/uuid inodes, they have fixed size data forks. 118 */ 119int 120xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes) 121{ 122 int offset; 123 int minforkoff; /* lower limit on valid forkoff locations */ 124 int maxforkoff; /* upper limit on valid forkoff locations */ 125 int dsize; 126 xfs_mount_t *mp = dp->i_mount; 127 128 offset = (XFS_LITINO(mp) - bytes) >> 3; /* rounded down */ 129 130 switch (dp->i_d.di_format) { 131 case XFS_DINODE_FMT_DEV: 132 minforkoff = roundup(sizeof(xfs_dev_t), 8) >> 3; 133 return (offset >= minforkoff) ? minforkoff : 0; 134 case XFS_DINODE_FMT_UUID: 135 minforkoff = roundup(sizeof(uuid_t), 8) >> 3; 136 return (offset >= minforkoff) ? minforkoff : 0; 137 } 138 139 if (!(mp->m_flags & XFS_MOUNT_ATTR2)) { 140 if (bytes <= XFS_IFORK_ASIZE(dp)) 141 return dp->i_d.di_forkoff; 142 return 0; 143 } 144 145 dsize = dp->i_df.if_bytes; 146 147 switch (dp->i_d.di_format) { 148 case XFS_DINODE_FMT_EXTENTS: 149 /* 150 * If there is no attr fork and the data fork is extents, 151 * determine if creating the default attr fork will result 152 * in the extents form migrating to btree. If so, the 153 * minimum offset only needs to be the space required for 154 * the btree root. 155 */ 156 if (!dp->i_d.di_forkoff && dp->i_df.if_bytes > 157 xfs_default_attroffset(dp)) 158 dsize = XFS_BMDR_SPACE_CALC(MINDBTPTRS); 159 break; 160 161 case XFS_DINODE_FMT_BTREE: 162 /* 163 * If have data btree then keep forkoff if we have one, 164 * otherwise we are adding a new attr, so then we set 165 * minforkoff to where the btree root can finish so we have 166 * plenty of room for attrs 167 */ 168 if (dp->i_d.di_forkoff) { 169 if (offset < dp->i_d.di_forkoff) 170 return 0; 171 else 172 return dp->i_d.di_forkoff; 173 } else 174 dsize = XFS_BMAP_BROOT_SPACE(dp->i_df.if_broot); 175 break; 176 } 177 178 /* 179 * A data fork btree root must have space for at least 180 * MINDBTPTRS key/ptr pairs if the data fork is small or empty. 181 */ 182 minforkoff = MAX(dsize, XFS_BMDR_SPACE_CALC(MINDBTPTRS)); 183 minforkoff = roundup(minforkoff, 8) >> 3; 184 185 /* attr fork btree root can have at least this many key/ptr pairs */ 186 maxforkoff = XFS_LITINO(mp) - XFS_BMDR_SPACE_CALC(MINABTPTRS); 187 maxforkoff = maxforkoff >> 3; /* rounded down */ 188 189 if (offset >= minforkoff && offset < maxforkoff) 190 return offset; 191 if (offset >= maxforkoff) 192 return maxforkoff; 193 return 0; 194} 195 196/* 197 * Switch on the ATTR2 superblock bit (implies also FEATURES2) 198 */ 199STATIC void 200xfs_sbversion_add_attr2(xfs_mount_t *mp, xfs_trans_t *tp) 201{ 202 if ((mp->m_flags & XFS_MOUNT_ATTR2) && 203 !(xfs_sb_version_hasattr2(&mp->m_sb))) { 204 spin_lock(&mp->m_sb_lock); 205 if (!xfs_sb_version_hasattr2(&mp->m_sb)) { 206 xfs_sb_version_addattr2(&mp->m_sb); 207 spin_unlock(&mp->m_sb_lock); 208 xfs_mod_sb(tp, XFS_SB_VERSIONNUM | XFS_SB_FEATURES2); 209 } else 210 spin_unlock(&mp->m_sb_lock); 211 } 212} 213 214/* 215 * Create the initial contents of a shortform attribute list. 216 */ 217void 218xfs_attr_shortform_create(xfs_da_args_t *args) 219{ 220 xfs_attr_sf_hdr_t *hdr; 221 xfs_inode_t *dp; 222 xfs_ifork_t *ifp; 223 224 dp = args->dp; 225 ASSERT(dp != NULL); 226 ifp = dp->i_afp; 227 ASSERT(ifp != NULL); 228 ASSERT(ifp->if_bytes == 0); 229 if (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS) { 230 ifp->if_flags &= ~XFS_IFEXTENTS; /* just in case */ 231 dp->i_d.di_aformat = XFS_DINODE_FMT_LOCAL; 232 ifp->if_flags |= XFS_IFINLINE; 233 } else { 234 ASSERT(ifp->if_flags & XFS_IFINLINE); 235 } 236 xfs_idata_realloc(dp, sizeof(*hdr), XFS_ATTR_FORK); 237 hdr = (xfs_attr_sf_hdr_t *)ifp->if_u1.if_data; 238 hdr->count = 0; 239 hdr->totsize = cpu_to_be16(sizeof(*hdr)); 240 xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_ADATA); 241} 242 243/* 244 * Add a name/value pair to the shortform attribute list. 245 * Overflow from the inode has already been checked for. 246 */ 247void 248xfs_attr_shortform_add(xfs_da_args_t *args, int forkoff) 249{ 250 xfs_attr_shortform_t *sf; 251 xfs_attr_sf_entry_t *sfe; 252 int i, offset, size; 253 xfs_mount_t *mp; 254 xfs_inode_t *dp; 255 xfs_ifork_t *ifp; 256 257 dp = args->dp; 258 mp = dp->i_mount; 259 dp->i_d.di_forkoff = forkoff; 260 dp->i_df.if_ext_max = 261 XFS_IFORK_DSIZE(dp) / (uint)sizeof(xfs_bmbt_rec_t); 262 dp->i_afp->if_ext_max = 263 XFS_IFORK_ASIZE(dp) / (uint)sizeof(xfs_bmbt_rec_t); 264 265 ifp = dp->i_afp; 266 ASSERT(ifp->if_flags & XFS_IFINLINE); 267 sf = (xfs_attr_shortform_t *)ifp->if_u1.if_data; 268 sfe = &sf->list[0]; 269 for (i = 0; i < sf->hdr.count; sfe = XFS_ATTR_SF_NEXTENTRY(sfe), i++) { 270#ifdef DEBUG 271 if (sfe->namelen != args->namelen) 272 continue; 273 if (memcmp(args->name, sfe->nameval, args->namelen) != 0) 274 continue; 275 if (!xfs_attr_namesp_match(args->flags, sfe->flags)) 276 continue; 277 ASSERT(0); 278#endif 279 } 280 281 offset = (char *)sfe - (char *)sf; 282 size = XFS_ATTR_SF_ENTSIZE_BYNAME(args->namelen, args->valuelen); 283 xfs_idata_realloc(dp, size, XFS_ATTR_FORK); 284 sf = (xfs_attr_shortform_t *)ifp->if_u1.if_data; 285 sfe = (xfs_attr_sf_entry_t *)((char *)sf + offset); 286 287 sfe->namelen = args->namelen; 288 sfe->valuelen = args->valuelen; 289 sfe->flags = XFS_ATTR_NSP_ARGS_TO_ONDISK(args->flags); 290 memcpy(sfe->nameval, args->name, args->namelen); 291 memcpy(&sfe->nameval[args->namelen], args->value, args->valuelen); 292 sf->hdr.count++; 293 be16_add_cpu(&sf->hdr.totsize, size); 294 xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_ADATA); 295 296 xfs_sbversion_add_attr2(mp, args->trans); 297} 298 299/* 300 * After the last attribute is removed revert to original inode format, 301 * making all literal area available to the data fork once more. 302 */ 303STATIC void 304xfs_attr_fork_reset( 305 struct xfs_inode *ip, 306 struct xfs_trans *tp) 307{ 308 xfs_idestroy_fork(ip, XFS_ATTR_FORK); 309 ip->i_d.di_forkoff = 0; 310 ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS; 311 312 ASSERT(ip->i_d.di_anextents == 0); 313 ASSERT(ip->i_afp == NULL); 314 315 ip->i_df.if_ext_max = XFS_IFORK_DSIZE(ip) / sizeof(xfs_bmbt_rec_t); 316 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); 317} 318 319/* 320 * Remove an attribute from the shortform attribute list structure. 321 */ 322int 323xfs_attr_shortform_remove(xfs_da_args_t *args) 324{ 325 xfs_attr_shortform_t *sf; 326 xfs_attr_sf_entry_t *sfe; 327 int base, size=0, end, totsize, i; 328 xfs_mount_t *mp; 329 xfs_inode_t *dp; 330 331 dp = args->dp; 332 mp = dp->i_mount; 333 base = sizeof(xfs_attr_sf_hdr_t); 334 sf = (xfs_attr_shortform_t *)dp->i_afp->if_u1.if_data; 335 sfe = &sf->list[0]; 336 end = sf->hdr.count; 337 for (i = 0; i < end; sfe = XFS_ATTR_SF_NEXTENTRY(sfe), 338 base += size, i++) { 339 size = XFS_ATTR_SF_ENTSIZE(sfe); 340 if (sfe->namelen != args->namelen) 341 continue; 342 if (memcmp(sfe->nameval, args->name, args->namelen) != 0) 343 continue; 344 if (!xfs_attr_namesp_match(args->flags, sfe->flags)) 345 continue; 346 break; 347 } 348 if (i == end) 349 return(XFS_ERROR(ENOATTR)); 350 351 /* 352 * Fix up the attribute fork data, covering the hole 353 */ 354 end = base + size; 355 totsize = be16_to_cpu(sf->hdr.totsize); 356 if (end != totsize) 357 memmove(&((char *)sf)[base], &((char *)sf)[end], totsize - end); 358 sf->hdr.count--; 359 be16_add_cpu(&sf->hdr.totsize, -size); 360 361 /* 362 * Fix up the start offset of the attribute fork 363 */ 364 totsize -= size; 365 if (totsize == sizeof(xfs_attr_sf_hdr_t) && 366 (mp->m_flags & XFS_MOUNT_ATTR2) && 367 (dp->i_d.di_format != XFS_DINODE_FMT_BTREE) && 368 !(args->op_flags & XFS_DA_OP_ADDNAME)) { 369 xfs_attr_fork_reset(dp, args->trans); 370 } else { 371 xfs_idata_realloc(dp, -size, XFS_ATTR_FORK); 372 dp->i_d.di_forkoff = xfs_attr_shortform_bytesfit(dp, totsize); 373 ASSERT(dp->i_d.di_forkoff); 374 ASSERT(totsize > sizeof(xfs_attr_sf_hdr_t) || 375 (args->op_flags & XFS_DA_OP_ADDNAME) || 376 !(mp->m_flags & XFS_MOUNT_ATTR2) || 377 dp->i_d.di_format == XFS_DINODE_FMT_BTREE); 378 dp->i_afp->if_ext_max = 379 XFS_IFORK_ASIZE(dp) / (uint)sizeof(xfs_bmbt_rec_t); 380 dp->i_df.if_ext_max = 381 XFS_IFORK_DSIZE(dp) / (uint)sizeof(xfs_bmbt_rec_t); 382 xfs_trans_log_inode(args->trans, dp, 383 XFS_ILOG_CORE | XFS_ILOG_ADATA); 384 } 385 386 xfs_sbversion_add_attr2(mp, args->trans); 387 388 return(0); 389} 390 391/* 392 * Look up a name in a shortform attribute list structure. 393 */ 394/*ARGSUSED*/ 395int 396xfs_attr_shortform_lookup(xfs_da_args_t *args) 397{ 398 xfs_attr_shortform_t *sf; 399 xfs_attr_sf_entry_t *sfe; 400 int i; 401 xfs_ifork_t *ifp; 402 403 ifp = args->dp->i_afp; 404 ASSERT(ifp->if_flags & XFS_IFINLINE); 405 sf = (xfs_attr_shortform_t *)ifp->if_u1.if_data; 406 sfe = &sf->list[0]; 407 for (i = 0; i < sf->hdr.count; 408 sfe = XFS_ATTR_SF_NEXTENTRY(sfe), i++) { 409 if (sfe->namelen != args->namelen) 410 continue; 411 if (memcmp(args->name, sfe->nameval, args->namelen) != 0) 412 continue; 413 if (!xfs_attr_namesp_match(args->flags, sfe->flags)) 414 continue; 415 return(XFS_ERROR(EEXIST)); 416 } 417 return(XFS_ERROR(ENOATTR)); 418} 419 420/* 421 * Look up a name in a shortform attribute list structure. 422 */ 423/*ARGSUSED*/ 424int 425xfs_attr_shortform_getvalue(xfs_da_args_t *args) 426{ 427 xfs_attr_shortform_t *sf; 428 xfs_attr_sf_entry_t *sfe; 429 int i; 430 431 ASSERT(args->dp->i_d.di_aformat == XFS_IFINLINE); 432 sf = (xfs_attr_shortform_t *)args->dp->i_afp->if_u1.if_data; 433 sfe = &sf->list[0]; 434 for (i = 0; i < sf->hdr.count; 435 sfe = XFS_ATTR_SF_NEXTENTRY(sfe), i++) { 436 if (sfe->namelen != args->namelen) 437 continue; 438 if (memcmp(args->name, sfe->nameval, args->namelen) != 0) 439 continue; 440 if (!xfs_attr_namesp_match(args->flags, sfe->flags)) 441 continue; 442 if (args->flags & ATTR_KERNOVAL) { 443 args->valuelen = sfe->valuelen; 444 return(XFS_ERROR(EEXIST)); 445 } 446 if (args->valuelen < sfe->valuelen) { 447 args->valuelen = sfe->valuelen; 448 return(XFS_ERROR(ERANGE)); 449 } 450 args->valuelen = sfe->valuelen; 451 memcpy(args->value, &sfe->nameval[args->namelen], 452 args->valuelen); 453 return(XFS_ERROR(EEXIST)); 454 } 455 return(XFS_ERROR(ENOATTR)); 456} 457 458/* 459 * Convert from using the shortform to the leaf. 460 */ 461int 462xfs_attr_shortform_to_leaf(xfs_da_args_t *args) 463{ 464 xfs_inode_t *dp; 465 xfs_attr_shortform_t *sf; 466 xfs_attr_sf_entry_t *sfe; 467 xfs_da_args_t nargs; 468 char *tmpbuffer; 469 int error, i, size; 470 xfs_dablk_t blkno; 471 xfs_dabuf_t *bp; 472 xfs_ifork_t *ifp; 473 474 dp = args->dp; 475 ifp = dp->i_afp; 476 sf = (xfs_attr_shortform_t *)ifp->if_u1.if_data; 477 size = be16_to_cpu(sf->hdr.totsize); 478 tmpbuffer = kmem_alloc(size, KM_SLEEP); 479 ASSERT(tmpbuffer != NULL); 480 memcpy(tmpbuffer, ifp->if_u1.if_data, size); 481 sf = (xfs_attr_shortform_t *)tmpbuffer; 482 483 xfs_idata_realloc(dp, -size, XFS_ATTR_FORK); 484 bp = NULL; 485 error = xfs_da_grow_inode(args, &blkno); 486 if (error) { 487 /* 488 * If we hit an IO error middle of the transaction inside 489 * grow_inode(), we may have inconsistent data. Bail out. 490 */ 491 if (error == EIO) 492 goto out; 493 xfs_idata_realloc(dp, size, XFS_ATTR_FORK); /* try to put */ 494 memcpy(ifp->if_u1.if_data, tmpbuffer, size); /* it back */ 495 goto out; 496 } 497 498 ASSERT(blkno == 0); 499 error = xfs_attr_leaf_create(args, blkno, &bp); 500 if (error) { 501 error = xfs_da_shrink_inode(args, 0, bp); 502 bp = NULL; 503 if (error) 504 goto out; 505 xfs_idata_realloc(dp, size, XFS_ATTR_FORK); /* try to put */ 506 memcpy(ifp->if_u1.if_data, tmpbuffer, size); /* it back */ 507 goto out; 508 } 509 510 memset((char *)&nargs, 0, sizeof(nargs)); 511 nargs.dp = dp; 512 nargs.firstblock = args->firstblock; 513 nargs.flist = args->flist; 514 nargs.total = args->total; 515 nargs.whichfork = XFS_ATTR_FORK; 516 nargs.trans = args->trans; 517 nargs.op_flags = XFS_DA_OP_OKNOENT; 518 519 sfe = &sf->list[0]; 520 for (i = 0; i < sf->hdr.count; i++) { 521 nargs.name = sfe->nameval; 522 nargs.namelen = sfe->namelen; 523 nargs.value = &sfe->nameval[nargs.namelen]; 524 nargs.valuelen = sfe->valuelen; 525 nargs.hashval = xfs_da_hashname(sfe->nameval, 526 sfe->namelen); 527 nargs.flags = XFS_ATTR_NSP_ONDISK_TO_ARGS(sfe->flags); 528 error = xfs_attr_leaf_lookup_int(bp, &nargs); /* set a->index */ 529 ASSERT(error == ENOATTR); 530 error = xfs_attr_leaf_add(bp, &nargs); 531 ASSERT(error != ENOSPC); 532 if (error) 533 goto out; 534 sfe = XFS_ATTR_SF_NEXTENTRY(sfe); 535 } 536 error = 0; 537 538out: 539 if(bp) 540 xfs_da_buf_done(bp); 541 kmem_free(tmpbuffer); 542 return(error); 543} 544 545STATIC int 546xfs_attr_shortform_compare(const void *a, const void *b) 547{ 548 xfs_attr_sf_sort_t *sa, *sb; 549 550 sa = (xfs_attr_sf_sort_t *)a; 551 sb = (xfs_attr_sf_sort_t *)b; 552 if (sa->hash < sb->hash) { 553 return(-1); 554 } else if (sa->hash > sb->hash) { 555 return(1); 556 } else { 557 return(sa->entno - sb->entno); 558 } 559} 560 561 562#define XFS_ISRESET_CURSOR(cursor) \ 563 (!((cursor)->initted) && !((cursor)->hashval) && \ 564 !((cursor)->blkno) && !((cursor)->offset)) 565/* 566 * Copy out entries of shortform attribute lists for attr_list(). 567 * Shortform attribute lists are not stored in hashval sorted order. 568 * If the output buffer is not large enough to hold them all, then we 569 * we have to calculate each entries' hashvalue and sort them before 570 * we can begin returning them to the user. 571 */ 572/*ARGSUSED*/ 573int 574xfs_attr_shortform_list(xfs_attr_list_context_t *context) 575{ 576 attrlist_cursor_kern_t *cursor; 577 xfs_attr_sf_sort_t *sbuf, *sbp; 578 xfs_attr_shortform_t *sf; 579 xfs_attr_sf_entry_t *sfe; 580 xfs_inode_t *dp; 581 int sbsize, nsbuf, count, i; 582 int error; 583 584 ASSERT(context != NULL); 585 dp = context->dp; 586 ASSERT(dp != NULL); 587 ASSERT(dp->i_afp != NULL); 588 sf = (xfs_attr_shortform_t *)dp->i_afp->if_u1.if_data; 589 ASSERT(sf != NULL); 590 if (!sf->hdr.count) 591 return(0); 592 cursor = context->cursor; 593 ASSERT(cursor != NULL); 594 595 trace_xfs_attr_list_sf(context); 596 597 /* 598 * If the buffer is large enough and the cursor is at the start, 599 * do not bother with sorting since we will return everything in 600 * one buffer and another call using the cursor won't need to be 601 * made. 602 * Note the generous fudge factor of 16 overhead bytes per entry. 603 * If bufsize is zero then put_listent must be a search function 604 * and can just scan through what we have. 605 */ 606 if (context->bufsize == 0 || 607 (XFS_ISRESET_CURSOR(cursor) && 608 (dp->i_afp->if_bytes + sf->hdr.count * 16) < context->bufsize)) { 609 for (i = 0, sfe = &sf->list[0]; i < sf->hdr.count; i++) { 610 error = context->put_listent(context, 611 sfe->flags, 612 sfe->nameval, 613 (int)sfe->namelen, 614 (int)sfe->valuelen, 615 &sfe->nameval[sfe->namelen]); 616 617 /* 618 * Either search callback finished early or 619 * didn't fit it all in the buffer after all. 620 */ 621 if (context->seen_enough) 622 break; 623 624 if (error) 625 return error; 626 sfe = XFS_ATTR_SF_NEXTENTRY(sfe); 627 } 628 trace_xfs_attr_list_sf_all(context); 629 return(0); 630 } 631 632 /* do no more for a search callback */ 633 if (context->bufsize == 0) 634 return 0; 635 636 /* 637 * It didn't all fit, so we have to sort everything on hashval. 638 */ 639 sbsize = sf->hdr.count * sizeof(*sbuf); 640 sbp = sbuf = kmem_alloc(sbsize, KM_SLEEP); 641 642 /* 643 * Scan the attribute list for the rest of the entries, storing 644 * the relevant info from only those that match into a buffer. 645 */ 646 nsbuf = 0; 647 for (i = 0, sfe = &sf->list[0]; i < sf->hdr.count; i++) { 648 if (unlikely( 649 ((char *)sfe < (char *)sf) || 650 ((char *)sfe >= ((char *)sf + dp->i_afp->if_bytes)))) { 651 XFS_CORRUPTION_ERROR("xfs_attr_shortform_list", 652 XFS_ERRLEVEL_LOW, 653 context->dp->i_mount, sfe); 654 kmem_free(sbuf); 655 return XFS_ERROR(EFSCORRUPTED); 656 } 657 658 sbp->entno = i; 659 sbp->hash = xfs_da_hashname(sfe->nameval, sfe->namelen); 660 sbp->name = sfe->nameval; 661 sbp->namelen = sfe->namelen; 662 /* These are bytes, and both on-disk, don't endian-flip */ 663 sbp->valuelen = sfe->valuelen; 664 sbp->flags = sfe->flags; 665 sfe = XFS_ATTR_SF_NEXTENTRY(sfe); 666 sbp++; 667 nsbuf++; 668 } 669 670 /* 671 * Sort the entries on hash then entno. 672 */ 673 xfs_sort(sbuf, nsbuf, sizeof(*sbuf), xfs_attr_shortform_compare); 674 675 /* 676 * Re-find our place IN THE SORTED LIST. 677 */ 678 count = 0; 679 cursor->initted = 1; 680 cursor->blkno = 0; 681 for (sbp = sbuf, i = 0; i < nsbuf; i++, sbp++) { 682 if (sbp->hash == cursor->hashval) { 683 if (cursor->offset == count) { 684 break; 685 } 686 count++; 687 } else if (sbp->hash > cursor->hashval) { 688 break; 689 } 690 } 691 if (i == nsbuf) { 692 kmem_free(sbuf); 693 return(0); 694 } 695 696 /* 697 * Loop putting entries into the user buffer. 698 */ 699 for ( ; i < nsbuf; i++, sbp++) { 700 if (cursor->hashval != sbp->hash) { 701 cursor->hashval = sbp->hash; 702 cursor->offset = 0; 703 } 704 error = context->put_listent(context, 705 sbp->flags, 706 sbp->name, 707 sbp->namelen, 708 sbp->valuelen, 709 &sbp->name[sbp->namelen]); 710 if (error) 711 return error; 712 if (context->seen_enough) 713 break; 714 cursor->offset++; 715 } 716 717 kmem_free(sbuf); 718 return(0); 719} 720 721/* 722 * Check a leaf attribute block to see if all the entries would fit into 723 * a shortform attribute list. 724 */ 725int 726xfs_attr_shortform_allfit(xfs_dabuf_t *bp, xfs_inode_t *dp) 727{ 728 xfs_attr_leafblock_t *leaf; 729 xfs_attr_leaf_entry_t *entry; 730 xfs_attr_leaf_name_local_t *name_loc; 731 int bytes, i; 732 733 leaf = bp->data; 734 ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC); 735 736 entry = &leaf->entries[0]; 737 bytes = sizeof(struct xfs_attr_sf_hdr); 738 for (i = 0; i < be16_to_cpu(leaf->hdr.count); entry++, i++) { 739 if (entry->flags & XFS_ATTR_INCOMPLETE) 740 continue; /* don't copy partial entries */ 741 if (!(entry->flags & XFS_ATTR_LOCAL)) 742 return(0); 743 name_loc = xfs_attr_leaf_name_local(leaf, i); 744 if (name_loc->namelen >= XFS_ATTR_SF_ENTSIZE_MAX) 745 return(0); 746 if (be16_to_cpu(name_loc->valuelen) >= XFS_ATTR_SF_ENTSIZE_MAX) 747 return(0); 748 bytes += sizeof(struct xfs_attr_sf_entry)-1 749 + name_loc->namelen 750 + be16_to_cpu(name_loc->valuelen); 751 } 752 if ((dp->i_mount->m_flags & XFS_MOUNT_ATTR2) && 753 (dp->i_d.di_format != XFS_DINODE_FMT_BTREE) && 754 (bytes == sizeof(struct xfs_attr_sf_hdr))) 755 return(-1); 756 return(xfs_attr_shortform_bytesfit(dp, bytes)); 757} 758 759/* 760 * Convert a leaf attribute list to shortform attribute list 761 */ 762int 763xfs_attr_leaf_to_shortform(xfs_dabuf_t *bp, xfs_da_args_t *args, int forkoff) 764{ 765 xfs_attr_leafblock_t *leaf; 766 xfs_attr_leaf_entry_t *entry; 767 xfs_attr_leaf_name_local_t *name_loc; 768 xfs_da_args_t nargs; 769 xfs_inode_t *dp; 770 char *tmpbuffer; 771 int error, i; 772 773 dp = args->dp; 774 tmpbuffer = kmem_alloc(XFS_LBSIZE(dp->i_mount), KM_SLEEP); 775 ASSERT(tmpbuffer != NULL); 776 777 ASSERT(bp != NULL); 778 memcpy(tmpbuffer, bp->data, XFS_LBSIZE(dp->i_mount)); 779 leaf = (xfs_attr_leafblock_t *)tmpbuffer; 780 ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC); 781 memset(bp->data, 0, XFS_LBSIZE(dp->i_mount)); 782 783 /* 784 * Clean out the prior contents of the attribute list. 785 */ 786 error = xfs_da_shrink_inode(args, 0, bp); 787 if (error) 788 goto out; 789 790 if (forkoff == -1) { 791 ASSERT(dp->i_mount->m_flags & XFS_MOUNT_ATTR2); 792 ASSERT(dp->i_d.di_format != XFS_DINODE_FMT_BTREE); 793 xfs_attr_fork_reset(dp, args->trans); 794 goto out; 795 } 796 797 xfs_attr_shortform_create(args); 798 799 /* 800 * Copy the attributes 801 */ 802 memset((char *)&nargs, 0, sizeof(nargs)); 803 nargs.dp = dp; 804 nargs.firstblock = args->firstblock; 805 nargs.flist = args->flist; 806 nargs.total = args->total; 807 nargs.whichfork = XFS_ATTR_FORK; 808 nargs.trans = args->trans; 809 nargs.op_flags = XFS_DA_OP_OKNOENT; 810 entry = &leaf->entries[0]; 811 for (i = 0; i < be16_to_cpu(leaf->hdr.count); entry++, i++) { 812 if (entry->flags & XFS_ATTR_INCOMPLETE) 813 continue; /* don't copy partial entries */ 814 if (!entry->nameidx) 815 continue; 816 ASSERT(entry->flags & XFS_ATTR_LOCAL); 817 name_loc = xfs_attr_leaf_name_local(leaf, i); 818 nargs.name = name_loc->nameval; 819 nargs.namelen = name_loc->namelen; 820 nargs.value = &name_loc->nameval[nargs.namelen]; 821 nargs.valuelen = be16_to_cpu(name_loc->valuelen); 822 nargs.hashval = be32_to_cpu(entry->hashval); 823 nargs.flags = XFS_ATTR_NSP_ONDISK_TO_ARGS(entry->flags); 824 xfs_attr_shortform_add(&nargs, forkoff); 825 } 826 error = 0; 827 828out: 829 kmem_free(tmpbuffer); 830 return(error); 831} 832 833/* 834 * Convert from using a single leaf to a root node and a leaf. 835 */ 836int 837xfs_attr_leaf_to_node(xfs_da_args_t *args) 838{ 839 xfs_attr_leafblock_t *leaf; 840 xfs_da_intnode_t *node; 841 xfs_inode_t *dp; 842 xfs_dabuf_t *bp1, *bp2; 843 xfs_dablk_t blkno; 844 int error; 845 846 dp = args->dp; 847 bp1 = bp2 = NULL; 848 error = xfs_da_grow_inode(args, &blkno); 849 if (error) 850 goto out; 851 error = xfs_da_read_buf(args->trans, args->dp, 0, -1, &bp1, 852 XFS_ATTR_FORK); 853 if (error) 854 goto out; 855 ASSERT(bp1 != NULL); 856 bp2 = NULL; 857 error = xfs_da_get_buf(args->trans, args->dp, blkno, -1, &bp2, 858 XFS_ATTR_FORK); 859 if (error) 860 goto out; 861 ASSERT(bp2 != NULL); 862 memcpy(bp2->data, bp1->data, XFS_LBSIZE(dp->i_mount)); 863 xfs_da_buf_done(bp1); 864 bp1 = NULL; 865 xfs_da_log_buf(args->trans, bp2, 0, XFS_LBSIZE(dp->i_mount) - 1); 866 867 /* 868 * Set up the new root node. 869 */ 870 error = xfs_da_node_create(args, 0, 1, &bp1, XFS_ATTR_FORK); 871 if (error) 872 goto out; 873 node = bp1->data; 874 leaf = bp2->data; 875 ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC); 876 /* both on-disk, don't endian-flip twice */ 877 node->btree[0].hashval = 878 leaf->entries[be16_to_cpu(leaf->hdr.count)-1 ].hashval; 879 node->btree[0].before = cpu_to_be32(blkno); 880 node->hdr.count = cpu_to_be16(1); 881 xfs_da_log_buf(args->trans, bp1, 0, XFS_LBSIZE(dp->i_mount) - 1); 882 error = 0; 883out: 884 if (bp1) 885 xfs_da_buf_done(bp1); 886 if (bp2) 887 xfs_da_buf_done(bp2); 888 return(error); 889} 890 891 892/*======================================================================== 893 * Routines used for growing the Btree. 894 *========================================================================*/ 895 896/* 897 * Create the initial contents of a leaf attribute list 898 * or a leaf in a node attribute list. 899 */ 900STATIC int 901xfs_attr_leaf_create(xfs_da_args_t *args, xfs_dablk_t blkno, xfs_dabuf_t **bpp) 902{ 903 xfs_attr_leafblock_t *leaf; 904 xfs_attr_leaf_hdr_t *hdr; 905 xfs_inode_t *dp; 906 xfs_dabuf_t *bp; 907 int error; 908 909 dp = args->dp; 910 ASSERT(dp != NULL); 911 error = xfs_da_get_buf(args->trans, args->dp, blkno, -1, &bp, 912 XFS_ATTR_FORK); 913 if (error) 914 return(error); 915 ASSERT(bp != NULL); 916 leaf = bp->data; 917 memset((char *)leaf, 0, XFS_LBSIZE(dp->i_mount)); 918 hdr = &leaf->hdr; 919 hdr->info.magic = cpu_to_be16(XFS_ATTR_LEAF_MAGIC); 920 hdr->firstused = cpu_to_be16(XFS_LBSIZE(dp->i_mount)); 921 if (!hdr->firstused) { 922 hdr->firstused = cpu_to_be16( 923 XFS_LBSIZE(dp->i_mount) - XFS_ATTR_LEAF_NAME_ALIGN); 924 } 925 926 hdr->freemap[0].base = cpu_to_be16(sizeof(xfs_attr_leaf_hdr_t)); 927 hdr->freemap[0].size = cpu_to_be16(be16_to_cpu(hdr->firstused) - 928 sizeof(xfs_attr_leaf_hdr_t)); 929 930 xfs_da_log_buf(args->trans, bp, 0, XFS_LBSIZE(dp->i_mount) - 1); 931 932 *bpp = bp; 933 return(0); 934} 935 936/* 937 * Split the leaf node, rebalance, then add the new entry. 938 */ 939int 940xfs_attr_leaf_split(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk, 941 xfs_da_state_blk_t *newblk) 942{ 943 xfs_dablk_t blkno; 944 int error; 945 946 /* 947 * Allocate space for a new leaf node. 948 */ 949 ASSERT(oldblk->magic == XFS_ATTR_LEAF_MAGIC); 950 error = xfs_da_grow_inode(state->args, &blkno); 951 if (error) 952 return(error); 953 error = xfs_attr_leaf_create(state->args, blkno, &newblk->bp); 954 if (error) 955 return(error); 956 newblk->blkno = blkno; 957 newblk->magic = XFS_ATTR_LEAF_MAGIC; 958 959 /* 960 * Rebalance the entries across the two leaves. 961 * NOTE: rebalance() currently depends on the 2nd block being empty. 962 */ 963 xfs_attr_leaf_rebalance(state, oldblk, newblk); 964 error = xfs_da_blk_link(state, oldblk, newblk); 965 if (error) 966 return(error); 967 968 /* 969 * Save info on "old" attribute for "atomic rename" ops, leaf_add() 970 * modifies the index/blkno/rmtblk/rmtblkcnt fields to show the 971 * "new" attrs info. Will need the "old" info to remove it later. 972 * 973 * Insert the "new" entry in the correct block. 974 */ 975 if (state->inleaf) 976 error = xfs_attr_leaf_add(oldblk->bp, state->args); 977 else 978 error = xfs_attr_leaf_add(newblk->bp, state->args); 979 980 /* 981 * Update last hashval in each block since we added the name. 982 */ 983 oldblk->hashval = xfs_attr_leaf_lasthash(oldblk->bp, NULL); 984 newblk->hashval = xfs_attr_leaf_lasthash(newblk->bp, NULL); 985 return(error); 986} 987 988/* 989 * Add a name to the leaf attribute list structure. 990 */ 991int 992xfs_attr_leaf_add(xfs_dabuf_t *bp, xfs_da_args_t *args) 993{ 994 xfs_attr_leafblock_t *leaf; 995 xfs_attr_leaf_hdr_t *hdr; 996 xfs_attr_leaf_map_t *map; 997 int tablesize, entsize, sum, tmp, i; 998 999 leaf = bp->data; 1000 ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC); 1001 ASSERT((args->index >= 0) 1002 && (args->index <= be16_to_cpu(leaf->hdr.count))); 1003 hdr = &leaf->hdr; 1004 entsize = xfs_attr_leaf_newentsize(args->namelen, args->valuelen, 1005 args->trans->t_mountp->m_sb.sb_blocksize, NULL); 1006 1007 /* 1008 * Search through freemap for first-fit on new name length. 1009 * (may need to figure in size of entry struct too) 1010 */ 1011 tablesize = (be16_to_cpu(hdr->count) + 1) 1012 * sizeof(xfs_attr_leaf_entry_t) 1013 + sizeof(xfs_attr_leaf_hdr_t); 1014 map = &hdr->freemap[XFS_ATTR_LEAF_MAPSIZE-1]; 1015 for (sum = 0, i = XFS_ATTR_LEAF_MAPSIZE-1; i >= 0; map--, i--) { 1016 if (tablesize > be16_to_cpu(hdr->firstused)) { 1017 sum += be16_to_cpu(map->size); 1018 continue; 1019 } 1020 if (!map->size) 1021 continue; /* no space in this map */ 1022 tmp = entsize; 1023 if (be16_to_cpu(map->base) < be16_to_cpu(hdr->firstused)) 1024 tmp += sizeof(xfs_attr_leaf_entry_t); 1025 if (be16_to_cpu(map->size) >= tmp) { 1026 tmp = xfs_attr_leaf_add_work(bp, args, i); 1027 return(tmp); 1028 } 1029 sum += be16_to_cpu(map->size); 1030 } 1031 1032 /* 1033 * If there are no holes in the address space of the block, 1034 * and we don't have enough freespace, then compaction will do us 1035 * no good and we should just give up. 1036 */ 1037 if (!hdr->holes && (sum < entsize)) 1038 return(XFS_ERROR(ENOSPC)); 1039 1040 /* 1041 * Compact the entries to coalesce free space. 1042 * This may change the hdr->count via dropping INCOMPLETE entries. 1043 */ 1044 xfs_attr_leaf_compact(args->trans, bp); 1045 1046 /* 1047 * After compaction, the block is guaranteed to have only one 1048 * free region, in freemap[0]. If it is not big enough, give up. 1049 */ 1050 if (be16_to_cpu(hdr->freemap[0].size) 1051 < (entsize + sizeof(xfs_attr_leaf_entry_t))) 1052 return(XFS_ERROR(ENOSPC)); 1053 1054 return(xfs_attr_leaf_add_work(bp, args, 0)); 1055} 1056 1057/* 1058 * Add a name to a leaf attribute list structure. 1059 */ 1060STATIC int 1061xfs_attr_leaf_add_work(xfs_dabuf_t *bp, xfs_da_args_t *args, int mapindex) 1062{ 1063 xfs_attr_leafblock_t *leaf; 1064 xfs_attr_leaf_hdr_t *hdr; 1065 xfs_attr_leaf_entry_t *entry; 1066 xfs_attr_leaf_name_local_t *name_loc; 1067 xfs_attr_leaf_name_remote_t *name_rmt; 1068 xfs_attr_leaf_map_t *map; 1069 xfs_mount_t *mp; 1070 int tmp, i; 1071 1072 leaf = bp->data; 1073 ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC); 1074 hdr = &leaf->hdr; 1075 ASSERT((mapindex >= 0) && (mapindex < XFS_ATTR_LEAF_MAPSIZE)); 1076 ASSERT((args->index >= 0) && (args->index <= be16_to_cpu(hdr->count))); 1077 1078 /* 1079 * Force open some space in the entry array and fill it in. 1080 */ 1081 entry = &leaf->entries[args->index]; 1082 if (args->index < be16_to_cpu(hdr->count)) { 1083 tmp = be16_to_cpu(hdr->count) - args->index; 1084 tmp *= sizeof(xfs_attr_leaf_entry_t); 1085 memmove((char *)(entry+1), (char *)entry, tmp); 1086 xfs_da_log_buf(args->trans, bp, 1087 XFS_DA_LOGRANGE(leaf, entry, tmp + sizeof(*entry))); 1088 } 1089 be16_add_cpu(&hdr->count, 1); 1090 1091 /* 1092 * Allocate space for the new string (at the end of the run). 1093 */ 1094 map = &hdr->freemap[mapindex]; 1095 mp = args->trans->t_mountp; 1096 ASSERT(be16_to_cpu(map->base) < XFS_LBSIZE(mp)); 1097 ASSERT((be16_to_cpu(map->base) & 0x3) == 0); 1098 ASSERT(be16_to_cpu(map->size) >= 1099 xfs_attr_leaf_newentsize(args->namelen, args->valuelen, 1100 mp->m_sb.sb_blocksize, NULL)); 1101 ASSERT(be16_to_cpu(map->size) < XFS_LBSIZE(mp)); 1102 ASSERT((be16_to_cpu(map->size) & 0x3) == 0); 1103 be16_add_cpu(&map->size, 1104 -xfs_attr_leaf_newentsize(args->namelen, args->valuelen, 1105 mp->m_sb.sb_blocksize, &tmp)); 1106 entry->nameidx = cpu_to_be16(be16_to_cpu(map->base) + 1107 be16_to_cpu(map->size)); 1108 entry->hashval = cpu_to_be32(args->hashval); 1109 entry->flags = tmp ? XFS_ATTR_LOCAL : 0; 1110 entry->flags |= XFS_ATTR_NSP_ARGS_TO_ONDISK(args->flags); 1111 if (args->op_flags & XFS_DA_OP_RENAME) { 1112 entry->flags |= XFS_ATTR_INCOMPLETE; 1113 if ((args->blkno2 == args->blkno) && 1114 (args->index2 <= args->index)) { 1115 args->index2++; 1116 } 1117 } 1118 xfs_da_log_buf(args->trans, bp, 1119 XFS_DA_LOGRANGE(leaf, entry, sizeof(*entry))); 1120 ASSERT((args->index == 0) || 1121 (be32_to_cpu(entry->hashval) >= be32_to_cpu((entry-1)->hashval))); 1122 ASSERT((args->index == be16_to_cpu(hdr->count)-1) || 1123 (be32_to_cpu(entry->hashval) <= be32_to_cpu((entry+1)->hashval))); 1124 1125 /* 1126 * Copy the attribute name and value into the new space. 1127 * 1128 * For "remote" attribute values, simply note that we need to 1129 * allocate space for the "remote" value. We can't actually 1130 * allocate the extents in this transaction, and we can't decide 1131 * which blocks they should be as we might allocate more blocks 1132 * as part of this transaction (a split operation for example). 1133 */ 1134 if (entry->flags & XFS_ATTR_LOCAL) { 1135 name_loc = xfs_attr_leaf_name_local(leaf, args->index); 1136 name_loc->namelen = args->namelen; 1137 name_loc->valuelen = cpu_to_be16(args->valuelen); 1138 memcpy((char *)name_loc->nameval, args->name, args->namelen); 1139 memcpy((char *)&name_loc->nameval[args->namelen], args->value, 1140 be16_to_cpu(name_loc->valuelen)); 1141 } else { 1142 name_rmt = xfs_attr_leaf_name_remote(leaf, args->index); 1143 name_rmt->namelen = args->namelen; 1144 memcpy((char *)name_rmt->name, args->name, args->namelen); 1145 entry->flags |= XFS_ATTR_INCOMPLETE; 1146 /* just in case */ 1147 name_rmt->valuelen = 0; 1148 name_rmt->valueblk = 0; 1149 args->rmtblkno = 1; 1150 args->rmtblkcnt = XFS_B_TO_FSB(mp, args->valuelen); 1151 } 1152 xfs_da_log_buf(args->trans, bp, 1153 XFS_DA_LOGRANGE(leaf, xfs_attr_leaf_name(leaf, args->index), 1154 xfs_attr_leaf_entsize(leaf, args->index))); 1155 1156 /* 1157 * Update the control info for this leaf node 1158 */ 1159 if (be16_to_cpu(entry->nameidx) < be16_to_cpu(hdr->firstused)) { 1160 /* both on-disk, don't endian-flip twice */ 1161 hdr->firstused = entry->nameidx; 1162 } 1163 ASSERT(be16_to_cpu(hdr->firstused) >= 1164 ((be16_to_cpu(hdr->count) * sizeof(*entry)) + sizeof(*hdr))); 1165 tmp = (be16_to_cpu(hdr->count)-1) * sizeof(xfs_attr_leaf_entry_t) 1166 + sizeof(xfs_attr_leaf_hdr_t); 1167 map = &hdr->freemap[0]; 1168 for (i = 0; i < XFS_ATTR_LEAF_MAPSIZE; map++, i++) { 1169 if (be16_to_cpu(map->base) == tmp) { 1170 be16_add_cpu(&map->base, sizeof(xfs_attr_leaf_entry_t)); 1171 be16_add_cpu(&map->size, 1172 -((int)sizeof(xfs_attr_leaf_entry_t))); 1173 } 1174 } 1175 be16_add_cpu(&hdr->usedbytes, xfs_attr_leaf_entsize(leaf, args->index)); 1176 xfs_da_log_buf(args->trans, bp, 1177 XFS_DA_LOGRANGE(leaf, hdr, sizeof(*hdr))); 1178 return(0); 1179} 1180 1181/* 1182 * Garbage collect a leaf attribute list block by copying it to a new buffer. 1183 */ 1184STATIC void 1185xfs_attr_leaf_compact(xfs_trans_t *trans, xfs_dabuf_t *bp) 1186{ 1187 xfs_attr_leafblock_t *leaf_s, *leaf_d; 1188 xfs_attr_leaf_hdr_t *hdr_s, *hdr_d; 1189 xfs_mount_t *mp; 1190 char *tmpbuffer; 1191 1192 mp = trans->t_mountp; 1193 tmpbuffer = kmem_alloc(XFS_LBSIZE(mp), KM_SLEEP); 1194 ASSERT(tmpbuffer != NULL); 1195 memcpy(tmpbuffer, bp->data, XFS_LBSIZE(mp)); 1196 memset(bp->data, 0, XFS_LBSIZE(mp)); 1197 1198 /* 1199 * Copy basic information 1200 */ 1201 leaf_s = (xfs_attr_leafblock_t *)tmpbuffer; 1202 leaf_d = bp->data; 1203 hdr_s = &leaf_s->hdr; 1204 hdr_d = &leaf_d->hdr; 1205 hdr_d->info = hdr_s->info; /* struct copy */ 1206 hdr_d->firstused = cpu_to_be16(XFS_LBSIZE(mp)); 1207 /* handle truncation gracefully */ 1208 if (!hdr_d->firstused) { 1209 hdr_d->firstused = cpu_to_be16( 1210 XFS_LBSIZE(mp) - XFS_ATTR_LEAF_NAME_ALIGN); 1211 } 1212 hdr_d->usedbytes = 0; 1213 hdr_d->count = 0; 1214 hdr_d->holes = 0; 1215 hdr_d->freemap[0].base = cpu_to_be16(sizeof(xfs_attr_leaf_hdr_t)); 1216 hdr_d->freemap[0].size = cpu_to_be16(be16_to_cpu(hdr_d->firstused) - 1217 sizeof(xfs_attr_leaf_hdr_t)); 1218 1219 /* 1220 * Copy all entry's in the same (sorted) order, 1221 * but allocate name/value pairs packed and in sequence. 1222 */ 1223 xfs_attr_leaf_moveents(leaf_s, 0, leaf_d, 0, 1224 be16_to_cpu(hdr_s->count), mp); 1225 xfs_da_log_buf(trans, bp, 0, XFS_LBSIZE(mp) - 1); 1226 1227 kmem_free(tmpbuffer); 1228} 1229 1230/* 1231 * Redistribute the attribute list entries between two leaf nodes, 1232 * taking into account the size of the new entry. 1233 * 1234 * NOTE: if new block is empty, then it will get the upper half of the 1235 * old block. At present, all (one) callers pass in an empty second block. 1236 * 1237 * This code adjusts the args->index/blkno and args->index2/blkno2 fields 1238 * to match what it is doing in splitting the attribute leaf block. Those 1239 * values are used in "atomic rename" operations on attributes. Note that 1240 * the "new" and "old" values can end up in different blocks. 1241 */ 1242STATIC void 1243xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, 1244 xfs_da_state_blk_t *blk2) 1245{ 1246 xfs_da_args_t *args; 1247 xfs_da_state_blk_t *tmp_blk; 1248 xfs_attr_leafblock_t *leaf1, *leaf2; 1249 xfs_attr_leaf_hdr_t *hdr1, *hdr2; 1250 int count, totallen, max, space, swap; 1251 1252 /* 1253 * Set up environment. 1254 */ 1255 ASSERT(blk1->magic == XFS_ATTR_LEAF_MAGIC); 1256 ASSERT(blk2->magic == XFS_ATTR_LEAF_MAGIC); 1257 leaf1 = blk1->bp->data; 1258 leaf2 = blk2->bp->data; 1259 ASSERT(be16_to_cpu(leaf1->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC); 1260 ASSERT(be16_to_cpu(leaf2->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC); 1261 args = state->args; 1262 1263 /* 1264 * Check ordering of blocks, reverse if it makes things simpler. 1265 * 1266 * NOTE: Given that all (current) callers pass in an empty 1267 * second block, this code should never set "swap". 1268 */ 1269 swap = 0; 1270 if (xfs_attr_leaf_order(blk1->bp, blk2->bp)) { 1271 tmp_blk = blk1; 1272 blk1 = blk2; 1273 blk2 = tmp_blk; 1274 leaf1 = blk1->bp->data; 1275 leaf2 = blk2->bp->data; 1276 swap = 1; 1277 } 1278 hdr1 = &leaf1->hdr; 1279 hdr2 = &leaf2->hdr; 1280 1281 /* 1282 * Examine entries until we reduce the absolute difference in 1283 * byte usage between the two blocks to a minimum. Then get 1284 * the direction to copy and the number of elements to move. 1285 * 1286 * "inleaf" is true if the new entry should be inserted into blk1. 1287 * If "swap" is also true, then reverse the sense of "inleaf". 1288 */ 1289 state->inleaf = xfs_attr_leaf_figure_balance(state, blk1, blk2, 1290 &count, &totallen); 1291 if (swap) 1292 state->inleaf = !state->inleaf; 1293 1294 /* 1295 * Move any entries required from leaf to leaf: 1296 */ 1297 if (count < be16_to_cpu(hdr1->count)) { 1298 /* 1299 * Figure the total bytes to be added to the destination leaf. 1300 */ 1301 /* number entries being moved */ 1302 count = be16_to_cpu(hdr1->count) - count; 1303 space = be16_to_cpu(hdr1->usedbytes) - totallen; 1304 space += count * sizeof(xfs_attr_leaf_entry_t); 1305 1306 /* 1307 * leaf2 is the destination, compact it if it looks tight. 1308 */ 1309 max = be16_to_cpu(hdr2->firstused) 1310 - sizeof(xfs_attr_leaf_hdr_t); 1311 max -= be16_to_cpu(hdr2->count) * sizeof(xfs_attr_leaf_entry_t); 1312 if (space > max) { 1313 xfs_attr_leaf_compact(args->trans, blk2->bp); 1314 } 1315 1316 /* 1317 * Move high entries from leaf1 to low end of leaf2. 1318 */ 1319 xfs_attr_leaf_moveents(leaf1, be16_to_cpu(hdr1->count) - count, 1320 leaf2, 0, count, state->mp); 1321 1322 xfs_da_log_buf(args->trans, blk1->bp, 0, state->blocksize-1); 1323 xfs_da_log_buf(args->trans, blk2->bp, 0, state->blocksize-1); 1324 } else if (count > be16_to_cpu(hdr1->count)) { 1325 /* 1326 * I assert that since all callers pass in an empty 1327 * second buffer, this code should never execute. 1328 */ 1329 1330 /* 1331 * Figure the total bytes to be added to the destination leaf. 1332 */ 1333 /* number entries being moved */ 1334 count -= be16_to_cpu(hdr1->count); 1335 space = totallen - be16_to_cpu(hdr1->usedbytes); 1336 space += count * sizeof(xfs_attr_leaf_entry_t); 1337 1338 /* 1339 * leaf1 is the destination, compact it if it looks tight. 1340 */ 1341 max = be16_to_cpu(hdr1->firstused) 1342 - sizeof(xfs_attr_leaf_hdr_t); 1343 max -= be16_to_cpu(hdr1->count) * sizeof(xfs_attr_leaf_entry_t); 1344 if (space > max) { 1345 xfs_attr_leaf_compact(args->trans, blk1->bp); 1346 } 1347 1348 /* 1349 * Move low entries from leaf2 to high end of leaf1. 1350 */ 1351 xfs_attr_leaf_moveents(leaf2, 0, leaf1, 1352 be16_to_cpu(hdr1->count), count, state->mp); 1353 1354 xfs_da_log_buf(args->trans, blk1->bp, 0, state->blocksize-1); 1355 xfs_da_log_buf(args->trans, blk2->bp, 0, state->blocksize-1); 1356 } 1357 1358 /* 1359 * Copy out last hashval in each block for B-tree code. 1360 */ 1361 blk1->hashval = be32_to_cpu( 1362 leaf1->entries[be16_to_cpu(leaf1->hdr.count)-1].hashval); 1363 blk2->hashval = be32_to_cpu( 1364 leaf2->entries[be16_to_cpu(leaf2->hdr.count)-1].hashval); 1365 1366 /* 1367 * Adjust the expected index for insertion. 1368 * NOTE: this code depends on the (current) situation that the 1369 * second block was originally empty. 1370 * 1371 * If the insertion point moved to the 2nd block, we must adjust 1372 * the index. We must also track the entry just following the 1373 * new entry for use in an "atomic rename" operation, that entry 1374 * is always the "old" entry and the "new" entry is what we are 1375 * inserting. The index/blkno fields refer to the "old" entry, 1376 * while the index2/blkno2 fields refer to the "new" entry. 1377 */ 1378 if (blk1->index > be16_to_cpu(leaf1->hdr.count)) { 1379 ASSERT(state->inleaf == 0); 1380 blk2->index = blk1->index - be16_to_cpu(leaf1->hdr.count); 1381 args->index = args->index2 = blk2->index; 1382 args->blkno = args->blkno2 = blk2->blkno; 1383 } else if (blk1->index == be16_to_cpu(leaf1->hdr.count)) { 1384 if (state->inleaf) { 1385 args->index = blk1->index; 1386 args->blkno = blk1->blkno; 1387 args->index2 = 0; 1388 args->blkno2 = blk2->blkno; 1389 } else { 1390 blk2->index = blk1->index 1391 - be16_to_cpu(leaf1->hdr.count); 1392 args->index = args->index2 = blk2->index; 1393 args->blkno = args->blkno2 = blk2->blkno; 1394 } 1395 } else { 1396 ASSERT(state->inleaf == 1); 1397 args->index = args->index2 = blk1->index; 1398 args->blkno = args->blkno2 = blk1->blkno; 1399 } 1400} 1401 1402/* 1403 * Examine entries until we reduce the absolute difference in 1404 * byte usage between the two blocks to a minimum. 1405 * GROT: Is this really necessary? With other than a 512 byte blocksize, 1406 * GROT: there will always be enough room in either block for a new entry. 1407 * GROT: Do a double-split for this case? 1408 */ 1409STATIC int 1410xfs_attr_leaf_figure_balance(xfs_da_state_t *state, 1411 xfs_da_state_blk_t *blk1, 1412 xfs_da_state_blk_t *blk2, 1413 int *countarg, int *usedbytesarg) 1414{ 1415 xfs_attr_leafblock_t *leaf1, *leaf2; 1416 xfs_attr_leaf_hdr_t *hdr1, *hdr2; 1417 xfs_attr_leaf_entry_t *entry; 1418 int count, max, index, totallen, half; 1419 int lastdelta, foundit, tmp; 1420 1421 /* 1422 * Set up environment. 1423 */ 1424 leaf1 = blk1->bp->data; 1425 leaf2 = blk2->bp->data; 1426 hdr1 = &leaf1->hdr; 1427 hdr2 = &leaf2->hdr; 1428 foundit = 0; 1429 totallen = 0; 1430 1431 /* 1432 * Examine entries until we reduce the absolute difference in 1433 * byte usage between the two blocks to a minimum. 1434 */ 1435 max = be16_to_cpu(hdr1->count) + be16_to_cpu(hdr2->count); 1436 half = (max+1) * sizeof(*entry); 1437 half += be16_to_cpu(hdr1->usedbytes) + 1438 be16_to_cpu(hdr2->usedbytes) + 1439 xfs_attr_leaf_newentsize( 1440 state->args->namelen, 1441 state->args->valuelen, 1442 state->blocksize, NULL); 1443 half /= 2; 1444 lastdelta = state->blocksize; 1445 entry = &leaf1->entries[0]; 1446 for (count = index = 0; count < max; entry++, index++, count++) { 1447 1448#define XFS_ATTR_ABS(A) (((A) < 0) ? -(A) : (A)) 1449 /* 1450 * The new entry is in the first block, account for it. 1451 */ 1452 if (count == blk1->index) { 1453 tmp = totallen + sizeof(*entry) + 1454 xfs_attr_leaf_newentsize( 1455 state->args->namelen, 1456 state->args->valuelen, 1457 state->blocksize, NULL); 1458 if (XFS_ATTR_ABS(half - tmp) > lastdelta) 1459 break; 1460 lastdelta = XFS_ATTR_ABS(half - tmp); 1461 totallen = tmp; 1462 foundit = 1; 1463 } 1464 1465 /* 1466 * Wrap around into the second block if necessary. 1467 */ 1468 if (count == be16_to_cpu(hdr1->count)) { 1469 leaf1 = leaf2; 1470 entry = &leaf1->entries[0]; 1471 index = 0; 1472 } 1473 1474 /* 1475 * Figure out if next leaf entry would be too much. 1476 */ 1477 tmp = totallen + sizeof(*entry) + xfs_attr_leaf_entsize(leaf1, 1478 index); 1479 if (XFS_ATTR_ABS(half - tmp) > lastdelta) 1480 break; 1481 lastdelta = XFS_ATTR_ABS(half - tmp); 1482 totallen = tmp; 1483#undef XFS_ATTR_ABS 1484 } 1485 1486 /* 1487 * Calculate the number of usedbytes that will end up in lower block. 1488 * If new entry not in lower block, fix up the count. 1489 */ 1490 totallen -= count * sizeof(*entry); 1491 if (foundit) { 1492 totallen -= sizeof(*entry) + 1493 xfs_attr_leaf_newentsize( 1494 state->args->namelen, 1495 state->args->valuelen, 1496 state->blocksize, NULL); 1497 } 1498 1499 *countarg = count; 1500 *usedbytesarg = totallen; 1501 return(foundit); 1502} 1503 1504/*======================================================================== 1505 * Routines used for shrinking the Btree. 1506 *========================================================================*/ 1507 1508/* 1509 * Check a leaf block and its neighbors to see if the block should be 1510 * collapsed into one or the other neighbor. Always keep the block 1511 * with the smaller block number. 1512 * If the current block is over 50% full, don't try to join it, return 0. 1513 * If the block is empty, fill in the state structure and return 2. 1514 * If it can be collapsed, fill in the state structure and return 1. 1515 * If nothing can be done, return 0. 1516 * 1517 * GROT: allow for INCOMPLETE entries in calculation. 1518 */ 1519int 1520xfs_attr_leaf_toosmall(xfs_da_state_t *state, int *action) 1521{ 1522 xfs_attr_leafblock_t *leaf; 1523 xfs_da_state_blk_t *blk; 1524 xfs_da_blkinfo_t *info; 1525 int count, bytes, forward, error, retval, i; 1526 xfs_dablk_t blkno; 1527 xfs_dabuf_t *bp; 1528 1529 /* 1530 * Check for the degenerate case of the block being over 50% full. 1531 * If so, it's not worth even looking to see if we might be able 1532 * to coalesce with a sibling. 1533 */ 1534 blk = &state->path.blk[ state->path.active-1 ]; 1535 info = blk->bp->data; 1536 ASSERT(be16_to_cpu(info->magic) == XFS_ATTR_LEAF_MAGIC); 1537 leaf = (xfs_attr_leafblock_t *)info; 1538 count = be16_to_cpu(leaf->hdr.count); 1539 bytes = sizeof(xfs_attr_leaf_hdr_t) + 1540 count * sizeof(xfs_attr_leaf_entry_t) + 1541 be16_to_cpu(leaf->hdr.usedbytes); 1542 if (bytes > (state->blocksize >> 1)) { 1543 *action = 0; /* blk over 50%, don't try to join */ 1544 return(0); 1545 } 1546 1547 /* 1548 * Check for the degenerate case of the block being empty. 1549 * If the block is empty, we'll simply delete it, no need to 1550 * coalesce it with a sibling block. We choose (arbitrarily) 1551 * to merge with the forward block unless it is NULL. 1552 */ 1553 if (count == 0) { 1554 /* 1555 * Make altpath point to the block we want to keep and 1556 * path point to the block we want to drop (this one). 1557 */ 1558 forward = (info->forw != 0); 1559 memcpy(&state->altpath, &state->path, sizeof(state->path)); 1560 error = xfs_da_path_shift(state, &state->altpath, forward, 1561 0, &retval); 1562 if (error) 1563 return(error); 1564 if (retval) { 1565 *action = 0; 1566 } else { 1567 *action = 2; 1568 } 1569 return(0); 1570 } 1571 1572 /* 1573 * Examine each sibling block to see if we can coalesce with 1574 * at least 25% free space to spare. We need to figure out 1575 * whether to merge with the forward or the backward block. 1576 * We prefer coalescing with the lower numbered sibling so as 1577 * to shrink an attribute list over time. 1578 */ 1579 /* start with smaller blk num */ 1580 forward = (be32_to_cpu(info->forw) < be32_to_cpu(info->back)); 1581 for (i = 0; i < 2; forward = !forward, i++) { 1582 if (forward) 1583 blkno = be32_to_cpu(info->forw); 1584 else 1585 blkno = be32_to_cpu(info->back); 1586 if (blkno == 0) 1587 continue; 1588 error = xfs_da_read_buf(state->args->trans, state->args->dp, 1589 blkno, -1, &bp, XFS_ATTR_FORK); 1590 if (error) 1591 return(error); 1592 ASSERT(bp != NULL); 1593 1594 leaf = (xfs_attr_leafblock_t *)info; 1595 count = be16_to_cpu(leaf->hdr.count); 1596 bytes = state->blocksize - (state->blocksize>>2); 1597 bytes -= be16_to_cpu(leaf->hdr.usedbytes); 1598 leaf = bp->data; 1599 ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC); 1600 count += be16_to_cpu(leaf->hdr.count); 1601 bytes -= be16_to_cpu(leaf->hdr.usedbytes); 1602 bytes -= count * sizeof(xfs_attr_leaf_entry_t); 1603 bytes -= sizeof(xfs_attr_leaf_hdr_t); 1604 xfs_da_brelse(state->args->trans, bp); 1605 if (bytes >= 0) 1606 break; /* fits with at least 25% to spare */ 1607 } 1608 if (i >= 2) { 1609 *action = 0; 1610 return(0); 1611 } 1612 1613 /* 1614 * Make altpath point to the block we want to keep (the lower 1615 * numbered block) and path point to the block we want to drop. 1616 */ 1617 memcpy(&state->altpath, &state->path, sizeof(state->path)); 1618 if (blkno < blk->blkno) { 1619 error = xfs_da_path_shift(state, &state->altpath, forward, 1620 0, &retval); 1621 } else { 1622 error = xfs_da_path_shift(state, &state->path, forward, 1623 0, &retval); 1624 } 1625 if (error) 1626 return(error); 1627 if (retval) { 1628 *action = 0; 1629 } else { 1630 *action = 1; 1631 } 1632 return(0); 1633} 1634 1635/* 1636 * Remove a name from the leaf attribute list structure. 1637 * 1638 * Return 1 if leaf is less than 37% full, 0 if >= 37% full. 1639 * If two leaves are 37% full, when combined they will leave 25% free. 1640 */ 1641int 1642xfs_attr_leaf_remove(xfs_dabuf_t *bp, xfs_da_args_t *args) 1643{ 1644 xfs_attr_leafblock_t *leaf; 1645 xfs_attr_leaf_hdr_t *hdr; 1646 xfs_attr_leaf_map_t *map; 1647 xfs_attr_leaf_entry_t *entry; 1648 int before, after, smallest, entsize; 1649 int tablesize, tmp, i; 1650 xfs_mount_t *mp; 1651 1652 leaf = bp->data; 1653 ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC); 1654 hdr = &leaf->hdr; 1655 mp = args->trans->t_mountp; 1656 ASSERT((be16_to_cpu(hdr->count) > 0) 1657 && (be16_to_cpu(hdr->count) < (XFS_LBSIZE(mp)/8))); 1658 ASSERT((args->index >= 0) 1659 && (args->index < be16_to_cpu(hdr->count))); 1660 ASSERT(be16_to_cpu(hdr->firstused) >= 1661 ((be16_to_cpu(hdr->count) * sizeof(*entry)) + sizeof(*hdr))); 1662 entry = &leaf->entries[args->index]; 1663 ASSERT(be16_to_cpu(entry->nameidx) >= be16_to_cpu(hdr->firstused)); 1664 ASSERT(be16_to_cpu(entry->nameidx) < XFS_LBSIZE(mp)); 1665 1666 /* 1667 * Scan through free region table: 1668 * check for adjacency of free'd entry with an existing one, 1669 * find smallest free region in case we need to replace it, 1670 * adjust any map that borders the entry table, 1671 */ 1672 tablesize = be16_to_cpu(hdr->count) * sizeof(xfs_attr_leaf_entry_t) 1673 + sizeof(xfs_attr_leaf_hdr_t); 1674 map = &hdr->freemap[0]; 1675 tmp = be16_to_cpu(map->size); 1676 before = after = -1; 1677 smallest = XFS_ATTR_LEAF_MAPSIZE - 1; 1678 entsize = xfs_attr_leaf_entsize(leaf, args->index); 1679 for (i = 0; i < XFS_ATTR_LEAF_MAPSIZE; map++, i++) { 1680 ASSERT(be16_to_cpu(map->base) < XFS_LBSIZE(mp)); 1681 ASSERT(be16_to_cpu(map->size) < XFS_LBSIZE(mp)); 1682 if (be16_to_cpu(map->base) == tablesize) { 1683 be16_add_cpu(&map->base, 1684 -((int)sizeof(xfs_attr_leaf_entry_t))); 1685 be16_add_cpu(&map->size, sizeof(xfs_attr_leaf_entry_t)); 1686 } 1687 1688 if ((be16_to_cpu(map->base) + be16_to_cpu(map->size)) 1689 == be16_to_cpu(entry->nameidx)) { 1690 before = i; 1691 } else if (be16_to_cpu(map->base) 1692 == (be16_to_cpu(entry->nameidx) + entsize)) { 1693 after = i; 1694 } else if (be16_to_cpu(map->size) < tmp) { 1695 tmp = be16_to_cpu(map->size); 1696 smallest = i; 1697 } 1698 } 1699 1700 /* 1701 * Coalesce adjacent freemap regions, 1702 * or replace the smallest region. 1703 */ 1704 if ((before >= 0) || (after >= 0)) { 1705 if ((before >= 0) && (after >= 0)) { 1706 map = &hdr->freemap[before]; 1707 be16_add_cpu(&map->size, entsize); 1708 be16_add_cpu(&map->size, 1709 be16_to_cpu(hdr->freemap[after].size)); 1710 hdr->freemap[after].base = 0; 1711 hdr->freemap[after].size = 0; 1712 } else if (before >= 0) { 1713 map = &hdr->freemap[before]; 1714 be16_add_cpu(&map->size, entsize); 1715 } else { 1716 map = &hdr->freemap[after]; 1717 /* both on-disk, don't endian flip twice */ 1718 map->base = entry->nameidx; 1719 be16_add_cpu(&map->size, entsize); 1720 } 1721 } else { 1722 /* 1723 * Replace smallest region (if it is smaller than free'd entry) 1724 */ 1725 map = &hdr->freemap[smallest]; 1726 if (be16_to_cpu(map->size) < entsize) { 1727 map->base = cpu_to_be16(be16_to_cpu(entry->nameidx)); 1728 map->size = cpu_to_be16(entsize); 1729 } 1730 } 1731 1732 /* 1733 * Did we remove the first entry? 1734 */ 1735 if (be16_to_cpu(entry->nameidx) == be16_to_cpu(hdr->firstused)) 1736 smallest = 1; 1737 else 1738 smallest = 0; 1739 1740 /* 1741 * Compress the remaining entries and zero out the removed stuff. 1742 */ 1743 memset(xfs_attr_leaf_name(leaf, args->index), 0, entsize); 1744 be16_add_cpu(&hdr->usedbytes, -entsize); 1745 xfs_da_log_buf(args->trans, bp, 1746 XFS_DA_LOGRANGE(leaf, xfs_attr_leaf_name(leaf, args->index), 1747 entsize)); 1748 1749 tmp = (be16_to_cpu(hdr->count) - args->index) 1750 * sizeof(xfs_attr_leaf_entry_t); 1751 memmove((char *)entry, (char *)(entry+1), tmp); 1752 be16_add_cpu(&hdr->count, -1); 1753 xfs_da_log_buf(args->trans, bp, 1754 XFS_DA_LOGRANGE(leaf, entry, tmp + sizeof(*entry))); 1755 entry = &leaf->entries[be16_to_cpu(hdr->count)]; 1756 memset((char *)entry, 0, sizeof(xfs_attr_leaf_entry_t)); 1757 1758 /* 1759 * If we removed the first entry, re-find the first used byte 1760 * in the name area. Note that if the entry was the "firstused", 1761 * then we don't have a "hole" in our block resulting from 1762 * removing the name. 1763 */ 1764 if (smallest) { 1765 tmp = XFS_LBSIZE(mp); 1766 entry = &leaf->entries[0]; 1767 for (i = be16_to_cpu(hdr->count)-1; i >= 0; entry++, i--) { 1768 ASSERT(be16_to_cpu(entry->nameidx) >= 1769 be16_to_cpu(hdr->firstused)); 1770 ASSERT(be16_to_cpu(entry->nameidx) < XFS_LBSIZE(mp)); 1771 1772 if (be16_to_cpu(entry->nameidx) < tmp) 1773 tmp = be16_to_cpu(entry->nameidx); 1774 } 1775 hdr->firstused = cpu_to_be16(tmp); 1776 if (!hdr->firstused) { 1777 hdr->firstused = cpu_to_be16( 1778 tmp - XFS_ATTR_LEAF_NAME_ALIGN); 1779 } 1780 } else { 1781 hdr->holes = 1; /* mark as needing compaction */ 1782 } 1783 xfs_da_log_buf(args->trans, bp, 1784 XFS_DA_LOGRANGE(leaf, hdr, sizeof(*hdr))); 1785 1786 /* 1787 * Check if leaf is less than 50% full, caller may want to 1788 * "join" the leaf with a sibling if so. 1789 */ 1790 tmp = sizeof(xfs_attr_leaf_hdr_t); 1791 tmp += be16_to_cpu(leaf->hdr.count) * sizeof(xfs_attr_leaf_entry_t); 1792 tmp += be16_to_cpu(leaf->hdr.usedbytes); 1793 return(tmp < mp->m_attr_magicpct); /* leaf is < 37% full */ 1794} 1795 1796/* 1797 * Move all the attribute list entries from drop_leaf into save_leaf. 1798 */ 1799void 1800xfs_attr_leaf_unbalance(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk, 1801 xfs_da_state_blk_t *save_blk) 1802{ 1803 xfs_attr_leafblock_t *drop_leaf, *save_leaf, *tmp_leaf; 1804 xfs_attr_leaf_hdr_t *drop_hdr, *save_hdr, *tmp_hdr; 1805 xfs_mount_t *mp; 1806 char *tmpbuffer; 1807 1808 /* 1809 * Set up environment. 1810 */ 1811 mp = state->mp; 1812 ASSERT(drop_blk->magic == XFS_ATTR_LEAF_MAGIC); 1813 ASSERT(save_blk->magic == XFS_ATTR_LEAF_MAGIC); 1814 drop_leaf = drop_blk->bp->data; 1815 save_leaf = save_blk->bp->data; 1816 ASSERT(be16_to_cpu(drop_leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC); 1817 ASSERT(be16_to_cpu(save_leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC); 1818 drop_hdr = &drop_leaf->hdr; 1819 save_hdr = &save_leaf->hdr; 1820 1821 /* 1822 * Save last hashval from dying block for later Btree fixup. 1823 */ 1824 drop_blk->hashval = be32_to_cpu( 1825 drop_leaf->entries[be16_to_cpu(drop_leaf->hdr.count)-1].hashval); 1826 1827 /* 1828 * Check if we need a temp buffer, or can we do it in place. 1829 * Note that we don't check "leaf" for holes because we will 1830 * always be dropping it, toosmall() decided that for us already. 1831 */ 1832 if (save_hdr->holes == 0) { 1833 /* 1834 * dest leaf has no holes, so we add there. May need 1835 * to make some room in the entry array. 1836 */ 1837 if (xfs_attr_leaf_order(save_blk->bp, drop_blk->bp)) { 1838 xfs_attr_leaf_moveents(drop_leaf, 0, save_leaf, 0, 1839 be16_to_cpu(drop_hdr->count), mp); 1840 } else { 1841 xfs_attr_leaf_moveents(drop_leaf, 0, save_leaf, 1842 be16_to_cpu(save_hdr->count), 1843 be16_to_cpu(drop_hdr->count), mp); 1844 } 1845 } else { 1846 /* 1847 * Destination has holes, so we make a temporary copy 1848 * of the leaf and add them both to that. 1849 */ 1850 tmpbuffer = kmem_alloc(state->blocksize, KM_SLEEP); 1851 ASSERT(tmpbuffer != NULL); 1852 memset(tmpbuffer, 0, state->blocksize); 1853 tmp_leaf = (xfs_attr_leafblock_t *)tmpbuffer; 1854 tmp_hdr = &tmp_leaf->hdr; 1855 tmp_hdr->info = save_hdr->info; /* struct copy */ 1856 tmp_hdr->count = 0; 1857 tmp_hdr->firstused = cpu_to_be16(state->blocksize); 1858 if (!tmp_hdr->firstused) { 1859 tmp_hdr->firstused = cpu_to_be16( 1860 state->blocksize - XFS_ATTR_LEAF_NAME_ALIGN); 1861 } 1862 tmp_hdr->usedbytes = 0; 1863 if (xfs_attr_leaf_order(save_blk->bp, drop_blk->bp)) { 1864 xfs_attr_leaf_moveents(drop_leaf, 0, tmp_leaf, 0, 1865 be16_to_cpu(drop_hdr->count), mp); 1866 xfs_attr_leaf_moveents(save_leaf, 0, tmp_leaf, 1867 be16_to_cpu(tmp_leaf->hdr.count), 1868 be16_to_cpu(save_hdr->count), mp); 1869 } else { 1870 xfs_attr_leaf_moveents(save_leaf, 0, tmp_leaf, 0, 1871 be16_to_cpu(save_hdr->count), mp); 1872 xfs_attr_leaf_moveents(drop_leaf, 0, tmp_leaf, 1873 be16_to_cpu(tmp_leaf->hdr.count), 1874 be16_to_cpu(drop_hdr->count), mp); 1875 } 1876 memcpy((char *)save_leaf, (char *)tmp_leaf, state->blocksize); 1877 kmem_free(tmpbuffer); 1878 } 1879 1880 xfs_da_log_buf(state->args->trans, save_blk->bp, 0, 1881 state->blocksize - 1); 1882 1883 /* 1884 * Copy out last hashval in each block for B-tree code. 1885 */ 1886 save_blk->hashval = be32_to_cpu( 1887 save_leaf->entries[be16_to_cpu(save_leaf->hdr.count)-1].hashval); 1888} 1889 1890/*======================================================================== 1891 * Routines used for finding things in the Btree. 1892 *========================================================================*/ 1893 1894/* 1895 * Look up a name in a leaf attribute list structure. 1896 * This is the internal routine, it uses the caller's buffer. 1897 * 1898 * Note that duplicate keys are allowed, but only check within the 1899 * current leaf node. The Btree code must check in adjacent leaf nodes. 1900 * 1901 * Return in args->index the index into the entry[] array of either 1902 * the found entry, or where the entry should have been (insert before 1903 * that entry). 1904 * 1905 * Don't change the args->value unless we find the attribute. 1906 */ 1907int 1908xfs_attr_leaf_lookup_int(xfs_dabuf_t *bp, xfs_da_args_t *args) 1909{ 1910 xfs_attr_leafblock_t *leaf; 1911 xfs_attr_leaf_entry_t *entry; 1912 xfs_attr_leaf_name_local_t *name_loc; 1913 xfs_attr_leaf_name_remote_t *name_rmt; 1914 int probe, span; 1915 xfs_dahash_t hashval; 1916 1917 leaf = bp->data; 1918 ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC); 1919 ASSERT(be16_to_cpu(leaf->hdr.count) 1920 < (XFS_LBSIZE(args->dp->i_mount)/8)); 1921 1922 /* 1923 * Binary search. (note: small blocks will skip this loop) 1924 */ 1925 hashval = args->hashval; 1926 probe = span = be16_to_cpu(leaf->hdr.count) / 2; 1927 for (entry = &leaf->entries[probe]; span > 4; 1928 entry = &leaf->entries[probe]) { 1929 span /= 2; 1930 if (be32_to_cpu(entry->hashval) < hashval) 1931 probe += span; 1932 else if (be32_to_cpu(entry->hashval) > hashval) 1933 probe -= span; 1934 else 1935 break; 1936 } 1937 ASSERT((probe >= 0) && 1938 (!leaf->hdr.count 1939 || (probe < be16_to_cpu(leaf->hdr.count)))); 1940 ASSERT((span <= 4) || (be32_to_cpu(entry->hashval) == hashval)); 1941 1942 /* 1943 * Since we may have duplicate hashval's, find the first matching 1944 * hashval in the leaf. 1945 */ 1946 while ((probe > 0) && (be32_to_cpu(entry->hashval) >= hashval)) { 1947 entry--; 1948 probe--; 1949 } 1950 while ((probe < be16_to_cpu(leaf->hdr.count)) && 1951 (be32_to_cpu(entry->hashval) < hashval)) { 1952 entry++; 1953 probe++; 1954 } 1955 if ((probe == be16_to_cpu(leaf->hdr.count)) || 1956 (be32_to_cpu(entry->hashval) != hashval)) { 1957 args->index = probe; 1958 return(XFS_ERROR(ENOATTR)); 1959 } 1960 1961 /* 1962 * Duplicate keys may be present, so search all of them for a match. 1963 */ 1964 for ( ; (probe < be16_to_cpu(leaf->hdr.count)) && 1965 (be32_to_cpu(entry->hashval) == hashval); 1966 entry++, probe++) { 1967/* 1968 * GROT: Add code to remove incomplete entries. 1969 */ 1970 /* 1971 * If we are looking for INCOMPLETE entries, show only those. 1972 * If we are looking for complete entries, show only those. 1973 */ 1974 if ((args->flags & XFS_ATTR_INCOMPLETE) != 1975 (entry->flags & XFS_ATTR_INCOMPLETE)) { 1976 continue; 1977 } 1978 if (entry->flags & XFS_ATTR_LOCAL) { 1979 name_loc = xfs_attr_leaf_name_local(leaf, probe); 1980 if (name_loc->namelen != args->namelen) 1981 continue; 1982 if (memcmp(args->name, (char *)name_loc->nameval, args->namelen) != 0) 1983 continue; 1984 if (!xfs_attr_namesp_match(args->flags, entry->flags)) 1985 continue; 1986 args->index = probe; 1987 return(XFS_ERROR(EEXIST)); 1988 } else { 1989 name_rmt = xfs_attr_leaf_name_remote(leaf, probe); 1990 if (name_rmt->namelen != args->namelen) 1991 continue; 1992 if (memcmp(args->name, (char *)name_rmt->name, 1993 args->namelen) != 0) 1994 continue; 1995 if (!xfs_attr_namesp_match(args->flags, entry->flags)) 1996 continue; 1997 args->index = probe; 1998 args->rmtblkno = be32_to_cpu(name_rmt->valueblk); 1999 args->rmtblkcnt = XFS_B_TO_FSB(args->dp->i_mount, 2000 be32_to_cpu(name_rmt->valuelen)); 2001 return(XFS_ERROR(EEXIST)); 2002 } 2003 } 2004 args->index = probe; 2005 return(XFS_ERROR(ENOATTR)); 2006} 2007 2008/* 2009 * Get the value associated with an attribute name from a leaf attribute 2010 * list structure. 2011 */ 2012int 2013xfs_attr_leaf_getvalue(xfs_dabuf_t *bp, xfs_da_args_t *args) 2014{ 2015 int valuelen; 2016 xfs_attr_leafblock_t *leaf; 2017 xfs_attr_leaf_entry_t *entry; 2018 xfs_attr_leaf_name_local_t *name_loc; 2019 xfs_attr_leaf_name_remote_t *name_rmt; 2020 2021 leaf = bp->data; 2022 ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC); 2023 ASSERT(be16_to_cpu(leaf->hdr.count) 2024 < (XFS_LBSIZE(args->dp->i_mount)/8)); 2025 ASSERT(args->index < be16_to_cpu(leaf->hdr.count)); 2026 2027 entry = &leaf->entries[args->index]; 2028 if (entry->flags & XFS_ATTR_LOCAL) { 2029 name_loc = xfs_attr_leaf_name_local(leaf, args->index); 2030 ASSERT(name_loc->namelen == args->namelen); 2031 ASSERT(memcmp(args->name, name_loc->nameval, args->namelen) == 0); 2032 valuelen = be16_to_cpu(name_loc->valuelen); 2033 if (args->flags & ATTR_KERNOVAL) { 2034 args->valuelen = valuelen; 2035 return(0); 2036 } 2037 if (args->valuelen < valuelen) { 2038 args->valuelen = valuelen; 2039 return(XFS_ERROR(ERANGE)); 2040 } 2041 args->valuelen = valuelen; 2042 memcpy(args->value, &name_loc->nameval[args->namelen], valuelen); 2043 } else { 2044 name_rmt = xfs_attr_leaf_name_remote(leaf, args->index); 2045 ASSERT(name_rmt->namelen == args->namelen); 2046 ASSERT(memcmp(args->name, name_rmt->name, args->namelen) == 0); 2047 valuelen = be32_to_cpu(name_rmt->valuelen); 2048 args->rmtblkno = be32_to_cpu(name_rmt->valueblk); 2049 args->rmtblkcnt = XFS_B_TO_FSB(args->dp->i_mount, valuelen); 2050 if (args->flags & ATTR_KERNOVAL) { 2051 args->valuelen = valuelen; 2052 return(0); 2053 } 2054 if (args->valuelen < valuelen) { 2055 args->valuelen = valuelen; 2056 return(XFS_ERROR(ERANGE)); 2057 } 2058 args->valuelen = valuelen; 2059 } 2060 return(0); 2061} 2062 2063/*======================================================================== 2064 * Utility routines. 2065 *========================================================================*/ 2066 2067/* 2068 * Move the indicated entries from one leaf to another. 2069 * NOTE: this routine modifies both source and destination leaves. 2070 */ 2071/*ARGSUSED*/ 2072STATIC void 2073xfs_attr_leaf_moveents(xfs_attr_leafblock_t *leaf_s, int start_s, 2074 xfs_attr_leafblock_t *leaf_d, int start_d, 2075 int count, xfs_mount_t *mp) 2076{ 2077 xfs_attr_leaf_hdr_t *hdr_s, *hdr_d; 2078 xfs_attr_leaf_entry_t *entry_s, *entry_d; 2079 int desti, tmp, i; 2080 2081 /* 2082 * Check for nothing to do. 2083 */ 2084 if (count == 0) 2085 return; 2086 2087 /* 2088 * Set up environment. 2089 */ 2090 ASSERT(be16_to_cpu(leaf_s->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC); 2091 ASSERT(be16_to_cpu(leaf_d->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC); 2092 hdr_s = &leaf_s->hdr; 2093 hdr_d = &leaf_d->hdr; 2094 ASSERT((be16_to_cpu(hdr_s->count) > 0) && 2095 (be16_to_cpu(hdr_s->count) < (XFS_LBSIZE(mp)/8))); 2096 ASSERT(be16_to_cpu(hdr_s->firstused) >= 2097 ((be16_to_cpu(hdr_s->count) 2098 * sizeof(*entry_s))+sizeof(*hdr_s))); 2099 ASSERT(be16_to_cpu(hdr_d->count) < (XFS_LBSIZE(mp)/8)); 2100 ASSERT(be16_to_cpu(hdr_d->firstused) >= 2101 ((be16_to_cpu(hdr_d->count) 2102 * sizeof(*entry_d))+sizeof(*hdr_d))); 2103 2104 ASSERT(start_s < be16_to_cpu(hdr_s->count)); 2105 ASSERT(start_d <= be16_to_cpu(hdr_d->count)); 2106 ASSERT(count <= be16_to_cpu(hdr_s->count)); 2107 2108 /* 2109 * Move the entries in the destination leaf up to make a hole? 2110 */ 2111 if (start_d < be16_to_cpu(hdr_d->count)) { 2112 tmp = be16_to_cpu(hdr_d->count) - start_d; 2113 tmp *= sizeof(xfs_attr_leaf_entry_t); 2114 entry_s = &leaf_d->entries[start_d]; 2115 entry_d = &leaf_d->entries[start_d + count]; 2116 memmove((char *)entry_d, (char *)entry_s, tmp); 2117 } 2118 2119 /* 2120 * Copy all entry's in the same (sorted) order, 2121 * but allocate attribute info packed and in sequence. 2122 */ 2123 entry_s = &leaf_s->entries[start_s]; 2124 entry_d = &leaf_d->entries[start_d]; 2125 desti = start_d; 2126 for (i = 0; i < count; entry_s++, entry_d++, desti++, i++) { 2127 ASSERT(be16_to_cpu(entry_s->nameidx) 2128 >= be16_to_cpu(hdr_s->firstused)); 2129 tmp = xfs_attr_leaf_entsize(leaf_s, start_s + i); 2130#ifdef GROT 2131 /* 2132 * Code to drop INCOMPLETE entries. Difficult to use as we 2133 * may also need to change the insertion index. Code turned 2134 * off for 6.2, should be revisited later. 2135 */ 2136 if (entry_s->flags & XFS_ATTR_INCOMPLETE) { /* skip partials? */ 2137 memset(xfs_attr_leaf_name(leaf_s, start_s + i), 0, tmp); 2138 be16_add_cpu(&hdr_s->usedbytes, -tmp); 2139 be16_add_cpu(&hdr_s->count, -1); 2140 entry_d--; /* to compensate for ++ in loop hdr */ 2141 desti--; 2142 if ((start_s + i) < offset) 2143 result++; /* insertion index adjustment */ 2144 } else { 2145#endif /* GROT */ 2146 be16_add_cpu(&hdr_d->firstused, -tmp); 2147 /* both on-disk, don't endian flip twice */ 2148 entry_d->hashval = entry_s->hashval; 2149 /* both on-disk, don't endian flip twice */ 2150 entry_d->nameidx = hdr_d->firstused; 2151 entry_d->flags = entry_s->flags; 2152 ASSERT(be16_to_cpu(entry_d->nameidx) + tmp 2153 <= XFS_LBSIZE(mp)); 2154 memmove(xfs_attr_leaf_name(leaf_d, desti), 2155 xfs_attr_leaf_name(leaf_s, start_s + i), tmp); 2156 ASSERT(be16_to_cpu(entry_s->nameidx) + tmp 2157 <= XFS_LBSIZE(mp)); 2158 memset(xfs_attr_leaf_name(leaf_s, start_s + i), 0, tmp); 2159 be16_add_cpu(&hdr_s->usedbytes, -tmp); 2160 be16_add_cpu(&hdr_d->usedbytes, tmp); 2161 be16_add_cpu(&hdr_s->count, -1); 2162 be16_add_cpu(&hdr_d->count, 1); 2163 tmp = be16_to_cpu(hdr_d->count) 2164 * sizeof(xfs_attr_leaf_entry_t) 2165 + sizeof(xfs_attr_leaf_hdr_t); 2166 ASSERT(be16_to_cpu(hdr_d->firstused) >= tmp); 2167#ifdef GROT 2168 } 2169#endif /* GROT */ 2170 } 2171 2172 /* 2173 * Zero out the entries we just copied. 2174 */ 2175 if (start_s == be16_to_cpu(hdr_s->count)) { 2176 tmp = count * sizeof(xfs_attr_leaf_entry_t); 2177 entry_s = &leaf_s->entries[start_s]; 2178 ASSERT(((char *)entry_s + tmp) <= 2179 ((char *)leaf_s + XFS_LBSIZE(mp))); 2180 memset((char *)entry_s, 0, tmp); 2181 } else { 2182 /* 2183 * Move the remaining entries down to fill the hole, 2184 * then zero the entries at the top. 2185 */ 2186 tmp = be16_to_cpu(hdr_s->count) - count; 2187 tmp *= sizeof(xfs_attr_leaf_entry_t); 2188 entry_s = &leaf_s->entries[start_s + count]; 2189 entry_d = &leaf_s->entries[start_s]; 2190 memmove((char *)entry_d, (char *)entry_s, tmp); 2191 2192 tmp = count * sizeof(xfs_attr_leaf_entry_t); 2193 entry_s = &leaf_s->entries[be16_to_cpu(hdr_s->count)]; 2194 ASSERT(((char *)entry_s + tmp) <= 2195 ((char *)leaf_s + XFS_LBSIZE(mp))); 2196 memset((char *)entry_s, 0, tmp); 2197 } 2198 2199 /* 2200 * Fill in the freemap information 2201 */ 2202 hdr_d->freemap[0].base = cpu_to_be16(sizeof(xfs_attr_leaf_hdr_t)); 2203 be16_add_cpu(&hdr_d->freemap[0].base, be16_to_cpu(hdr_d->count) * 2204 sizeof(xfs_attr_leaf_entry_t)); 2205 hdr_d->freemap[0].size = cpu_to_be16(be16_to_cpu(hdr_d->firstused) 2206 - be16_to_cpu(hdr_d->freemap[0].base)); 2207 hdr_d->freemap[1].base = 0; 2208 hdr_d->freemap[2].base = 0; 2209 hdr_d->freemap[1].size = 0; 2210 hdr_d->freemap[2].size = 0; 2211 hdr_s->holes = 1; /* leaf may not be compact */ 2212} 2213 2214/* 2215 * Compare two leaf blocks "order". 2216 * Return 0 unless leaf2 should go before leaf1. 2217 */ 2218int 2219xfs_attr_leaf_order(xfs_dabuf_t *leaf1_bp, xfs_dabuf_t *leaf2_bp) 2220{ 2221 xfs_attr_leafblock_t *leaf1, *leaf2; 2222 2223 leaf1 = leaf1_bp->data; 2224 leaf2 = leaf2_bp->data; 2225 ASSERT((be16_to_cpu(leaf1->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC) && 2226 (be16_to_cpu(leaf2->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC)); 2227 if ((be16_to_cpu(leaf1->hdr.count) > 0) && 2228 (be16_to_cpu(leaf2->hdr.count) > 0) && 2229 ((be32_to_cpu(leaf2->entries[0].hashval) < 2230 be32_to_cpu(leaf1->entries[0].hashval)) || 2231 (be32_to_cpu(leaf2->entries[ 2232 be16_to_cpu(leaf2->hdr.count)-1].hashval) < 2233 be32_to_cpu(leaf1->entries[ 2234 be16_to_cpu(leaf1->hdr.count)-1].hashval)))) { 2235 return(1); 2236 } 2237 return(0); 2238} 2239 2240/* 2241 * Pick up the last hashvalue from a leaf block. 2242 */ 2243xfs_dahash_t 2244xfs_attr_leaf_lasthash(xfs_dabuf_t *bp, int *count) 2245{ 2246 xfs_attr_leafblock_t *leaf; 2247 2248 leaf = bp->data; 2249 ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC); 2250 if (count) 2251 *count = be16_to_cpu(leaf->hdr.count); 2252 if (!leaf->hdr.count) 2253 return(0); 2254 return be32_to_cpu(leaf->entries[be16_to_cpu(leaf->hdr.count)-1].hashval); 2255} 2256 2257/* 2258 * Calculate the number of bytes used to store the indicated attribute 2259 * (whether local or remote only calculate bytes in this block). 2260 */ 2261STATIC int 2262xfs_attr_leaf_entsize(xfs_attr_leafblock_t *leaf, int index) 2263{ 2264 xfs_attr_leaf_name_local_t *name_loc; 2265 xfs_attr_leaf_name_remote_t *name_rmt; 2266 int size; 2267 2268 ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC); 2269 if (leaf->entries[index].flags & XFS_ATTR_LOCAL) { 2270 name_loc = xfs_attr_leaf_name_local(leaf, index); 2271 size = xfs_attr_leaf_entsize_local(name_loc->namelen, 2272 be16_to_cpu(name_loc->valuelen)); 2273 } else { 2274 name_rmt = xfs_attr_leaf_name_remote(leaf, index); 2275 size = xfs_attr_leaf_entsize_remote(name_rmt->namelen); 2276 } 2277 return(size); 2278} 2279 2280/* 2281 * Calculate the number of bytes that would be required to store the new 2282 * attribute (whether local or remote only calculate bytes in this block). 2283 * This routine decides as a side effect whether the attribute will be 2284 * a "local" or a "remote" attribute. 2285 */ 2286int 2287xfs_attr_leaf_newentsize(int namelen, int valuelen, int blocksize, int *local) 2288{ 2289 int size; 2290 2291 size = xfs_attr_leaf_entsize_local(namelen, valuelen); 2292 if (size < xfs_attr_leaf_entsize_local_max(blocksize)) { 2293 if (local) { 2294 *local = 1; 2295 } 2296 } else { 2297 size = xfs_attr_leaf_entsize_remote(namelen); 2298 if (local) { 2299 *local = 0; 2300 } 2301 } 2302 return(size); 2303} 2304 2305/* 2306 * Copy out attribute list entries for attr_list(), for leaf attribute lists. 2307 */ 2308int 2309xfs_attr_leaf_list_int(xfs_dabuf_t *bp, xfs_attr_list_context_t *context) 2310{ 2311 attrlist_cursor_kern_t *cursor; 2312 xfs_attr_leafblock_t *leaf; 2313 xfs_attr_leaf_entry_t *entry; 2314 int retval, i; 2315 2316 ASSERT(bp != NULL); 2317 leaf = bp->data; 2318 cursor = context->cursor; 2319 cursor->initted = 1; 2320 2321 trace_xfs_attr_list_leaf(context); 2322 2323 /* 2324 * Re-find our place in the leaf block if this is a new syscall. 2325 */ 2326 if (context->resynch) { 2327 entry = &leaf->entries[0]; 2328 for (i = 0; i < be16_to_cpu(leaf->hdr.count); entry++, i++) { 2329 if (be32_to_cpu(entry->hashval) == cursor->hashval) { 2330 if (cursor->offset == context->dupcnt) { 2331 context->dupcnt = 0; 2332 break; 2333 } 2334 context->dupcnt++; 2335 } else if (be32_to_cpu(entry->hashval) > 2336 cursor->hashval) { 2337 context->dupcnt = 0; 2338 break; 2339 } 2340 } 2341 if (i == be16_to_cpu(leaf->hdr.count)) { 2342 trace_xfs_attr_list_notfound(context); 2343 return(0); 2344 } 2345 } else { 2346 entry = &leaf->entries[0]; 2347 i = 0; 2348 } 2349 context->resynch = 0; 2350 2351 /* 2352 * We have found our place, start copying out the new attributes. 2353 */ 2354 retval = 0; 2355 for ( ; (i < be16_to_cpu(leaf->hdr.count)); entry++, i++) { 2356 if (be32_to_cpu(entry->hashval) != cursor->hashval) { 2357 cursor->hashval = be32_to_cpu(entry->hashval); 2358 cursor->offset = 0; 2359 } 2360 2361 if (entry->flags & XFS_ATTR_INCOMPLETE) 2362 continue; /* skip incomplete entries */ 2363 2364 if (entry->flags & XFS_ATTR_LOCAL) { 2365 xfs_attr_leaf_name_local_t *name_loc = 2366 xfs_attr_leaf_name_local(leaf, i); 2367 2368 retval = context->put_listent(context, 2369 entry->flags, 2370 name_loc->nameval, 2371 (int)name_loc->namelen, 2372 be16_to_cpu(name_loc->valuelen), 2373 &name_loc->nameval[name_loc->namelen]); 2374 if (retval) 2375 return retval; 2376 } else { 2377 xfs_attr_leaf_name_remote_t *name_rmt = 2378 xfs_attr_leaf_name_remote(leaf, i); 2379 2380 int valuelen = be32_to_cpu(name_rmt->valuelen); 2381 2382 if (context->put_value) { 2383 xfs_da_args_t args; 2384 2385 memset((char *)&args, 0, sizeof(args)); 2386 args.dp = context->dp; 2387 args.whichfork = XFS_ATTR_FORK; 2388 args.valuelen = valuelen; 2389 args.value = kmem_alloc(valuelen, KM_SLEEP); 2390 args.rmtblkno = be32_to_cpu(name_rmt->valueblk); 2391 args.rmtblkcnt = XFS_B_TO_FSB(args.dp->i_mount, valuelen); 2392 retval = xfs_attr_rmtval_get(&args); 2393 if (retval) 2394 return retval; 2395 retval = context->put_listent(context, 2396 entry->flags, 2397 name_rmt->name, 2398 (int)name_rmt->namelen, 2399 valuelen, 2400 args.value); 2401 kmem_free(args.value); 2402 } else { 2403 retval = context->put_listent(context, 2404 entry->flags, 2405 name_rmt->name, 2406 (int)name_rmt->namelen, 2407 valuelen, 2408 NULL); 2409 } 2410 if (retval) 2411 return retval; 2412 } 2413 if (context->seen_enough) 2414 break; 2415 cursor->offset++; 2416 } 2417 trace_xfs_attr_list_leaf_end(context); 2418 return(retval); 2419} 2420 2421 2422/*======================================================================== 2423 * Manage the INCOMPLETE flag in a leaf entry 2424 *========================================================================*/ 2425 2426/* 2427 * Clear the INCOMPLETE flag on an entry in a leaf block. 2428 */ 2429int 2430xfs_attr_leaf_clearflag(xfs_da_args_t *args) 2431{ 2432 xfs_attr_leafblock_t *leaf; 2433 xfs_attr_leaf_entry_t *entry; 2434 xfs_attr_leaf_name_remote_t *name_rmt; 2435 xfs_dabuf_t *bp; 2436 int error; 2437#ifdef DEBUG 2438 xfs_attr_leaf_name_local_t *name_loc; 2439 int namelen; 2440 char *name; 2441#endif /* DEBUG */ 2442 2443 /* 2444 * Set up the operation. 2445 */ 2446 error = xfs_da_read_buf(args->trans, args->dp, args->blkno, -1, &bp, 2447 XFS_ATTR_FORK); 2448 if (error) { 2449 return(error); 2450 } 2451 ASSERT(bp != NULL); 2452 2453 leaf = bp->data; 2454 ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC); 2455 ASSERT(args->index < be16_to_cpu(leaf->hdr.count)); 2456 ASSERT(args->index >= 0); 2457 entry = &leaf->entries[ args->index ]; 2458 ASSERT(entry->flags & XFS_ATTR_INCOMPLETE); 2459 2460#ifdef DEBUG 2461 if (entry->flags & XFS_ATTR_LOCAL) { 2462 name_loc = xfs_attr_leaf_name_local(leaf, args->index); 2463 namelen = name_loc->namelen; 2464 name = (char *)name_loc->nameval; 2465 } else { 2466 name_rmt = xfs_attr_leaf_name_remote(leaf, args->index); 2467 namelen = name_rmt->namelen; 2468 name = (char *)name_rmt->name; 2469 } 2470 ASSERT(be32_to_cpu(entry->hashval) == args->hashval); 2471 ASSERT(namelen == args->namelen); 2472 ASSERT(memcmp(name, args->name, namelen) == 0); 2473#endif /* DEBUG */ 2474 2475 entry->flags &= ~XFS_ATTR_INCOMPLETE; 2476 xfs_da_log_buf(args->trans, bp, 2477 XFS_DA_LOGRANGE(leaf, entry, sizeof(*entry))); 2478 2479 if (args->rmtblkno) { 2480 ASSERT((entry->flags & XFS_ATTR_LOCAL) == 0); 2481 name_rmt = xfs_attr_leaf_name_remote(leaf, args->index); 2482 name_rmt->valueblk = cpu_to_be32(args->rmtblkno); 2483 name_rmt->valuelen = cpu_to_be32(args->valuelen); 2484 xfs_da_log_buf(args->trans, bp, 2485 XFS_DA_LOGRANGE(leaf, name_rmt, sizeof(*name_rmt))); 2486 } 2487 xfs_da_buf_done(bp); 2488 2489 /* 2490 * Commit the flag value change and start the next trans in series. 2491 */ 2492 return xfs_trans_roll(&args->trans, args->dp); 2493} 2494 2495/* 2496 * Set the INCOMPLETE flag on an entry in a leaf block. 2497 */ 2498int 2499xfs_attr_leaf_setflag(xfs_da_args_t *args) 2500{ 2501 xfs_attr_leafblock_t *leaf; 2502 xfs_attr_leaf_entry_t *entry; 2503 xfs_attr_leaf_name_remote_t *name_rmt; 2504 xfs_dabuf_t *bp; 2505 int error; 2506 2507 /* 2508 * Set up the operation. 2509 */ 2510 error = xfs_da_read_buf(args->trans, args->dp, args->blkno, -1, &bp, 2511 XFS_ATTR_FORK); 2512 if (error) { 2513 return(error); 2514 } 2515 ASSERT(bp != NULL); 2516 2517 leaf = bp->data; 2518 ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC); 2519 ASSERT(args->index < be16_to_cpu(leaf->hdr.count)); 2520 ASSERT(args->index >= 0); 2521 entry = &leaf->entries[ args->index ]; 2522 2523 ASSERT((entry->flags & XFS_ATTR_INCOMPLETE) == 0); 2524 entry->flags |= XFS_ATTR_INCOMPLETE; 2525 xfs_da_log_buf(args->trans, bp, 2526 XFS_DA_LOGRANGE(leaf, entry, sizeof(*entry))); 2527 if ((entry->flags & XFS_ATTR_LOCAL) == 0) { 2528 name_rmt = xfs_attr_leaf_name_remote(leaf, args->index); 2529 name_rmt->valueblk = 0; 2530 name_rmt->valuelen = 0; 2531 xfs_da_log_buf(args->trans, bp, 2532 XFS_DA_LOGRANGE(leaf, name_rmt, sizeof(*name_rmt))); 2533 } 2534 xfs_da_buf_done(bp); 2535 2536 /* 2537 * Commit the flag value change and start the next trans in series. 2538 */ 2539 return xfs_trans_roll(&args->trans, args->dp); 2540} 2541 2542/* 2543 * In a single transaction, clear the INCOMPLETE flag on the leaf entry 2544 * given by args->blkno/index and set the INCOMPLETE flag on the leaf 2545 * entry given by args->blkno2/index2. 2546 * 2547 * Note that they could be in different blocks, or in the same block. 2548 */ 2549int 2550xfs_attr_leaf_flipflags(xfs_da_args_t *args) 2551{ 2552 xfs_attr_leafblock_t *leaf1, *leaf2; 2553 xfs_attr_leaf_entry_t *entry1, *entry2; 2554 xfs_attr_leaf_name_remote_t *name_rmt; 2555 xfs_dabuf_t *bp1, *bp2; 2556 int error; 2557#ifdef DEBUG 2558 xfs_attr_leaf_name_local_t *name_loc; 2559 int namelen1, namelen2; 2560 char *name1, *name2; 2561#endif /* DEBUG */ 2562 2563 /* 2564 * Read the block containing the "old" attr 2565 */ 2566 error = xfs_da_read_buf(args->trans, args->dp, args->blkno, -1, &bp1, 2567 XFS_ATTR_FORK); 2568 if (error) { 2569 return(error); 2570 } 2571 ASSERT(bp1 != NULL); 2572 2573 /* 2574 * Read the block containing the "new" attr, if it is different 2575 */ 2576 if (args->blkno2 != args->blkno) { 2577 error = xfs_da_read_buf(args->trans, args->dp, args->blkno2, 2578 -1, &bp2, XFS_ATTR_FORK); 2579 if (error) { 2580 return(error); 2581 } 2582 ASSERT(bp2 != NULL); 2583 } else { 2584 bp2 = bp1; 2585 } 2586 2587 leaf1 = bp1->data; 2588 ASSERT(be16_to_cpu(leaf1->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC); 2589 ASSERT(args->index < be16_to_cpu(leaf1->hdr.count)); 2590 ASSERT(args->index >= 0); 2591 entry1 = &leaf1->entries[ args->index ]; 2592 2593 leaf2 = bp2->data; 2594 ASSERT(be16_to_cpu(leaf2->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC); 2595 ASSERT(args->index2 < be16_to_cpu(leaf2->hdr.count)); 2596 ASSERT(args->index2 >= 0); 2597 entry2 = &leaf2->entries[ args->index2 ]; 2598 2599#ifdef DEBUG 2600 if (entry1->flags & XFS_ATTR_LOCAL) { 2601 name_loc = xfs_attr_leaf_name_local(leaf1, args->index); 2602 namelen1 = name_loc->namelen; 2603 name1 = (char *)name_loc->nameval; 2604 } else { 2605 name_rmt = xfs_attr_leaf_name_remote(leaf1, args->index); 2606 namelen1 = name_rmt->namelen; 2607 name1 = (char *)name_rmt->name; 2608 } 2609 if (entry2->flags & XFS_ATTR_LOCAL) { 2610 name_loc = xfs_attr_leaf_name_local(leaf2, args->index2); 2611 namelen2 = name_loc->namelen; 2612 name2 = (char *)name_loc->nameval; 2613 } else { 2614 name_rmt = xfs_attr_leaf_name_remote(leaf2, args->index2); 2615 namelen2 = name_rmt->namelen; 2616 name2 = (char *)name_rmt->name; 2617 } 2618 ASSERT(be32_to_cpu(entry1->hashval) == be32_to_cpu(entry2->hashval)); 2619 ASSERT(namelen1 == namelen2); 2620 ASSERT(memcmp(name1, name2, namelen1) == 0); 2621#endif /* DEBUG */ 2622 2623 ASSERT(entry1->flags & XFS_ATTR_INCOMPLETE); 2624 ASSERT((entry2->flags & XFS_ATTR_INCOMPLETE) == 0); 2625 2626 entry1->flags &= ~XFS_ATTR_INCOMPLETE; 2627 xfs_da_log_buf(args->trans, bp1, 2628 XFS_DA_LOGRANGE(leaf1, entry1, sizeof(*entry1))); 2629 if (args->rmtblkno) { 2630 ASSERT((entry1->flags & XFS_ATTR_LOCAL) == 0); 2631 name_rmt = xfs_attr_leaf_name_remote(leaf1, args->index); 2632 name_rmt->valueblk = cpu_to_be32(args->rmtblkno); 2633 name_rmt->valuelen = cpu_to_be32(args->valuelen); 2634 xfs_da_log_buf(args->trans, bp1, 2635 XFS_DA_LOGRANGE(leaf1, name_rmt, sizeof(*name_rmt))); 2636 } 2637 2638 entry2->flags |= XFS_ATTR_INCOMPLETE; 2639 xfs_da_log_buf(args->trans, bp2, 2640 XFS_DA_LOGRANGE(leaf2, entry2, sizeof(*entry2))); 2641 if ((entry2->flags & XFS_ATTR_LOCAL) == 0) { 2642 name_rmt = xfs_attr_leaf_name_remote(leaf2, args->index2); 2643 name_rmt->valueblk = 0; 2644 name_rmt->valuelen = 0; 2645 xfs_da_log_buf(args->trans, bp2, 2646 XFS_DA_LOGRANGE(leaf2, name_rmt, sizeof(*name_rmt))); 2647 } 2648 xfs_da_buf_done(bp1); 2649 if (bp1 != bp2) 2650 xfs_da_buf_done(bp2); 2651 2652 /* 2653 * Commit the flag value change and start the next trans in series. 2654 */ 2655 error = xfs_trans_roll(&args->trans, args->dp); 2656 2657 return(error); 2658} 2659 2660/*======================================================================== 2661 * Indiscriminately delete the entire attribute fork 2662 *========================================================================*/ 2663 2664/* 2665 * Recurse (gasp!) through the attribute nodes until we find leaves. 2666 * We're doing a depth-first traversal in order to invalidate everything. 2667 */ 2668int 2669xfs_attr_root_inactive(xfs_trans_t **trans, xfs_inode_t *dp) 2670{ 2671 xfs_da_blkinfo_t *info; 2672 xfs_daddr_t blkno; 2673 xfs_dabuf_t *bp; 2674 int error; 2675 2676 /* 2677 * Read block 0 to see what we have to work with. 2678 * We only get here if we have extents, since we remove 2679 * the extents in reverse order the extent containing 2680 * block 0 must still be there. 2681 */ 2682 error = xfs_da_read_buf(*trans, dp, 0, -1, &bp, XFS_ATTR_FORK); 2683 if (error) 2684 return(error); 2685 blkno = xfs_da_blkno(bp); 2686 2687 /* 2688 * Invalidate the tree, even if the "tree" is only a single leaf block. 2689 * This is a depth-first traversal! 2690 */ 2691 info = bp->data; 2692 if (be16_to_cpu(info->magic) == XFS_DA_NODE_MAGIC) { 2693 error = xfs_attr_node_inactive(trans, dp, bp, 1); 2694 } else if (be16_to_cpu(info->magic) == XFS_ATTR_LEAF_MAGIC) { 2695 error = xfs_attr_leaf_inactive(trans, dp, bp); 2696 } else { 2697 error = XFS_ERROR(EIO); 2698 xfs_da_brelse(*trans, bp); 2699 } 2700 if (error) 2701 return(error); 2702 2703 /* 2704 * Invalidate the incore copy of the root block. 2705 */ 2706 error = xfs_da_get_buf(*trans, dp, 0, blkno, &bp, XFS_ATTR_FORK); 2707 if (error) 2708 return(error); 2709 xfs_da_binval(*trans, bp); /* remove from cache */ 2710 /* 2711 * Commit the invalidate and start the next transaction. 2712 */ 2713 error = xfs_trans_roll(trans, dp); 2714 2715 return (error); 2716} 2717 2718/* 2719 * Recurse (gasp!) through the attribute nodes until we find leaves. 2720 * We're doing a depth-first traversal in order to invalidate everything. 2721 */ 2722STATIC int 2723xfs_attr_node_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp, 2724 int level) 2725{ 2726 xfs_da_blkinfo_t *info; 2727 xfs_da_intnode_t *node; 2728 xfs_dablk_t child_fsb; 2729 xfs_daddr_t parent_blkno, child_blkno; 2730 int error, count, i; 2731 xfs_dabuf_t *child_bp; 2732 2733 /* 2734 * Since this code is recursive (gasp!) we must protect ourselves. 2735 */ 2736 if (level > XFS_DA_NODE_MAXDEPTH) { 2737 xfs_da_brelse(*trans, bp); /* no locks for later trans */ 2738 return(XFS_ERROR(EIO)); 2739 } 2740 2741 node = bp->data; 2742 ASSERT(be16_to_cpu(node->hdr.info.magic) == XFS_DA_NODE_MAGIC); 2743 parent_blkno = xfs_da_blkno(bp); /* save for re-read later */ 2744 count = be16_to_cpu(node->hdr.count); 2745 if (!count) { 2746 xfs_da_brelse(*trans, bp); 2747 return(0); 2748 } 2749 child_fsb = be32_to_cpu(node->btree[0].before); 2750 xfs_da_brelse(*trans, bp); /* no locks for later trans */ 2751 2752 /* 2753 * If this is the node level just above the leaves, simply loop 2754 * over the leaves removing all of them. If this is higher up 2755 * in the tree, recurse downward. 2756 */ 2757 for (i = 0; i < count; i++) { 2758 /* 2759 * Read the subsidiary block to see what we have to work with. 2760 * Don't do this in a transaction. This is a depth-first 2761 * traversal of the tree so we may deal with many blocks 2762 * before we come back to this one. 2763 */ 2764 error = xfs_da_read_buf(*trans, dp, child_fsb, -2, &child_bp, 2765 XFS_ATTR_FORK); 2766 if (error) 2767 return(error); 2768 if (child_bp) { 2769 /* save for re-read later */ 2770 child_blkno = xfs_da_blkno(child_bp); 2771 2772 /* 2773 * Invalidate the subtree, however we have to. 2774 */ 2775 info = child_bp->data; 2776 if (be16_to_cpu(info->magic) == XFS_DA_NODE_MAGIC) { 2777 error = xfs_attr_node_inactive(trans, dp, 2778 child_bp, level+1); 2779 } else if (be16_to_cpu(info->magic) == XFS_ATTR_LEAF_MAGIC) { 2780 error = xfs_attr_leaf_inactive(trans, dp, 2781 child_bp); 2782 } else { 2783 error = XFS_ERROR(EIO); 2784 xfs_da_brelse(*trans, child_bp); 2785 } 2786 if (error) 2787 return(error); 2788 2789 /* 2790 * Remove the subsidiary block from the cache 2791 * and from the log. 2792 */ 2793 error = xfs_da_get_buf(*trans, dp, 0, child_blkno, 2794 &child_bp, XFS_ATTR_FORK); 2795 if (error) 2796 return(error); 2797 xfs_da_binval(*trans, child_bp); 2798 } 2799 2800 /* 2801 * If we're not done, re-read the parent to get the next 2802 * child block number. 2803 */ 2804 if ((i+1) < count) { 2805 error = xfs_da_read_buf(*trans, dp, 0, parent_blkno, 2806 &bp, XFS_ATTR_FORK); 2807 if (error) 2808 return(error); 2809 child_fsb = be32_to_cpu(node->btree[i+1].before); 2810 xfs_da_brelse(*trans, bp); 2811 } 2812 /* 2813 * Atomically commit the whole invalidate stuff. 2814 */ 2815 error = xfs_trans_roll(trans, dp); 2816 if (error) 2817 return (error); 2818 } 2819 2820 return(0); 2821} 2822 2823/* 2824 * Invalidate all of the "remote" value regions pointed to by a particular 2825 * leaf block. 2826 * Note that we must release the lock on the buffer so that we are not 2827 * caught holding something that the logging code wants to flush to disk. 2828 */ 2829STATIC int 2830xfs_attr_leaf_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp) 2831{ 2832 xfs_attr_leafblock_t *leaf; 2833 xfs_attr_leaf_entry_t *entry; 2834 xfs_attr_leaf_name_remote_t *name_rmt; 2835 xfs_attr_inactive_list_t *list, *lp; 2836 int error, count, size, tmp, i; 2837 2838 leaf = bp->data; 2839 ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC); 2840 2841 /* 2842 * Count the number of "remote" value extents. 2843 */ 2844 count = 0; 2845 entry = &leaf->entries[0]; 2846 for (i = 0; i < be16_to_cpu(leaf->hdr.count); entry++, i++) { 2847 if (be16_to_cpu(entry->nameidx) && 2848 ((entry->flags & XFS_ATTR_LOCAL) == 0)) { 2849 name_rmt = xfs_attr_leaf_name_remote(leaf, i); 2850 if (name_rmt->valueblk) 2851 count++; 2852 } 2853 } 2854 2855 /* 2856 * If there are no "remote" values, we're done. 2857 */ 2858 if (count == 0) { 2859 xfs_da_brelse(*trans, bp); 2860 return(0); 2861 } 2862 2863 /* 2864 * Allocate storage for a list of all the "remote" value extents. 2865 */ 2866 size = count * sizeof(xfs_attr_inactive_list_t); 2867 list = (xfs_attr_inactive_list_t *)kmem_alloc(size, KM_SLEEP); 2868 2869 /* 2870 * Identify each of the "remote" value extents. 2871 */ 2872 lp = list; 2873 entry = &leaf->entries[0]; 2874 for (i = 0; i < be16_to_cpu(leaf->hdr.count); entry++, i++) { 2875 if (be16_to_cpu(entry->nameidx) && 2876 ((entry->flags & XFS_ATTR_LOCAL) == 0)) { 2877 name_rmt = xfs_attr_leaf_name_remote(leaf, i); 2878 if (name_rmt->valueblk) { 2879 lp->valueblk = be32_to_cpu(name_rmt->valueblk); 2880 lp->valuelen = XFS_B_TO_FSB(dp->i_mount, 2881 be32_to_cpu(name_rmt->valuelen)); 2882 lp++; 2883 } 2884 } 2885 } 2886 xfs_da_brelse(*trans, bp); /* unlock for trans. in freextent() */ 2887 2888 /* 2889 * Invalidate each of the "remote" value extents. 2890 */ 2891 error = 0; 2892 for (lp = list, i = 0; i < count; i++, lp++) { 2893 tmp = xfs_attr_leaf_freextent(trans, dp, 2894 lp->valueblk, lp->valuelen); 2895 2896 if (error == 0) 2897 error = tmp; /* save only the 1st errno */ 2898 } 2899 2900 kmem_free((xfs_caddr_t)list); 2901 return(error); 2902} 2903 2904/* 2905 * Look at all the extents for this logical region, 2906 * invalidate any buffers that are incore/in transactions. 2907 */ 2908STATIC int 2909xfs_attr_leaf_freextent(xfs_trans_t **trans, xfs_inode_t *dp, 2910 xfs_dablk_t blkno, int blkcnt) 2911{ 2912 xfs_bmbt_irec_t map; 2913 xfs_dablk_t tblkno; 2914 int tblkcnt, dblkcnt, nmap, error; 2915 xfs_daddr_t dblkno; 2916 xfs_buf_t *bp; 2917 2918 /* 2919 * Roll through the "value", invalidating the attribute value's 2920 * blocks. 2921 */ 2922 tblkno = blkno; 2923 tblkcnt = blkcnt; 2924 while (tblkcnt > 0) { 2925 /* 2926 * Try to remember where we decided to put the value. 2927 */ 2928 nmap = 1; 2929 error = xfs_bmapi(*trans, dp, (xfs_fileoff_t)tblkno, tblkcnt, 2930 XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA, 2931 NULL, 0, &map, &nmap, NULL); 2932 if (error) { 2933 return(error); 2934 } 2935 ASSERT(nmap == 1); 2936 ASSERT(map.br_startblock != DELAYSTARTBLOCK); 2937 2938 /* 2939 * If it's a hole, these are already unmapped 2940 * so there's nothing to invalidate. 2941 */ 2942 if (map.br_startblock != HOLESTARTBLOCK) { 2943 2944 dblkno = XFS_FSB_TO_DADDR(dp->i_mount, 2945 map.br_startblock); 2946 dblkcnt = XFS_FSB_TO_BB(dp->i_mount, 2947 map.br_blockcount); 2948 bp = xfs_trans_get_buf(*trans, 2949 dp->i_mount->m_ddev_targp, 2950 dblkno, dblkcnt, XBF_LOCK); 2951 xfs_trans_binval(*trans, bp); 2952 /* 2953 * Roll to next transaction. 2954 */ 2955 error = xfs_trans_roll(trans, dp); 2956 if (error) 2957 return (error); 2958 } 2959 2960 tblkno += map.br_blockcount; 2961 tblkcnt -= map.br_blockcount; 2962 } 2963 2964 return(0); 2965} 2966