1 /* 2 * Copyright (c) 2000-2005 Silicon Graphics, Inc. 3 * Copyright (c) 2013 Red Hat, Inc. 4 * All Rights Reserved. 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it would be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 */ 19 #include "xfs.h" 20 #include "xfs_fs.h" 21 #include "xfs_types.h" 22 #include "xfs_bit.h" 23 #include "xfs_log.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_dinode.h" 31 #include "xfs_inode.h" 32 #include "xfs_dir2_format.h" 33 #include "xfs_dir2.h" 34 #include "xfs_dir2_priv.h" 35 #include "xfs_error.h" 36 #include "xfs_trace.h" 37 #include "xfs_bmap.h" 38 39 /* 40 * Directory file type support functions 41 */ 42 static unsigned char xfs_dir3_filetype_table[] = { 43 DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, 44 DT_FIFO, DT_SOCK, DT_LNK, DT_WHT, 45 }; 46 47 unsigned char 48 xfs_dir3_get_dtype( 49 struct xfs_mount *mp, 50 __uint8_t filetype) 51 { 52 if (!xfs_sb_version_hasftype(&mp->m_sb)) 53 return DT_UNKNOWN; 54 55 if (filetype >= XFS_DIR3_FT_MAX) 56 return DT_UNKNOWN; 57 58 return xfs_dir3_filetype_table[filetype]; 59 } 60 /* 61 * @mode, if set, indicates that the type field needs to be set up. 62 * This uses the transformation from file mode to DT_* as defined in linux/fs.h 63 * for file type specification. This will be propagated into the directory 64 * structure if appropriate for the given operation and filesystem config. 65 */ 66 const unsigned char xfs_mode_to_ftype[S_IFMT >> S_SHIFT] = { 67 [0] = XFS_DIR3_FT_UNKNOWN, 68 [S_IFREG >> S_SHIFT] = XFS_DIR3_FT_REG_FILE, 69 [S_IFDIR >> S_SHIFT] = XFS_DIR3_FT_DIR, 70 [S_IFCHR >> S_SHIFT] = XFS_DIR3_FT_CHRDEV, 71 [S_IFBLK >> S_SHIFT] = XFS_DIR3_FT_BLKDEV, 72 [S_IFIFO >> S_SHIFT] = XFS_DIR3_FT_FIFO, 73 [S_IFSOCK >> S_SHIFT] = XFS_DIR3_FT_SOCK, 74 [S_IFLNK >> S_SHIFT] = XFS_DIR3_FT_SYMLINK, 75 }; 76 77 STATIC int 78 xfs_dir2_sf_getdents( 79 xfs_inode_t *dp, /* incore directory inode */ 80 struct dir_context *ctx) 81 { 82 int i; /* shortform entry number */ 83 xfs_mount_t *mp; /* filesystem mount point */ 84 xfs_dir2_dataptr_t off; /* current entry's offset */ 85 xfs_dir2_sf_entry_t *sfep; /* shortform directory entry */ 86 xfs_dir2_sf_hdr_t *sfp; /* shortform structure */ 87 xfs_dir2_dataptr_t dot_offset; 88 xfs_dir2_dataptr_t dotdot_offset; 89 xfs_ino_t ino; 90 91 mp = dp->i_mount; 92 93 ASSERT(dp->i_df.if_flags & XFS_IFINLINE); 94 /* 95 * Give up if the directory is way too short. 96 */ 97 if (dp->i_d.di_size < offsetof(xfs_dir2_sf_hdr_t, parent)) { 98 ASSERT(XFS_FORCED_SHUTDOWN(mp)); 99 return XFS_ERROR(EIO); 100 } 101 102 ASSERT(dp->i_df.if_bytes == dp->i_d.di_size); 103 ASSERT(dp->i_df.if_u1.if_data != NULL); 104 105 sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; 106 107 ASSERT(dp->i_d.di_size >= xfs_dir2_sf_hdr_size(sfp->i8count)); 108 109 /* 110 * If the block number in the offset is out of range, we're done. 111 */ 112 if (xfs_dir2_dataptr_to_db(mp, ctx->pos) > mp->m_dirdatablk) 113 return 0; 114 115 /* 116 * Precalculate offsets for . and .. as we will always need them. 117 * 118 * XXX(hch): the second argument is sometimes 0 and sometimes 119 * mp->m_dirdatablk. 120 */ 121 dot_offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk, 122 xfs_dir3_data_dot_offset(mp)); 123 dotdot_offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk, 124 xfs_dir3_data_dotdot_offset(mp)); 125 126 /* 127 * Put . entry unless we're starting past it. 128 */ 129 if (ctx->pos <= dot_offset) { 130 ctx->pos = dot_offset & 0x7fffffff; 131 if (!dir_emit(ctx, ".", 1, dp->i_ino, DT_DIR)) 132 return 0; 133 } 134 135 /* 136 * Put .. entry unless we're starting past it. 137 */ 138 if (ctx->pos <= dotdot_offset) { 139 ino = xfs_dir2_sf_get_parent_ino(sfp); 140 ctx->pos = dotdot_offset & 0x7fffffff; 141 if (!dir_emit(ctx, "..", 2, ino, DT_DIR)) 142 return 0; 143 } 144 145 /* 146 * Loop while there are more entries and put'ing works. 147 */ 148 sfep = xfs_dir2_sf_firstentry(sfp); 149 for (i = 0; i < sfp->count; i++) { 150 __uint8_t filetype; 151 152 off = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk, 153 xfs_dir2_sf_get_offset(sfep)); 154 155 if (ctx->pos > off) { 156 sfep = xfs_dir3_sf_nextentry(mp, sfp, sfep); 157 continue; 158 } 159 160 ino = xfs_dir3_sfe_get_ino(mp, sfp, sfep); 161 filetype = xfs_dir3_sfe_get_ftype(mp, sfp, sfep); 162 ctx->pos = off & 0x7fffffff; 163 if (!dir_emit(ctx, (char *)sfep->name, sfep->namelen, ino, 164 xfs_dir3_get_dtype(mp, filetype))) 165 return 0; 166 sfep = xfs_dir3_sf_nextentry(mp, sfp, sfep); 167 } 168 169 ctx->pos = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk + 1, 0) & 170 0x7fffffff; 171 return 0; 172 } 173 174 /* 175 * Readdir for block directories. 176 */ 177 STATIC int 178 xfs_dir2_block_getdents( 179 xfs_inode_t *dp, /* incore inode */ 180 struct dir_context *ctx) 181 { 182 xfs_dir2_data_hdr_t *hdr; /* block header */ 183 struct xfs_buf *bp; /* buffer for block */ 184 xfs_dir2_block_tail_t *btp; /* block tail */ 185 xfs_dir2_data_entry_t *dep; /* block data entry */ 186 xfs_dir2_data_unused_t *dup; /* block unused entry */ 187 char *endptr; /* end of the data entries */ 188 int error; /* error return value */ 189 xfs_mount_t *mp; /* filesystem mount point */ 190 char *ptr; /* current data entry */ 191 int wantoff; /* starting block offset */ 192 xfs_off_t cook; 193 194 mp = dp->i_mount; 195 /* 196 * If the block number in the offset is out of range, we're done. 197 */ 198 if (xfs_dir2_dataptr_to_db(mp, ctx->pos) > mp->m_dirdatablk) 199 return 0; 200 201 error = xfs_dir3_block_read(NULL, dp, &bp); 202 if (error) 203 return error; 204 205 /* 206 * Extract the byte offset we start at from the seek pointer. 207 * We'll skip entries before this. 208 */ 209 wantoff = xfs_dir2_dataptr_to_off(mp, ctx->pos); 210 hdr = bp->b_addr; 211 xfs_dir3_data_check(dp, bp); 212 /* 213 * Set up values for the loop. 214 */ 215 btp = xfs_dir2_block_tail_p(mp, hdr); 216 ptr = (char *)xfs_dir3_data_entry_p(hdr); 217 endptr = (char *)xfs_dir2_block_leaf_p(btp); 218 219 /* 220 * Loop over the data portion of the block. 221 * Each object is a real entry (dep) or an unused one (dup). 222 */ 223 while (ptr < endptr) { 224 __uint8_t filetype; 225 226 dup = (xfs_dir2_data_unused_t *)ptr; 227 /* 228 * Unused, skip it. 229 */ 230 if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) { 231 ptr += be16_to_cpu(dup->length); 232 continue; 233 } 234 235 dep = (xfs_dir2_data_entry_t *)ptr; 236 237 /* 238 * Bump pointer for the next iteration. 239 */ 240 ptr += xfs_dir3_data_entsize(mp, dep->namelen); 241 /* 242 * The entry is before the desired starting point, skip it. 243 */ 244 if ((char *)dep - (char *)hdr < wantoff) 245 continue; 246 247 cook = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk, 248 (char *)dep - (char *)hdr); 249 250 ctx->pos = cook & 0x7fffffff; 251 filetype = xfs_dir3_dirent_get_ftype(mp, dep); 252 /* 253 * If it didn't fit, set the final offset to here & return. 254 */ 255 if (!dir_emit(ctx, (char *)dep->name, dep->namelen, 256 be64_to_cpu(dep->inumber), 257 xfs_dir3_get_dtype(mp, filetype))) { 258 xfs_trans_brelse(NULL, bp); 259 return 0; 260 } 261 } 262 263 /* 264 * Reached the end of the block. 265 * Set the offset to a non-existent block 1 and return. 266 */ 267 ctx->pos = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk + 1, 0) & 268 0x7fffffff; 269 xfs_trans_brelse(NULL, bp); 270 return 0; 271 } 272 273 struct xfs_dir2_leaf_map_info { 274 xfs_extlen_t map_blocks; /* number of fsbs in map */ 275 xfs_dablk_t map_off; /* last mapped file offset */ 276 int map_size; /* total entries in *map */ 277 int map_valid; /* valid entries in *map */ 278 int nmap; /* mappings to ask xfs_bmapi */ 279 xfs_dir2_db_t curdb; /* db for current block */ 280 int ra_current; /* number of read-ahead blks */ 281 int ra_index; /* *map index for read-ahead */ 282 int ra_offset; /* map entry offset for ra */ 283 int ra_want; /* readahead count wanted */ 284 struct xfs_bmbt_irec map[]; /* map vector for blocks */ 285 }; 286 287 STATIC int 288 xfs_dir2_leaf_readbuf( 289 struct xfs_inode *dp, 290 size_t bufsize, 291 struct xfs_dir2_leaf_map_info *mip, 292 xfs_dir2_off_t *curoff, 293 struct xfs_buf **bpp) 294 { 295 struct xfs_mount *mp = dp->i_mount; 296 struct xfs_buf *bp = *bpp; 297 struct xfs_bmbt_irec *map = mip->map; 298 struct blk_plug plug; 299 int error = 0; 300 int length; 301 int i; 302 int j; 303 304 /* 305 * If we have a buffer, we need to release it and 306 * take it out of the mapping. 307 */ 308 309 if (bp) { 310 xfs_trans_brelse(NULL, bp); 311 bp = NULL; 312 mip->map_blocks -= mp->m_dirblkfsbs; 313 /* 314 * Loop to get rid of the extents for the 315 * directory block. 316 */ 317 for (i = mp->m_dirblkfsbs; i > 0; ) { 318 j = min_t(int, map->br_blockcount, i); 319 map->br_blockcount -= j; 320 map->br_startblock += j; 321 map->br_startoff += j; 322 /* 323 * If mapping is done, pitch it from 324 * the table. 325 */ 326 if (!map->br_blockcount && --mip->map_valid) 327 memmove(&map[0], &map[1], 328 sizeof(map[0]) * mip->map_valid); 329 i -= j; 330 } 331 } 332 333 /* 334 * Recalculate the readahead blocks wanted. 335 */ 336 mip->ra_want = howmany(bufsize + mp->m_dirblksize, 337 mp->m_sb.sb_blocksize) - 1; 338 ASSERT(mip->ra_want >= 0); 339 340 /* 341 * If we don't have as many as we want, and we haven't 342 * run out of data blocks, get some more mappings. 343 */ 344 if (1 + mip->ra_want > mip->map_blocks && 345 mip->map_off < xfs_dir2_byte_to_da(mp, XFS_DIR2_LEAF_OFFSET)) { 346 /* 347 * Get more bmaps, fill in after the ones 348 * we already have in the table. 349 */ 350 mip->nmap = mip->map_size - mip->map_valid; 351 error = xfs_bmapi_read(dp, mip->map_off, 352 xfs_dir2_byte_to_da(mp, XFS_DIR2_LEAF_OFFSET) - 353 mip->map_off, 354 &map[mip->map_valid], &mip->nmap, 0); 355 356 /* 357 * Don't know if we should ignore this or try to return an 358 * error. The trouble with returning errors is that readdir 359 * will just stop without actually passing the error through. 360 */ 361 if (error) 362 goto out; /* XXX */ 363 364 /* 365 * If we got all the mappings we asked for, set the final map 366 * offset based on the last bmap value received. Otherwise, 367 * we've reached the end. 368 */ 369 if (mip->nmap == mip->map_size - mip->map_valid) { 370 i = mip->map_valid + mip->nmap - 1; 371 mip->map_off = map[i].br_startoff + map[i].br_blockcount; 372 } else 373 mip->map_off = xfs_dir2_byte_to_da(mp, 374 XFS_DIR2_LEAF_OFFSET); 375 376 /* 377 * Look for holes in the mapping, and eliminate them. Count up 378 * the valid blocks. 379 */ 380 for (i = mip->map_valid; i < mip->map_valid + mip->nmap; ) { 381 if (map[i].br_startblock == HOLESTARTBLOCK) { 382 mip->nmap--; 383 length = mip->map_valid + mip->nmap - i; 384 if (length) 385 memmove(&map[i], &map[i + 1], 386 sizeof(map[i]) * length); 387 } else { 388 mip->map_blocks += map[i].br_blockcount; 389 i++; 390 } 391 } 392 mip->map_valid += mip->nmap; 393 } 394 395 /* 396 * No valid mappings, so no more data blocks. 397 */ 398 if (!mip->map_valid) { 399 *curoff = xfs_dir2_da_to_byte(mp, mip->map_off); 400 goto out; 401 } 402 403 /* 404 * Read the directory block starting at the first mapping. 405 */ 406 mip->curdb = xfs_dir2_da_to_db(mp, map->br_startoff); 407 error = xfs_dir3_data_read(NULL, dp, map->br_startoff, 408 map->br_blockcount >= mp->m_dirblkfsbs ? 409 XFS_FSB_TO_DADDR(mp, map->br_startblock) : -1, &bp); 410 411 /* 412 * Should just skip over the data block instead of giving up. 413 */ 414 if (error) 415 goto out; /* XXX */ 416 417 /* 418 * Adjust the current amount of read-ahead: we just read a block that 419 * was previously ra. 420 */ 421 if (mip->ra_current) 422 mip->ra_current -= mp->m_dirblkfsbs; 423 424 /* 425 * Do we need more readahead? 426 */ 427 blk_start_plug(&plug); 428 for (mip->ra_index = mip->ra_offset = i = 0; 429 mip->ra_want > mip->ra_current && i < mip->map_blocks; 430 i += mp->m_dirblkfsbs) { 431 ASSERT(mip->ra_index < mip->map_valid); 432 /* 433 * Read-ahead a contiguous directory block. 434 */ 435 if (i > mip->ra_current && 436 map[mip->ra_index].br_blockcount >= mp->m_dirblkfsbs) { 437 xfs_dir3_data_readahead(NULL, dp, 438 map[mip->ra_index].br_startoff + mip->ra_offset, 439 XFS_FSB_TO_DADDR(mp, 440 map[mip->ra_index].br_startblock + 441 mip->ra_offset)); 442 mip->ra_current = i; 443 } 444 445 /* 446 * Read-ahead a non-contiguous directory block. This doesn't 447 * use our mapping, but this is a very rare case. 448 */ 449 else if (i > mip->ra_current) { 450 xfs_dir3_data_readahead(NULL, dp, 451 map[mip->ra_index].br_startoff + 452 mip->ra_offset, -1); 453 mip->ra_current = i; 454 } 455 456 /* 457 * Advance offset through the mapping table. 458 */ 459 for (j = 0; j < mp->m_dirblkfsbs; j++) { 460 /* 461 * The rest of this extent but not more than a dir 462 * block. 463 */ 464 length = min_t(int, mp->m_dirblkfsbs, 465 map[mip->ra_index].br_blockcount - 466 mip->ra_offset); 467 j += length; 468 mip->ra_offset += length; 469 470 /* 471 * Advance to the next mapping if this one is used up. 472 */ 473 if (mip->ra_offset == map[mip->ra_index].br_blockcount) { 474 mip->ra_offset = 0; 475 mip->ra_index++; 476 } 477 } 478 } 479 blk_finish_plug(&plug); 480 481 out: 482 *bpp = bp; 483 return error; 484 } 485 486 /* 487 * Getdents (readdir) for leaf and node directories. 488 * This reads the data blocks only, so is the same for both forms. 489 */ 490 STATIC int 491 xfs_dir2_leaf_getdents( 492 xfs_inode_t *dp, /* incore directory inode */ 493 struct dir_context *ctx, 494 size_t bufsize) 495 { 496 struct xfs_buf *bp = NULL; /* data block buffer */ 497 xfs_dir2_data_hdr_t *hdr; /* data block header */ 498 xfs_dir2_data_entry_t *dep; /* data entry */ 499 xfs_dir2_data_unused_t *dup; /* unused entry */ 500 int error = 0; /* error return value */ 501 int length; /* temporary length value */ 502 xfs_mount_t *mp; /* filesystem mount point */ 503 int byteoff; /* offset in current block */ 504 xfs_dir2_off_t curoff; /* current overall offset */ 505 xfs_dir2_off_t newoff; /* new curoff after new blk */ 506 char *ptr = NULL; /* pointer to current data */ 507 struct xfs_dir2_leaf_map_info *map_info; 508 509 /* 510 * If the offset is at or past the largest allowed value, 511 * give up right away. 512 */ 513 if (ctx->pos >= XFS_DIR2_MAX_DATAPTR) 514 return 0; 515 516 mp = dp->i_mount; 517 518 /* 519 * Set up to bmap a number of blocks based on the caller's 520 * buffer size, the directory block size, and the filesystem 521 * block size. 522 */ 523 length = howmany(bufsize + mp->m_dirblksize, 524 mp->m_sb.sb_blocksize); 525 map_info = kmem_zalloc(offsetof(struct xfs_dir2_leaf_map_info, map) + 526 (length * sizeof(struct xfs_bmbt_irec)), 527 KM_SLEEP | KM_NOFS); 528 map_info->map_size = length; 529 530 /* 531 * Inside the loop we keep the main offset value as a byte offset 532 * in the directory file. 533 */ 534 curoff = xfs_dir2_dataptr_to_byte(mp, ctx->pos); 535 536 /* 537 * Force this conversion through db so we truncate the offset 538 * down to get the start of the data block. 539 */ 540 map_info->map_off = xfs_dir2_db_to_da(mp, 541 xfs_dir2_byte_to_db(mp, curoff)); 542 543 /* 544 * Loop over directory entries until we reach the end offset. 545 * Get more blocks and readahead as necessary. 546 */ 547 while (curoff < XFS_DIR2_LEAF_OFFSET) { 548 __uint8_t filetype; 549 550 /* 551 * If we have no buffer, or we're off the end of the 552 * current buffer, need to get another one. 553 */ 554 if (!bp || ptr >= (char *)bp->b_addr + mp->m_dirblksize) { 555 556 error = xfs_dir2_leaf_readbuf(dp, bufsize, map_info, 557 &curoff, &bp); 558 if (error || !map_info->map_valid) 559 break; 560 561 /* 562 * Having done a read, we need to set a new offset. 563 */ 564 newoff = xfs_dir2_db_off_to_byte(mp, map_info->curdb, 0); 565 /* 566 * Start of the current block. 567 */ 568 if (curoff < newoff) 569 curoff = newoff; 570 /* 571 * Make sure we're in the right block. 572 */ 573 else if (curoff > newoff) 574 ASSERT(xfs_dir2_byte_to_db(mp, curoff) == 575 map_info->curdb); 576 hdr = bp->b_addr; 577 xfs_dir3_data_check(dp, bp); 578 /* 579 * Find our position in the block. 580 */ 581 ptr = (char *)xfs_dir3_data_entry_p(hdr); 582 byteoff = xfs_dir2_byte_to_off(mp, curoff); 583 /* 584 * Skip past the header. 585 */ 586 if (byteoff == 0) 587 curoff += xfs_dir3_data_entry_offset(hdr); 588 /* 589 * Skip past entries until we reach our offset. 590 */ 591 else { 592 while ((char *)ptr - (char *)hdr < byteoff) { 593 dup = (xfs_dir2_data_unused_t *)ptr; 594 595 if (be16_to_cpu(dup->freetag) 596 == XFS_DIR2_DATA_FREE_TAG) { 597 598 length = be16_to_cpu(dup->length); 599 ptr += length; 600 continue; 601 } 602 dep = (xfs_dir2_data_entry_t *)ptr; 603 length = 604 xfs_dir3_data_entsize(mp, dep->namelen); 605 ptr += length; 606 } 607 /* 608 * Now set our real offset. 609 */ 610 curoff = 611 xfs_dir2_db_off_to_byte(mp, 612 xfs_dir2_byte_to_db(mp, curoff), 613 (char *)ptr - (char *)hdr); 614 if (ptr >= (char *)hdr + mp->m_dirblksize) { 615 continue; 616 } 617 } 618 } 619 /* 620 * We have a pointer to an entry. 621 * Is it a live one? 622 */ 623 dup = (xfs_dir2_data_unused_t *)ptr; 624 /* 625 * No, it's unused, skip over it. 626 */ 627 if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) { 628 length = be16_to_cpu(dup->length); 629 ptr += length; 630 curoff += length; 631 continue; 632 } 633 634 dep = (xfs_dir2_data_entry_t *)ptr; 635 length = xfs_dir3_data_entsize(mp, dep->namelen); 636 filetype = xfs_dir3_dirent_get_ftype(mp, dep); 637 638 ctx->pos = xfs_dir2_byte_to_dataptr(mp, curoff) & 0x7fffffff; 639 if (!dir_emit(ctx, (char *)dep->name, dep->namelen, 640 be64_to_cpu(dep->inumber), 641 xfs_dir3_get_dtype(mp, filetype))) 642 break; 643 644 /* 645 * Advance to next entry in the block. 646 */ 647 ptr += length; 648 curoff += length; 649 /* bufsize may have just been a guess; don't go negative */ 650 bufsize = bufsize > length ? bufsize - length : 0; 651 } 652 653 /* 654 * All done. Set output offset value to current offset. 655 */ 656 if (curoff > xfs_dir2_dataptr_to_byte(mp, XFS_DIR2_MAX_DATAPTR)) 657 ctx->pos = XFS_DIR2_MAX_DATAPTR & 0x7fffffff; 658 else 659 ctx->pos = xfs_dir2_byte_to_dataptr(mp, curoff) & 0x7fffffff; 660 kmem_free(map_info); 661 if (bp) 662 xfs_trans_brelse(NULL, bp); 663 return error; 664 } 665 666 /* 667 * Read a directory. 668 */ 669 int 670 xfs_readdir( 671 xfs_inode_t *dp, 672 struct dir_context *ctx, 673 size_t bufsize) 674 { 675 int rval; /* return value */ 676 int v; /* type-checking value */ 677 678 trace_xfs_readdir(dp); 679 680 if (XFS_FORCED_SHUTDOWN(dp->i_mount)) 681 return XFS_ERROR(EIO); 682 683 ASSERT(S_ISDIR(dp->i_d.di_mode)); 684 XFS_STATS_INC(xs_dir_getdents); 685 686 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) 687 rval = xfs_dir2_sf_getdents(dp, ctx); 688 else if ((rval = xfs_dir2_isblock(NULL, dp, &v))) 689 ; 690 else if (v) 691 rval = xfs_dir2_block_getdents(dp, ctx); 692 else 693 rval = xfs_dir2_leaf_getdents(dp, ctx, bufsize); 694 return rval; 695 } 696