1 /* 2 * Copyright (c) 2000-2001,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_format.h" 21 #include "xfs_log_format.h" 22 #include "xfs_trans_resv.h" 23 #include "xfs_mount.h" 24 #include "xfs_defer.h" 25 #include "xfs_da_format.h" 26 #include "xfs_da_btree.h" 27 #include "xfs_inode.h" 28 #include "xfs_trans.h" 29 #include "xfs_inode_item.h" 30 #include "xfs_bmap.h" 31 #include "xfs_dir2.h" 32 #include "xfs_dir2_priv.h" 33 #include "xfs_error.h" 34 #include "xfs_trace.h" 35 36 struct xfs_name xfs_name_dotdot = { (unsigned char *)"..", 2, XFS_DIR3_FT_DIR }; 37 38 /* 39 * @mode, if set, indicates that the type field needs to be set up. 40 * This uses the transformation from file mode to DT_* as defined in linux/fs.h 41 * for file type specification. This will be propagated into the directory 42 * structure if appropriate for the given operation and filesystem config. 43 */ 44 const unsigned char xfs_mode_to_ftype[S_IFMT >> S_SHIFT] = { 45 [0] = XFS_DIR3_FT_UNKNOWN, 46 [S_IFREG >> S_SHIFT] = XFS_DIR3_FT_REG_FILE, 47 [S_IFDIR >> S_SHIFT] = XFS_DIR3_FT_DIR, 48 [S_IFCHR >> S_SHIFT] = XFS_DIR3_FT_CHRDEV, 49 [S_IFBLK >> S_SHIFT] = XFS_DIR3_FT_BLKDEV, 50 [S_IFIFO >> S_SHIFT] = XFS_DIR3_FT_FIFO, 51 [S_IFSOCK >> S_SHIFT] = XFS_DIR3_FT_SOCK, 52 [S_IFLNK >> S_SHIFT] = XFS_DIR3_FT_SYMLINK, 53 }; 54 55 /* 56 * ASCII case-insensitive (ie. A-Z) support for directories that was 57 * used in IRIX. 58 */ 59 STATIC xfs_dahash_t 60 xfs_ascii_ci_hashname( 61 struct xfs_name *name) 62 { 63 xfs_dahash_t hash; 64 int i; 65 66 for (i = 0, hash = 0; i < name->len; i++) 67 hash = tolower(name->name[i]) ^ rol32(hash, 7); 68 69 return hash; 70 } 71 72 STATIC enum xfs_dacmp 73 xfs_ascii_ci_compname( 74 struct xfs_da_args *args, 75 const unsigned char *name, 76 int len) 77 { 78 enum xfs_dacmp result; 79 int i; 80 81 if (args->namelen != len) 82 return XFS_CMP_DIFFERENT; 83 84 result = XFS_CMP_EXACT; 85 for (i = 0; i < len; i++) { 86 if (args->name[i] == name[i]) 87 continue; 88 if (tolower(args->name[i]) != tolower(name[i])) 89 return XFS_CMP_DIFFERENT; 90 result = XFS_CMP_CASE; 91 } 92 93 return result; 94 } 95 96 static struct xfs_nameops xfs_ascii_ci_nameops = { 97 .hashname = xfs_ascii_ci_hashname, 98 .compname = xfs_ascii_ci_compname, 99 }; 100 101 int 102 xfs_da_mount( 103 struct xfs_mount *mp) 104 { 105 struct xfs_da_geometry *dageo; 106 int nodehdr_size; 107 108 109 ASSERT(mp->m_sb.sb_versionnum & XFS_SB_VERSION_DIRV2BIT); 110 ASSERT((1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)) <= 111 XFS_MAX_BLOCKSIZE); 112 113 mp->m_dir_inode_ops = xfs_dir_get_ops(mp, NULL); 114 mp->m_nondir_inode_ops = xfs_nondir_get_ops(mp, NULL); 115 116 nodehdr_size = mp->m_dir_inode_ops->node_hdr_size; 117 mp->m_dir_geo = kmem_zalloc(sizeof(struct xfs_da_geometry), 118 KM_SLEEP | KM_MAYFAIL); 119 mp->m_attr_geo = kmem_zalloc(sizeof(struct xfs_da_geometry), 120 KM_SLEEP | KM_MAYFAIL); 121 if (!mp->m_dir_geo || !mp->m_attr_geo) { 122 kmem_free(mp->m_dir_geo); 123 kmem_free(mp->m_attr_geo); 124 return -ENOMEM; 125 } 126 127 /* set up directory geometry */ 128 dageo = mp->m_dir_geo; 129 dageo->blklog = mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog; 130 dageo->fsblog = mp->m_sb.sb_blocklog; 131 dageo->blksize = 1 << dageo->blklog; 132 dageo->fsbcount = 1 << mp->m_sb.sb_dirblklog; 133 134 /* 135 * Now we've set up the block conversion variables, we can calculate the 136 * segment block constants using the geometry structure. 137 */ 138 dageo->datablk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_DATA_OFFSET); 139 dageo->leafblk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_LEAF_OFFSET); 140 dageo->freeblk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_FREE_OFFSET); 141 dageo->node_ents = (dageo->blksize - nodehdr_size) / 142 (uint)sizeof(xfs_da_node_entry_t); 143 dageo->magicpct = (dageo->blksize * 37) / 100; 144 145 /* set up attribute geometry - single fsb only */ 146 dageo = mp->m_attr_geo; 147 dageo->blklog = mp->m_sb.sb_blocklog; 148 dageo->fsblog = mp->m_sb.sb_blocklog; 149 dageo->blksize = 1 << dageo->blklog; 150 dageo->fsbcount = 1; 151 dageo->node_ents = (dageo->blksize - nodehdr_size) / 152 (uint)sizeof(xfs_da_node_entry_t); 153 dageo->magicpct = (dageo->blksize * 37) / 100; 154 155 if (xfs_sb_version_hasasciici(&mp->m_sb)) 156 mp->m_dirnameops = &xfs_ascii_ci_nameops; 157 else 158 mp->m_dirnameops = &xfs_default_nameops; 159 160 return 0; 161 } 162 163 void 164 xfs_da_unmount( 165 struct xfs_mount *mp) 166 { 167 kmem_free(mp->m_dir_geo); 168 kmem_free(mp->m_attr_geo); 169 } 170 171 /* 172 * Return 1 if directory contains only "." and "..". 173 */ 174 int 175 xfs_dir_isempty( 176 xfs_inode_t *dp) 177 { 178 xfs_dir2_sf_hdr_t *sfp; 179 180 ASSERT(S_ISDIR(VFS_I(dp)->i_mode)); 181 if (dp->i_d.di_size == 0) /* might happen during shutdown. */ 182 return 1; 183 if (dp->i_d.di_size > XFS_IFORK_DSIZE(dp)) 184 return 0; 185 sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; 186 return !sfp->count; 187 } 188 189 /* 190 * Validate a given inode number. 191 */ 192 int 193 xfs_dir_ino_validate( 194 xfs_mount_t *mp, 195 xfs_ino_t ino) 196 { 197 xfs_agblock_t agblkno; 198 xfs_agino_t agino; 199 xfs_agnumber_t agno; 200 int ino_ok; 201 int ioff; 202 203 agno = XFS_INO_TO_AGNO(mp, ino); 204 agblkno = XFS_INO_TO_AGBNO(mp, ino); 205 ioff = XFS_INO_TO_OFFSET(mp, ino); 206 agino = XFS_OFFBNO_TO_AGINO(mp, agblkno, ioff); 207 ino_ok = 208 agno < mp->m_sb.sb_agcount && 209 agblkno < mp->m_sb.sb_agblocks && 210 agblkno != 0 && 211 ioff < (1 << mp->m_sb.sb_inopblog) && 212 XFS_AGINO_TO_INO(mp, agno, agino) == ino; 213 if (unlikely(XFS_TEST_ERROR(!ino_ok, mp, XFS_ERRTAG_DIR_INO_VALIDATE, 214 XFS_RANDOM_DIR_INO_VALIDATE))) { 215 xfs_warn(mp, "Invalid inode number 0x%Lx", 216 (unsigned long long) ino); 217 XFS_ERROR_REPORT("xfs_dir_ino_validate", XFS_ERRLEVEL_LOW, mp); 218 return -EFSCORRUPTED; 219 } 220 return 0; 221 } 222 223 /* 224 * Initialize a directory with its "." and ".." entries. 225 */ 226 int 227 xfs_dir_init( 228 xfs_trans_t *tp, 229 xfs_inode_t *dp, 230 xfs_inode_t *pdp) 231 { 232 struct xfs_da_args *args; 233 int error; 234 235 ASSERT(S_ISDIR(VFS_I(dp)->i_mode)); 236 error = xfs_dir_ino_validate(tp->t_mountp, pdp->i_ino); 237 if (error) 238 return error; 239 240 args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS); 241 if (!args) 242 return -ENOMEM; 243 244 args->geo = dp->i_mount->m_dir_geo; 245 args->dp = dp; 246 args->trans = tp; 247 error = xfs_dir2_sf_create(args, pdp->i_ino); 248 kmem_free(args); 249 return error; 250 } 251 252 /* 253 * Enter a name in a directory, or check for available space. 254 * If inum is 0, only the available space test is performed. 255 */ 256 int 257 xfs_dir_createname( 258 xfs_trans_t *tp, 259 xfs_inode_t *dp, 260 struct xfs_name *name, 261 xfs_ino_t inum, /* new entry inode number */ 262 xfs_fsblock_t *first, /* bmap's firstblock */ 263 struct xfs_defer_ops *dfops, /* bmap's freeblock list */ 264 xfs_extlen_t total) /* bmap's total block count */ 265 { 266 struct xfs_da_args *args; 267 int rval; 268 int v; /* type-checking value */ 269 270 ASSERT(S_ISDIR(VFS_I(dp)->i_mode)); 271 if (inum) { 272 rval = xfs_dir_ino_validate(tp->t_mountp, inum); 273 if (rval) 274 return rval; 275 XFS_STATS_INC(dp->i_mount, xs_dir_create); 276 } 277 278 args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS); 279 if (!args) 280 return -ENOMEM; 281 282 args->geo = dp->i_mount->m_dir_geo; 283 args->name = name->name; 284 args->namelen = name->len; 285 args->filetype = name->type; 286 args->hashval = dp->i_mount->m_dirnameops->hashname(name); 287 args->inumber = inum; 288 args->dp = dp; 289 args->firstblock = first; 290 args->dfops = dfops; 291 args->total = total; 292 args->whichfork = XFS_DATA_FORK; 293 args->trans = tp; 294 args->op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT; 295 if (!inum) 296 args->op_flags |= XFS_DA_OP_JUSTCHECK; 297 298 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) { 299 rval = xfs_dir2_sf_addname(args); 300 goto out_free; 301 } 302 303 rval = xfs_dir2_isblock(args, &v); 304 if (rval) 305 goto out_free; 306 if (v) { 307 rval = xfs_dir2_block_addname(args); 308 goto out_free; 309 } 310 311 rval = xfs_dir2_isleaf(args, &v); 312 if (rval) 313 goto out_free; 314 if (v) 315 rval = xfs_dir2_leaf_addname(args); 316 else 317 rval = xfs_dir2_node_addname(args); 318 319 out_free: 320 kmem_free(args); 321 return rval; 322 } 323 324 /* 325 * If doing a CI lookup and case-insensitive match, dup actual name into 326 * args.value. Return EEXIST for success (ie. name found) or an error. 327 */ 328 int 329 xfs_dir_cilookup_result( 330 struct xfs_da_args *args, 331 const unsigned char *name, 332 int len) 333 { 334 if (args->cmpresult == XFS_CMP_DIFFERENT) 335 return -ENOENT; 336 if (args->cmpresult != XFS_CMP_CASE || 337 !(args->op_flags & XFS_DA_OP_CILOOKUP)) 338 return -EEXIST; 339 340 args->value = kmem_alloc(len, KM_NOFS | KM_MAYFAIL); 341 if (!args->value) 342 return -ENOMEM; 343 344 memcpy(args->value, name, len); 345 args->valuelen = len; 346 return -EEXIST; 347 } 348 349 /* 350 * Lookup a name in a directory, give back the inode number. 351 * If ci_name is not NULL, returns the actual name in ci_name if it differs 352 * to name, or ci_name->name is set to NULL for an exact match. 353 */ 354 355 int 356 xfs_dir_lookup( 357 xfs_trans_t *tp, 358 xfs_inode_t *dp, 359 struct xfs_name *name, 360 xfs_ino_t *inum, /* out: inode number */ 361 struct xfs_name *ci_name) /* out: actual name if CI match */ 362 { 363 struct xfs_da_args *args; 364 int rval; 365 int v; /* type-checking value */ 366 int lock_mode; 367 368 ASSERT(S_ISDIR(VFS_I(dp)->i_mode)); 369 XFS_STATS_INC(dp->i_mount, xs_dir_lookup); 370 371 /* 372 * We need to use KM_NOFS here so that lockdep will not throw false 373 * positive deadlock warnings on a non-transactional lookup path. It is 374 * safe to recurse into inode recalim in that case, but lockdep can't 375 * easily be taught about it. Hence KM_NOFS avoids having to add more 376 * lockdep Doing this avoids having to add a bunch of lockdep class 377 * annotations into the reclaim path for the ilock. 378 */ 379 args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS); 380 args->geo = dp->i_mount->m_dir_geo; 381 args->name = name->name; 382 args->namelen = name->len; 383 args->filetype = name->type; 384 args->hashval = dp->i_mount->m_dirnameops->hashname(name); 385 args->dp = dp; 386 args->whichfork = XFS_DATA_FORK; 387 args->trans = tp; 388 args->op_flags = XFS_DA_OP_OKNOENT; 389 if (ci_name) 390 args->op_flags |= XFS_DA_OP_CILOOKUP; 391 392 lock_mode = xfs_ilock_data_map_shared(dp); 393 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) { 394 rval = xfs_dir2_sf_lookup(args); 395 goto out_check_rval; 396 } 397 398 rval = xfs_dir2_isblock(args, &v); 399 if (rval) 400 goto out_free; 401 if (v) { 402 rval = xfs_dir2_block_lookup(args); 403 goto out_check_rval; 404 } 405 406 rval = xfs_dir2_isleaf(args, &v); 407 if (rval) 408 goto out_free; 409 if (v) 410 rval = xfs_dir2_leaf_lookup(args); 411 else 412 rval = xfs_dir2_node_lookup(args); 413 414 out_check_rval: 415 if (rval == -EEXIST) 416 rval = 0; 417 if (!rval) { 418 *inum = args->inumber; 419 if (ci_name) { 420 ci_name->name = args->value; 421 ci_name->len = args->valuelen; 422 } 423 } 424 out_free: 425 xfs_iunlock(dp, lock_mode); 426 kmem_free(args); 427 return rval; 428 } 429 430 /* 431 * Remove an entry from a directory. 432 */ 433 int 434 xfs_dir_removename( 435 xfs_trans_t *tp, 436 xfs_inode_t *dp, 437 struct xfs_name *name, 438 xfs_ino_t ino, 439 xfs_fsblock_t *first, /* bmap's firstblock */ 440 struct xfs_defer_ops *dfops, /* bmap's freeblock list */ 441 xfs_extlen_t total) /* bmap's total block count */ 442 { 443 struct xfs_da_args *args; 444 int rval; 445 int v; /* type-checking value */ 446 447 ASSERT(S_ISDIR(VFS_I(dp)->i_mode)); 448 XFS_STATS_INC(dp->i_mount, xs_dir_remove); 449 450 args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS); 451 if (!args) 452 return -ENOMEM; 453 454 args->geo = dp->i_mount->m_dir_geo; 455 args->name = name->name; 456 args->namelen = name->len; 457 args->filetype = name->type; 458 args->hashval = dp->i_mount->m_dirnameops->hashname(name); 459 args->inumber = ino; 460 args->dp = dp; 461 args->firstblock = first; 462 args->dfops = dfops; 463 args->total = total; 464 args->whichfork = XFS_DATA_FORK; 465 args->trans = tp; 466 467 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) { 468 rval = xfs_dir2_sf_removename(args); 469 goto out_free; 470 } 471 472 rval = xfs_dir2_isblock(args, &v); 473 if (rval) 474 goto out_free; 475 if (v) { 476 rval = xfs_dir2_block_removename(args); 477 goto out_free; 478 } 479 480 rval = xfs_dir2_isleaf(args, &v); 481 if (rval) 482 goto out_free; 483 if (v) 484 rval = xfs_dir2_leaf_removename(args); 485 else 486 rval = xfs_dir2_node_removename(args); 487 out_free: 488 kmem_free(args); 489 return rval; 490 } 491 492 /* 493 * Replace the inode number of a directory entry. 494 */ 495 int 496 xfs_dir_replace( 497 xfs_trans_t *tp, 498 xfs_inode_t *dp, 499 struct xfs_name *name, /* name of entry to replace */ 500 xfs_ino_t inum, /* new inode number */ 501 xfs_fsblock_t *first, /* bmap's firstblock */ 502 struct xfs_defer_ops *dfops, /* bmap's freeblock list */ 503 xfs_extlen_t total) /* bmap's total block count */ 504 { 505 struct xfs_da_args *args; 506 int rval; 507 int v; /* type-checking value */ 508 509 ASSERT(S_ISDIR(VFS_I(dp)->i_mode)); 510 511 rval = xfs_dir_ino_validate(tp->t_mountp, inum); 512 if (rval) 513 return rval; 514 515 args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS); 516 if (!args) 517 return -ENOMEM; 518 519 args->geo = dp->i_mount->m_dir_geo; 520 args->name = name->name; 521 args->namelen = name->len; 522 args->filetype = name->type; 523 args->hashval = dp->i_mount->m_dirnameops->hashname(name); 524 args->inumber = inum; 525 args->dp = dp; 526 args->firstblock = first; 527 args->dfops = dfops; 528 args->total = total; 529 args->whichfork = XFS_DATA_FORK; 530 args->trans = tp; 531 532 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) { 533 rval = xfs_dir2_sf_replace(args); 534 goto out_free; 535 } 536 537 rval = xfs_dir2_isblock(args, &v); 538 if (rval) 539 goto out_free; 540 if (v) { 541 rval = xfs_dir2_block_replace(args); 542 goto out_free; 543 } 544 545 rval = xfs_dir2_isleaf(args, &v); 546 if (rval) 547 goto out_free; 548 if (v) 549 rval = xfs_dir2_leaf_replace(args); 550 else 551 rval = xfs_dir2_node_replace(args); 552 out_free: 553 kmem_free(args); 554 return rval; 555 } 556 557 /* 558 * See if this entry can be added to the directory without allocating space. 559 */ 560 int 561 xfs_dir_canenter( 562 xfs_trans_t *tp, 563 xfs_inode_t *dp, 564 struct xfs_name *name) /* name of entry to add */ 565 { 566 return xfs_dir_createname(tp, dp, name, 0, NULL, NULL, 0); 567 } 568 569 /* 570 * Utility routines. 571 */ 572 573 /* 574 * Add a block to the directory. 575 * 576 * This routine is for data and free blocks, not leaf/node blocks which are 577 * handled by xfs_da_grow_inode. 578 */ 579 int 580 xfs_dir2_grow_inode( 581 struct xfs_da_args *args, 582 int space, /* v2 dir's space XFS_DIR2_xxx_SPACE */ 583 xfs_dir2_db_t *dbp) /* out: block number added */ 584 { 585 struct xfs_inode *dp = args->dp; 586 struct xfs_mount *mp = dp->i_mount; 587 xfs_fileoff_t bno; /* directory offset of new block */ 588 int count; /* count of filesystem blocks */ 589 int error; 590 591 trace_xfs_dir2_grow_inode(args, space); 592 593 /* 594 * Set lowest possible block in the space requested. 595 */ 596 bno = XFS_B_TO_FSBT(mp, space * XFS_DIR2_SPACE_SIZE); 597 count = args->geo->fsbcount; 598 599 error = xfs_da_grow_inode_int(args, &bno, count); 600 if (error) 601 return error; 602 603 *dbp = xfs_dir2_da_to_db(args->geo, (xfs_dablk_t)bno); 604 605 /* 606 * Update file's size if this is the data space and it grew. 607 */ 608 if (space == XFS_DIR2_DATA_SPACE) { 609 xfs_fsize_t size; /* directory file (data) size */ 610 611 size = XFS_FSB_TO_B(mp, bno + count); 612 if (size > dp->i_d.di_size) { 613 dp->i_d.di_size = size; 614 xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE); 615 } 616 } 617 return 0; 618 } 619 620 /* 621 * See if the directory is a single-block form directory. 622 */ 623 int 624 xfs_dir2_isblock( 625 struct xfs_da_args *args, 626 int *vp) /* out: 1 is block, 0 is not block */ 627 { 628 xfs_fileoff_t last; /* last file offset */ 629 int rval; 630 631 if ((rval = xfs_bmap_last_offset(args->dp, &last, XFS_DATA_FORK))) 632 return rval; 633 rval = XFS_FSB_TO_B(args->dp->i_mount, last) == args->geo->blksize; 634 ASSERT(rval == 0 || args->dp->i_d.di_size == args->geo->blksize); 635 *vp = rval; 636 return 0; 637 } 638 639 /* 640 * See if the directory is a single-leaf form directory. 641 */ 642 int 643 xfs_dir2_isleaf( 644 struct xfs_da_args *args, 645 int *vp) /* out: 1 is block, 0 is not block */ 646 { 647 xfs_fileoff_t last; /* last file offset */ 648 int rval; 649 650 if ((rval = xfs_bmap_last_offset(args->dp, &last, XFS_DATA_FORK))) 651 return rval; 652 *vp = last == args->geo->leafblk + args->geo->fsbcount; 653 return 0; 654 } 655 656 /* 657 * Remove the given block from the directory. 658 * This routine is used for data and free blocks, leaf/node are done 659 * by xfs_da_shrink_inode. 660 */ 661 int 662 xfs_dir2_shrink_inode( 663 xfs_da_args_t *args, 664 xfs_dir2_db_t db, 665 struct xfs_buf *bp) 666 { 667 xfs_fileoff_t bno; /* directory file offset */ 668 xfs_dablk_t da; /* directory file offset */ 669 int done; /* bunmap is finished */ 670 xfs_inode_t *dp; 671 int error; 672 xfs_mount_t *mp; 673 xfs_trans_t *tp; 674 675 trace_xfs_dir2_shrink_inode(args, db); 676 677 dp = args->dp; 678 mp = dp->i_mount; 679 tp = args->trans; 680 da = xfs_dir2_db_to_da(args->geo, db); 681 682 /* Unmap the fsblock(s). */ 683 error = xfs_bunmapi(tp, dp, da, args->geo->fsbcount, 0, 0, 684 args->firstblock, args->dfops, &done); 685 if (error) { 686 /* 687 * ENOSPC actually can happen if we're in a removename with no 688 * space reservation, and the resulting block removal would 689 * cause a bmap btree split or conversion from extents to btree. 690 * This can only happen for un-fragmented directory blocks, 691 * since you need to be punching out the middle of an extent. 692 * In this case we need to leave the block in the file, and not 693 * binval it. So the block has to be in a consistent empty 694 * state and appropriately logged. We don't free up the buffer, 695 * the caller can tell it hasn't happened since it got an error 696 * back. 697 */ 698 return error; 699 } 700 ASSERT(done); 701 /* 702 * Invalidate the buffer from the transaction. 703 */ 704 xfs_trans_binval(tp, bp); 705 /* 706 * If it's not a data block, we're done. 707 */ 708 if (db >= xfs_dir2_byte_to_db(args->geo, XFS_DIR2_LEAF_OFFSET)) 709 return 0; 710 /* 711 * If the block isn't the last one in the directory, we're done. 712 */ 713 if (dp->i_d.di_size > xfs_dir2_db_off_to_byte(args->geo, db + 1, 0)) 714 return 0; 715 bno = da; 716 if ((error = xfs_bmap_last_before(tp, dp, &bno, XFS_DATA_FORK))) { 717 /* 718 * This can't really happen unless there's kernel corruption. 719 */ 720 return error; 721 } 722 if (db == args->geo->datablk) 723 ASSERT(bno == 0); 724 else 725 ASSERT(bno > 0); 726 /* 727 * Set the size to the new last block. 728 */ 729 dp->i_d.di_size = XFS_FSB_TO_B(mp, bno); 730 xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE); 731 return 0; 732 } 733