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_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_dir2.h" 28#include "xfs_dmapi.h" 29#include "xfs_mount.h" 30#include "xfs_da_btree.h" 31#include "xfs_bmap_btree.h" 32#include "xfs_alloc_btree.h" 33#include "xfs_dir2_sf.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_dir2_data.h" 40#include "xfs_dir2_leaf.h" 41#include "xfs_dir2_block.h" 42#include "xfs_dir2_node.h" 43#include "xfs_dir2_trace.h" 44#include "xfs_error.h" 45 46static int xfs_dir2_put_dirent64_direct(xfs_dir2_put_args_t *pa); 47static int xfs_dir2_put_dirent64_uio(xfs_dir2_put_args_t *pa); 48 49void 50xfs_dir_mount( 51 xfs_mount_t *mp) 52{ 53 ASSERT(XFS_SB_VERSION_HASDIRV2(&mp->m_sb)); 54 ASSERT((1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)) <= 55 XFS_MAX_BLOCKSIZE); 56 mp->m_dirblksize = 1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog); 57 mp->m_dirblkfsbs = 1 << mp->m_sb.sb_dirblklog; 58 mp->m_dirdatablk = XFS_DIR2_DB_TO_DA(mp, XFS_DIR2_DATA_FIRSTDB(mp)); 59 mp->m_dirleafblk = XFS_DIR2_DB_TO_DA(mp, XFS_DIR2_LEAF_FIRSTDB(mp)); 60 mp->m_dirfreeblk = XFS_DIR2_DB_TO_DA(mp, XFS_DIR2_FREE_FIRSTDB(mp)); 61 mp->m_attr_node_ents = 62 (mp->m_sb.sb_blocksize - (uint)sizeof(xfs_da_node_hdr_t)) / 63 (uint)sizeof(xfs_da_node_entry_t); 64 mp->m_dir_node_ents = 65 (mp->m_dirblksize - (uint)sizeof(xfs_da_node_hdr_t)) / 66 (uint)sizeof(xfs_da_node_entry_t); 67 mp->m_dir_magicpct = (mp->m_dirblksize * 37) / 100; 68} 69 70/* 71 * Return 1 if directory contains only "." and "..". 72 */ 73int 74xfs_dir_isempty( 75 xfs_inode_t *dp) 76{ 77 xfs_dir2_sf_t *sfp; 78 79 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); 80 if (dp->i_d.di_size == 0) /* might happen during shutdown. */ 81 return 1; 82 if (dp->i_d.di_size > XFS_IFORK_DSIZE(dp)) 83 return 0; 84 sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data; 85 return !sfp->hdr.count; 86} 87 88/* 89 * Validate a given inode number. 90 */ 91int 92xfs_dir_ino_validate( 93 xfs_mount_t *mp, 94 xfs_ino_t ino) 95{ 96 xfs_agblock_t agblkno; 97 xfs_agino_t agino; 98 xfs_agnumber_t agno; 99 int ino_ok; 100 int ioff; 101 102 agno = XFS_INO_TO_AGNO(mp, ino); 103 agblkno = XFS_INO_TO_AGBNO(mp, ino); 104 ioff = XFS_INO_TO_OFFSET(mp, ino); 105 agino = XFS_OFFBNO_TO_AGINO(mp, agblkno, ioff); 106 ino_ok = 107 agno < mp->m_sb.sb_agcount && 108 agblkno < mp->m_sb.sb_agblocks && 109 agblkno != 0 && 110 ioff < (1 << mp->m_sb.sb_inopblog) && 111 XFS_AGINO_TO_INO(mp, agno, agino) == ino; 112 if (unlikely(XFS_TEST_ERROR(!ino_ok, mp, XFS_ERRTAG_DIR_INO_VALIDATE, 113 XFS_RANDOM_DIR_INO_VALIDATE))) { 114 xfs_fs_cmn_err(CE_WARN, mp, "Invalid inode number 0x%Lx", 115 (unsigned long long) ino); 116 XFS_ERROR_REPORT("xfs_dir_ino_validate", XFS_ERRLEVEL_LOW, mp); 117 return XFS_ERROR(EFSCORRUPTED); 118 } 119 return 0; 120} 121 122/* 123 * Initialize a directory with its "." and ".." entries. 124 */ 125int 126xfs_dir_init( 127 xfs_trans_t *tp, 128 xfs_inode_t *dp, 129 xfs_inode_t *pdp) 130{ 131 xfs_da_args_t args; 132 int error; 133 134 memset((char *)&args, 0, sizeof(args)); 135 args.dp = dp; 136 args.trans = tp; 137 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); 138 if ((error = xfs_dir_ino_validate(tp->t_mountp, pdp->i_ino))) 139 return error; 140 return xfs_dir2_sf_create(&args, pdp->i_ino); 141} 142 143/* 144 Enter a name in a directory. 145 */ 146int 147xfs_dir_createname( 148 xfs_trans_t *tp, 149 xfs_inode_t *dp, 150 char *name, 151 int namelen, 152 xfs_ino_t inum, /* new entry inode number */ 153 xfs_fsblock_t *first, /* bmap's firstblock */ 154 xfs_bmap_free_t *flist, /* bmap's freeblock list */ 155 xfs_extlen_t total) /* bmap's total block count */ 156{ 157 xfs_da_args_t args; 158 int rval; 159 int v; /* type-checking value */ 160 161 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); 162 if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum))) 163 return rval; 164 XFS_STATS_INC(xs_dir_create); 165 166 args.name = name; 167 args.namelen = namelen; 168 args.hashval = xfs_da_hashname(name, namelen); 169 args.inumber = inum; 170 args.dp = dp; 171 args.firstblock = first; 172 args.flist = flist; 173 args.total = total; 174 args.whichfork = XFS_DATA_FORK; 175 args.trans = tp; 176 args.justcheck = 0; 177 args.addname = args.oknoent = 1; 178 179 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) 180 rval = xfs_dir2_sf_addname(&args); 181 else if ((rval = xfs_dir2_isblock(tp, dp, &v))) 182 return rval; 183 else if (v) 184 rval = xfs_dir2_block_addname(&args); 185 else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) 186 return rval; 187 else if (v) 188 rval = xfs_dir2_leaf_addname(&args); 189 else 190 rval = xfs_dir2_node_addname(&args); 191 return rval; 192} 193 194/* 195 * Lookup a name in a directory, give back the inode number. 196 */ 197int 198xfs_dir_lookup( 199 xfs_trans_t *tp, 200 xfs_inode_t *dp, 201 char *name, 202 int namelen, 203 xfs_ino_t *inum) /* out: inode number */ 204{ 205 xfs_da_args_t args; 206 int rval; 207 int v; /* type-checking value */ 208 209 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); 210 XFS_STATS_INC(xs_dir_lookup); 211 212 args.name = name; 213 args.namelen = namelen; 214 args.hashval = xfs_da_hashname(name, namelen); 215 args.inumber = 0; 216 args.dp = dp; 217 args.firstblock = NULL; 218 args.flist = NULL; 219 args.total = 0; 220 args.whichfork = XFS_DATA_FORK; 221 args.trans = tp; 222 args.justcheck = args.addname = 0; 223 args.oknoent = 1; 224 225 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) 226 rval = xfs_dir2_sf_lookup(&args); 227 else if ((rval = xfs_dir2_isblock(tp, dp, &v))) 228 return rval; 229 else if (v) 230 rval = xfs_dir2_block_lookup(&args); 231 else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) 232 return rval; 233 else if (v) 234 rval = xfs_dir2_leaf_lookup(&args); 235 else 236 rval = xfs_dir2_node_lookup(&args); 237 if (rval == EEXIST) 238 rval = 0; 239 if (rval == 0) 240 *inum = args.inumber; 241 return rval; 242} 243 244/* 245 * Remove an entry from a directory. 246 */ 247int 248xfs_dir_removename( 249 xfs_trans_t *tp, 250 xfs_inode_t *dp, 251 char *name, 252 int namelen, 253 xfs_ino_t ino, 254 xfs_fsblock_t *first, /* bmap's firstblock */ 255 xfs_bmap_free_t *flist, /* bmap's freeblock list */ 256 xfs_extlen_t total) /* bmap's total block count */ 257{ 258 xfs_da_args_t args; 259 int rval; 260 int v; /* type-checking value */ 261 262 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); 263 XFS_STATS_INC(xs_dir_remove); 264 265 args.name = name; 266 args.namelen = namelen; 267 args.hashval = xfs_da_hashname(name, namelen); 268 args.inumber = ino; 269 args.dp = dp; 270 args.firstblock = first; 271 args.flist = flist; 272 args.total = total; 273 args.whichfork = XFS_DATA_FORK; 274 args.trans = tp; 275 args.justcheck = args.addname = args.oknoent = 0; 276 277 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) 278 rval = xfs_dir2_sf_removename(&args); 279 else if ((rval = xfs_dir2_isblock(tp, dp, &v))) 280 return rval; 281 else if (v) 282 rval = xfs_dir2_block_removename(&args); 283 else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) 284 return rval; 285 else if (v) 286 rval = xfs_dir2_leaf_removename(&args); 287 else 288 rval = xfs_dir2_node_removename(&args); 289 return rval; 290} 291 292/* 293 * Read a directory. 294 */ 295int 296xfs_dir_getdents( 297 xfs_trans_t *tp, 298 xfs_inode_t *dp, 299 uio_t *uio, /* caller's buffer control */ 300 int *eofp) /* out: eof reached */ 301{ 302 int alignment; /* alignment required for ABI */ 303 xfs_dirent_t *dbp; /* malloc'ed buffer */ 304 xfs_dir2_put_t put; /* entry formatting routine */ 305 int rval; /* return value */ 306 int v; /* type-checking value */ 307 308 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); 309 XFS_STATS_INC(xs_dir_getdents); 310 /* 311 * If our caller has given us a single contiguous aligned memory buffer, 312 * just work directly within that buffer. If it's in user memory, 313 * lock it down first. 314 */ 315 alignment = sizeof(xfs_off_t) - 1; 316 if ((uio->uio_iovcnt == 1) && 317 (((__psint_t)uio->uio_iov[0].iov_base & alignment) == 0) && 318 ((uio->uio_iov[0].iov_len & alignment) == 0)) { 319 dbp = NULL; 320 put = xfs_dir2_put_dirent64_direct; 321 } else { 322 dbp = kmem_alloc(sizeof(*dbp) + MAXNAMELEN, KM_SLEEP); 323 put = xfs_dir2_put_dirent64_uio; 324 } 325 326 *eofp = 0; 327 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) 328 rval = xfs_dir2_sf_getdents(dp, uio, eofp, dbp, put); 329 else if ((rval = xfs_dir2_isblock(tp, dp, &v))) 330 ; 331 else if (v) 332 rval = xfs_dir2_block_getdents(tp, dp, uio, eofp, dbp, put); 333 else 334 rval = xfs_dir2_leaf_getdents(tp, dp, uio, eofp, dbp, put); 335 if (dbp != NULL) 336 kmem_free(dbp, sizeof(*dbp) + MAXNAMELEN); 337 return rval; 338} 339 340/* 341 * Replace the inode number of a directory entry. 342 */ 343int 344xfs_dir_replace( 345 xfs_trans_t *tp, 346 xfs_inode_t *dp, 347 char *name, /* name of entry to replace */ 348 int namelen, 349 xfs_ino_t inum, /* new inode number */ 350 xfs_fsblock_t *first, /* bmap's firstblock */ 351 xfs_bmap_free_t *flist, /* bmap's freeblock list */ 352 xfs_extlen_t total) /* bmap's total block count */ 353{ 354 xfs_da_args_t args; 355 int rval; 356 int v; /* type-checking value */ 357 358 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); 359 360 if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum))) 361 return rval; 362 363 args.name = name; 364 args.namelen = namelen; 365 args.hashval = xfs_da_hashname(name, namelen); 366 args.inumber = inum; 367 args.dp = dp; 368 args.firstblock = first; 369 args.flist = flist; 370 args.total = total; 371 args.whichfork = XFS_DATA_FORK; 372 args.trans = tp; 373 args.justcheck = args.addname = args.oknoent = 0; 374 375 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) 376 rval = xfs_dir2_sf_replace(&args); 377 else if ((rval = xfs_dir2_isblock(tp, dp, &v))) 378 return rval; 379 else if (v) 380 rval = xfs_dir2_block_replace(&args); 381 else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) 382 return rval; 383 else if (v) 384 rval = xfs_dir2_leaf_replace(&args); 385 else 386 rval = xfs_dir2_node_replace(&args); 387 return rval; 388} 389 390/* 391 * See if this entry can be added to the directory without allocating space. 392 */ 393int 394xfs_dir_canenter( 395 xfs_trans_t *tp, 396 xfs_inode_t *dp, 397 char *name, /* name of entry to add */ 398 int namelen) 399{ 400 xfs_da_args_t args; 401 int rval; 402 int v; /* type-checking value */ 403 404 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); 405 406 args.name = name; 407 args.namelen = namelen; 408 args.hashval = xfs_da_hashname(name, namelen); 409 args.inumber = 0; 410 args.dp = dp; 411 args.firstblock = NULL; 412 args.flist = NULL; 413 args.total = 0; 414 args.whichfork = XFS_DATA_FORK; 415 args.trans = tp; 416 args.justcheck = args.addname = args.oknoent = 1; 417 418 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) 419 rval = xfs_dir2_sf_addname(&args); 420 else if ((rval = xfs_dir2_isblock(tp, dp, &v))) 421 return rval; 422 else if (v) 423 rval = xfs_dir2_block_addname(&args); 424 else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) 425 return rval; 426 else if (v) 427 rval = xfs_dir2_leaf_addname(&args); 428 else 429 rval = xfs_dir2_node_addname(&args); 430 return rval; 431} 432 433/* 434 * Utility routines. 435 */ 436 437/* 438 * Add a block to the directory. 439 * This routine is for data and free blocks, not leaf/node blocks 440 * which are handled by xfs_da_grow_inode. 441 */ 442int 443xfs_dir2_grow_inode( 444 xfs_da_args_t *args, 445 int space, /* v2 dir's space XFS_DIR2_xxx_SPACE */ 446 xfs_dir2_db_t *dbp) /* out: block number added */ 447{ 448 xfs_fileoff_t bno; /* directory offset of new block */ 449 int count; /* count of filesystem blocks */ 450 xfs_inode_t *dp; /* incore directory inode */ 451 int error; 452 int got; /* blocks actually mapped */ 453 int i; 454 xfs_bmbt_irec_t map; /* single structure for bmap */ 455 int mapi; /* mapping index */ 456 xfs_bmbt_irec_t *mapp; /* bmap mapping structure(s) */ 457 xfs_mount_t *mp; 458 int nmap; /* number of bmap entries */ 459 xfs_trans_t *tp; 460 461 xfs_dir2_trace_args_s("grow_inode", args, space); 462 dp = args->dp; 463 tp = args->trans; 464 mp = dp->i_mount; 465 /* 466 * Set lowest possible block in the space requested. 467 */ 468 bno = XFS_B_TO_FSBT(mp, space * XFS_DIR2_SPACE_SIZE); 469 count = mp->m_dirblkfsbs; 470 /* 471 * Find the first hole for our block. 472 */ 473 if ((error = xfs_bmap_first_unused(tp, dp, count, &bno, XFS_DATA_FORK))) 474 return error; 475 nmap = 1; 476 ASSERT(args->firstblock != NULL); 477 /* 478 * Try mapping the new block contiguously (one extent). 479 */ 480 if ((error = xfs_bmapi(tp, dp, bno, count, 481 XFS_BMAPI_WRITE|XFS_BMAPI_METADATA|XFS_BMAPI_CONTIG, 482 args->firstblock, args->total, &map, &nmap, 483 args->flist, NULL))) 484 return error; 485 ASSERT(nmap <= 1); 486 if (nmap == 1) { 487 mapp = ↦ 488 mapi = 1; 489 } 490 /* 491 * Didn't work and this is a multiple-fsb directory block. 492 * Try again with contiguous flag turned on. 493 */ 494 else if (nmap == 0 && count > 1) { 495 xfs_fileoff_t b; /* current file offset */ 496 497 /* 498 * Space for maximum number of mappings. 499 */ 500 mapp = kmem_alloc(sizeof(*mapp) * count, KM_SLEEP); 501 /* 502 * Iterate until we get to the end of our block. 503 */ 504 for (b = bno, mapi = 0; b < bno + count; ) { 505 int c; /* current fsb count */ 506 507 /* 508 * Can't map more than MAX_NMAP at once. 509 */ 510 nmap = MIN(XFS_BMAP_MAX_NMAP, count); 511 c = (int)(bno + count - b); 512 if ((error = xfs_bmapi(tp, dp, b, c, 513 XFS_BMAPI_WRITE|XFS_BMAPI_METADATA, 514 args->firstblock, args->total, 515 &mapp[mapi], &nmap, args->flist, 516 NULL))) { 517 kmem_free(mapp, sizeof(*mapp) * count); 518 return error; 519 } 520 if (nmap < 1) 521 break; 522 /* 523 * Add this bunch into our table, go to the next offset. 524 */ 525 mapi += nmap; 526 b = mapp[mapi - 1].br_startoff + 527 mapp[mapi - 1].br_blockcount; 528 } 529 } 530 /* 531 * Didn't work. 532 */ 533 else { 534 mapi = 0; 535 mapp = NULL; 536 } 537 /* 538 * See how many fsb's we got. 539 */ 540 for (i = 0, got = 0; i < mapi; i++) 541 got += mapp[i].br_blockcount; 542 /* 543 * Didn't get enough fsb's, or the first/last block's are wrong. 544 */ 545 if (got != count || mapp[0].br_startoff != bno || 546 mapp[mapi - 1].br_startoff + mapp[mapi - 1].br_blockcount != 547 bno + count) { 548 if (mapp != &map) 549 kmem_free(mapp, sizeof(*mapp) * count); 550 return XFS_ERROR(ENOSPC); 551 } 552 /* 553 * Done with the temporary mapping table. 554 */ 555 if (mapp != &map) 556 kmem_free(mapp, sizeof(*mapp) * count); 557 *dbp = XFS_DIR2_DA_TO_DB(mp, (xfs_dablk_t)bno); 558 /* 559 * Update file's size if this is the data space and it grew. 560 */ 561 if (space == XFS_DIR2_DATA_SPACE) { 562 xfs_fsize_t size; /* directory file (data) size */ 563 564 size = XFS_FSB_TO_B(mp, bno + count); 565 if (size > dp->i_d.di_size) { 566 dp->i_d.di_size = size; 567 xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE); 568 } 569 } 570 return 0; 571} 572 573/* 574 * See if the directory is a single-block form directory. 575 */ 576int 577xfs_dir2_isblock( 578 xfs_trans_t *tp, 579 xfs_inode_t *dp, 580 int *vp) /* out: 1 is block, 0 is not block */ 581{ 582 xfs_fileoff_t last; /* last file offset */ 583 xfs_mount_t *mp; 584 int rval; 585 586 mp = dp->i_mount; 587 if ((rval = xfs_bmap_last_offset(tp, dp, &last, XFS_DATA_FORK))) 588 return rval; 589 rval = XFS_FSB_TO_B(mp, last) == mp->m_dirblksize; 590 ASSERT(rval == 0 || dp->i_d.di_size == mp->m_dirblksize); 591 *vp = rval; 592 return 0; 593} 594 595/* 596 * See if the directory is a single-leaf form directory. 597 */ 598int 599xfs_dir2_isleaf( 600 xfs_trans_t *tp, 601 xfs_inode_t *dp, 602 int *vp) /* out: 1 is leaf, 0 is not leaf */ 603{ 604 xfs_fileoff_t last; /* last file offset */ 605 xfs_mount_t *mp; 606 int rval; 607 608 mp = dp->i_mount; 609 if ((rval = xfs_bmap_last_offset(tp, dp, &last, XFS_DATA_FORK))) 610 return rval; 611 *vp = last == mp->m_dirleafblk + (1 << mp->m_sb.sb_dirblklog); 612 return 0; 613} 614 615/* 616 * Getdents put routine for 64-bit ABI, direct form. 617 */ 618static int 619xfs_dir2_put_dirent64_direct( 620 xfs_dir2_put_args_t *pa) 621{ 622 xfs_dirent_t *idbp; /* dirent pointer */ 623 iovec_t *iovp; /* io vector */ 624 int namelen; /* entry name length */ 625 int reclen; /* entry total length */ 626 uio_t *uio; /* I/O control */ 627 628 namelen = pa->namelen; 629 reclen = DIRENTSIZE(namelen); 630 uio = pa->uio; 631 /* 632 * Won't fit in the remaining space. 633 */ 634 if (reclen > uio->uio_resid) { 635 pa->done = 0; 636 return 0; 637 } 638 iovp = uio->uio_iov; 639 idbp = (xfs_dirent_t *)iovp->iov_base; 640 iovp->iov_base = (char *)idbp + reclen; 641 iovp->iov_len -= reclen; 642 uio->uio_resid -= reclen; 643 idbp->d_reclen = reclen; 644 idbp->d_ino = pa->ino; 645 idbp->d_off = pa->cook; 646 idbp->d_name[namelen] = '\0'; 647 pa->done = 1; 648 memcpy(idbp->d_name, pa->name, namelen); 649 return 0; 650} 651 652/* 653 * Getdents put routine for 64-bit ABI, uio form. 654 */ 655static int 656xfs_dir2_put_dirent64_uio( 657 xfs_dir2_put_args_t *pa) 658{ 659 xfs_dirent_t *idbp; /* dirent pointer */ 660 int namelen; /* entry name length */ 661 int reclen; /* entry total length */ 662 int rval; /* return value */ 663 uio_t *uio; /* I/O control */ 664 665 namelen = pa->namelen; 666 reclen = DIRENTSIZE(namelen); 667 uio = pa->uio; 668 /* 669 * Won't fit in the remaining space. 670 */ 671 if (reclen > uio->uio_resid) { 672 pa->done = 0; 673 return 0; 674 } 675 idbp = pa->dbp; 676 idbp->d_reclen = reclen; 677 idbp->d_ino = pa->ino; 678 idbp->d_off = pa->cook; 679 idbp->d_name[namelen] = '\0'; 680 memcpy(idbp->d_name, pa->name, namelen); 681 rval = xfs_uio_read((caddr_t)idbp, reclen, uio); 682 pa->done = (rval == 0); 683 return rval; 684} 685 686/* 687 * Remove the given block from the directory. 688 * This routine is used for data and free blocks, leaf/node are done 689 * by xfs_da_shrink_inode. 690 */ 691int 692xfs_dir2_shrink_inode( 693 xfs_da_args_t *args, 694 xfs_dir2_db_t db, 695 xfs_dabuf_t *bp) 696{ 697 xfs_fileoff_t bno; /* directory file offset */ 698 xfs_dablk_t da; /* directory file offset */ 699 int done; /* bunmap is finished */ 700 xfs_inode_t *dp; 701 int error; 702 xfs_mount_t *mp; 703 xfs_trans_t *tp; 704 705 xfs_dir2_trace_args_db("shrink_inode", args, db, bp); 706 dp = args->dp; 707 mp = dp->i_mount; 708 tp = args->trans; 709 da = XFS_DIR2_DB_TO_DA(mp, db); 710 /* 711 * Unmap the fsblock(s). 712 */ 713 if ((error = xfs_bunmapi(tp, dp, da, mp->m_dirblkfsbs, 714 XFS_BMAPI_METADATA, 0, args->firstblock, args->flist, 715 NULL, &done))) { 716 /* 717 * ENOSPC actually can happen if we're in a removename with 718 * no space reservation, and the resulting block removal 719 * would cause a bmap btree split or conversion from extents 720 * to btree. This can only happen for un-fragmented 721 * directory blocks, since you need to be punching out 722 * the middle of an extent. 723 * In this case we need to leave the block in the file, 724 * and not binval it. 725 * So the block has to be in a consistent empty state 726 * and appropriately logged. 727 * We don't free up the buffer, the caller can tell it 728 * hasn't happened since it got an error back. 729 */ 730 return error; 731 } 732 ASSERT(done); 733 /* 734 * Invalidate the buffer from the transaction. 735 */ 736 xfs_da_binval(tp, bp); 737 /* 738 * If it's not a data block, we're done. 739 */ 740 if (db >= XFS_DIR2_LEAF_FIRSTDB(mp)) 741 return 0; 742 /* 743 * If the block isn't the last one in the directory, we're done. 744 */ 745 if (dp->i_d.di_size > XFS_DIR2_DB_OFF_TO_BYTE(mp, db + 1, 0)) 746 return 0; 747 bno = da; 748 if ((error = xfs_bmap_last_before(tp, dp, &bno, XFS_DATA_FORK))) { 749 /* 750 * This can't really happen unless there's kernel corruption. 751 */ 752 return error; 753 } 754 if (db == mp->m_dirdatablk) 755 ASSERT(bno == 0); 756 else 757 ASSERT(bno > 0); 758 /* 759 * Set the size to the new last block. 760 */ 761 dp->i_d.di_size = XFS_FSB_TO_B(mp, bno); 762 xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE); 763 return 0; 764} 765