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_format.h" 22 #include "xfs_log_format.h" 23 #include "xfs_trans_resv.h" 24 #include "xfs_bit.h" 25 #include "xfs_sb.h" 26 #include "xfs_ag.h" 27 #include "xfs_mount.h" 28 #include "xfs_da_format.h" 29 #include "xfs_da_btree.h" 30 #include "xfs_inode.h" 31 #include "xfs_dir2.h" 32 #include "xfs_dir2_priv.h" 33 #include "xfs_error.h" 34 #include "xfs_trace.h" 35 #include "xfs_bmap.h" 36 #include "xfs_trans.h" 37 #include "xfs_dinode.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 struct xfs_da_args *args, 80 struct dir_context *ctx) 81 { 82 int i; /* shortform entry number */ 83 struct xfs_inode *dp = args->dp; /* incore directory inode */ 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 struct xfs_da_geometry *geo = args->geo; 91 92 ASSERT(dp->i_df.if_flags & XFS_IFINLINE); 93 /* 94 * Give up if the directory is way too short. 95 */ 96 if (dp->i_d.di_size < offsetof(xfs_dir2_sf_hdr_t, parent)) { 97 ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount)); 98 return -EIO; 99 } 100 101 ASSERT(dp->i_df.if_bytes == dp->i_d.di_size); 102 ASSERT(dp->i_df.if_u1.if_data != NULL); 103 104 sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; 105 106 ASSERT(dp->i_d.di_size >= xfs_dir2_sf_hdr_size(sfp->i8count)); 107 108 /* 109 * If the block number in the offset is out of range, we're done. 110 */ 111 if (xfs_dir2_dataptr_to_db(geo, ctx->pos) > geo->datablk) 112 return 0; 113 114 /* 115 * Precalculate offsets for . and .. as we will always need them. 116 * 117 * XXX(hch): the second argument is sometimes 0 and sometimes 118 * geo->datablk 119 */ 120 dot_offset = xfs_dir2_db_off_to_dataptr(geo, geo->datablk, 121 dp->d_ops->data_dot_offset); 122 dotdot_offset = xfs_dir2_db_off_to_dataptr(geo, geo->datablk, 123 dp->d_ops->data_dotdot_offset); 124 125 /* 126 * Put . entry unless we're starting past it. 127 */ 128 if (ctx->pos <= dot_offset) { 129 ctx->pos = dot_offset & 0x7fffffff; 130 if (!dir_emit(ctx, ".", 1, dp->i_ino, DT_DIR)) 131 return 0; 132 } 133 134 /* 135 * Put .. entry unless we're starting past it. 136 */ 137 if (ctx->pos <= dotdot_offset) { 138 ino = dp->d_ops->sf_get_parent_ino(sfp); 139 ctx->pos = dotdot_offset & 0x7fffffff; 140 if (!dir_emit(ctx, "..", 2, ino, DT_DIR)) 141 return 0; 142 } 143 144 /* 145 * Loop while there are more entries and put'ing works. 146 */ 147 sfep = xfs_dir2_sf_firstentry(sfp); 148 for (i = 0; i < sfp->count; i++) { 149 __uint8_t filetype; 150 151 off = xfs_dir2_db_off_to_dataptr(geo, geo->datablk, 152 xfs_dir2_sf_get_offset(sfep)); 153 154 if (ctx->pos > off) { 155 sfep = dp->d_ops->sf_nextentry(sfp, sfep); 156 continue; 157 } 158 159 ino = dp->d_ops->sf_get_ino(sfp, sfep); 160 filetype = dp->d_ops->sf_get_ftype(sfep); 161 ctx->pos = off & 0x7fffffff; 162 if (!dir_emit(ctx, (char *)sfep->name, sfep->namelen, ino, 163 xfs_dir3_get_dtype(dp->i_mount, filetype))) 164 return 0; 165 sfep = dp->d_ops->sf_nextentry(sfp, sfep); 166 } 167 168 ctx->pos = xfs_dir2_db_off_to_dataptr(geo, geo->datablk + 1, 0) & 169 0x7fffffff; 170 return 0; 171 } 172 173 /* 174 * Readdir for block directories. 175 */ 176 STATIC int 177 xfs_dir2_block_getdents( 178 struct xfs_da_args *args, 179 struct dir_context *ctx) 180 { 181 struct xfs_inode *dp = args->dp; /* incore directory inode */ 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 char *ptr; /* current data entry */ 190 int wantoff; /* starting block offset */ 191 xfs_off_t cook; 192 struct xfs_da_geometry *geo = args->geo; 193 194 /* 195 * If the block number in the offset is out of range, we're done. 196 */ 197 if (xfs_dir2_dataptr_to_db(geo, ctx->pos) > geo->datablk) 198 return 0; 199 200 error = xfs_dir3_block_read(NULL, dp, &bp); 201 if (error) 202 return error; 203 204 /* 205 * Extract the byte offset we start at from the seek pointer. 206 * We'll skip entries before this. 207 */ 208 wantoff = xfs_dir2_dataptr_to_off(geo, ctx->pos); 209 hdr = bp->b_addr; 210 xfs_dir3_data_check(dp, bp); 211 /* 212 * Set up values for the loop. 213 */ 214 btp = xfs_dir2_block_tail_p(geo, hdr); 215 ptr = (char *)dp->d_ops->data_entry_p(hdr); 216 endptr = (char *)xfs_dir2_block_leaf_p(btp); 217 218 /* 219 * Loop over the data portion of the block. 220 * Each object is a real entry (dep) or an unused one (dup). 221 */ 222 while (ptr < endptr) { 223 __uint8_t filetype; 224 225 dup = (xfs_dir2_data_unused_t *)ptr; 226 /* 227 * Unused, skip it. 228 */ 229 if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) { 230 ptr += be16_to_cpu(dup->length); 231 continue; 232 } 233 234 dep = (xfs_dir2_data_entry_t *)ptr; 235 236 /* 237 * Bump pointer for the next iteration. 238 */ 239 ptr += dp->d_ops->data_entsize(dep->namelen); 240 /* 241 * The entry is before the desired starting point, skip it. 242 */ 243 if ((char *)dep - (char *)hdr < wantoff) 244 continue; 245 246 cook = xfs_dir2_db_off_to_dataptr(geo, geo->datablk, 247 (char *)dep - (char *)hdr); 248 249 ctx->pos = cook & 0x7fffffff; 250 filetype = dp->d_ops->data_get_ftype(dep); 251 /* 252 * If it didn't fit, set the final offset to here & return. 253 */ 254 if (!dir_emit(ctx, (char *)dep->name, dep->namelen, 255 be64_to_cpu(dep->inumber), 256 xfs_dir3_get_dtype(dp->i_mount, filetype))) { 257 xfs_trans_brelse(NULL, bp); 258 return 0; 259 } 260 } 261 262 /* 263 * Reached the end of the block. 264 * Set the offset to a non-existent block 1 and return. 265 */ 266 ctx->pos = xfs_dir2_db_off_to_dataptr(geo, geo->datablk + 1, 0) & 267 0x7fffffff; 268 xfs_trans_brelse(NULL, bp); 269 return 0; 270 } 271 272 struct xfs_dir2_leaf_map_info { 273 xfs_extlen_t map_blocks; /* number of fsbs in map */ 274 xfs_dablk_t map_off; /* last mapped file offset */ 275 int map_size; /* total entries in *map */ 276 int map_valid; /* valid entries in *map */ 277 int nmap; /* mappings to ask xfs_bmapi */ 278 xfs_dir2_db_t curdb; /* db for current block */ 279 int ra_current; /* number of read-ahead blks */ 280 int ra_index; /* *map index for read-ahead */ 281 int ra_offset; /* map entry offset for ra */ 282 int ra_want; /* readahead count wanted */ 283 struct xfs_bmbt_irec map[]; /* map vector for blocks */ 284 }; 285 286 STATIC int 287 xfs_dir2_leaf_readbuf( 288 struct xfs_da_args *args, 289 size_t bufsize, 290 struct xfs_dir2_leaf_map_info *mip, 291 xfs_dir2_off_t *curoff, 292 struct xfs_buf **bpp) 293 { 294 struct xfs_inode *dp = args->dp; 295 struct xfs_buf *bp = *bpp; 296 struct xfs_bmbt_irec *map = mip->map; 297 struct blk_plug plug; 298 int error = 0; 299 int length; 300 int i; 301 int j; 302 struct xfs_da_geometry *geo = args->geo; 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 -= geo->fsbcount; 313 /* 314 * Loop to get rid of the extents for the 315 * directory block. 316 */ 317 for (i = geo->fsbcount; 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 + geo->blksize, (1 << geo->fsblog)) - 1; 337 ASSERT(mip->ra_want >= 0); 338 339 /* 340 * If we don't have as many as we want, and we haven't 341 * run out of data blocks, get some more mappings. 342 */ 343 if (1 + mip->ra_want > mip->map_blocks && 344 mip->map_off < xfs_dir2_byte_to_da(geo, XFS_DIR2_LEAF_OFFSET)) { 345 /* 346 * Get more bmaps, fill in after the ones 347 * we already have in the table. 348 */ 349 mip->nmap = mip->map_size - mip->map_valid; 350 error = xfs_bmapi_read(dp, mip->map_off, 351 xfs_dir2_byte_to_da(geo, XFS_DIR2_LEAF_OFFSET) - 352 mip->map_off, 353 &map[mip->map_valid], &mip->nmap, 0); 354 355 /* 356 * Don't know if we should ignore this or try to return an 357 * error. The trouble with returning errors is that readdir 358 * will just stop without actually passing the error through. 359 */ 360 if (error) 361 goto out; /* XXX */ 362 363 /* 364 * If we got all the mappings we asked for, set the final map 365 * offset based on the last bmap value received. Otherwise, 366 * we've reached the end. 367 */ 368 if (mip->nmap == mip->map_size - mip->map_valid) { 369 i = mip->map_valid + mip->nmap - 1; 370 mip->map_off = map[i].br_startoff + map[i].br_blockcount; 371 } else 372 mip->map_off = xfs_dir2_byte_to_da(geo, 373 XFS_DIR2_LEAF_OFFSET); 374 375 /* 376 * Look for holes in the mapping, and eliminate them. Count up 377 * the valid blocks. 378 */ 379 for (i = mip->map_valid; i < mip->map_valid + mip->nmap; ) { 380 if (map[i].br_startblock == HOLESTARTBLOCK) { 381 mip->nmap--; 382 length = mip->map_valid + mip->nmap - i; 383 if (length) 384 memmove(&map[i], &map[i + 1], 385 sizeof(map[i]) * length); 386 } else { 387 mip->map_blocks += map[i].br_blockcount; 388 i++; 389 } 390 } 391 mip->map_valid += mip->nmap; 392 } 393 394 /* 395 * No valid mappings, so no more data blocks. 396 */ 397 if (!mip->map_valid) { 398 *curoff = xfs_dir2_da_to_byte(geo, mip->map_off); 399 goto out; 400 } 401 402 /* 403 * Read the directory block starting at the first mapping. 404 */ 405 mip->curdb = xfs_dir2_da_to_db(geo, map->br_startoff); 406 error = xfs_dir3_data_read(NULL, dp, map->br_startoff, 407 map->br_blockcount >= geo->fsbcount ? 408 XFS_FSB_TO_DADDR(dp->i_mount, map->br_startblock) : 409 -1, &bp); 410 /* 411 * Should just skip over the data block instead of giving up. 412 */ 413 if (error) 414 goto out; /* XXX */ 415 416 /* 417 * Adjust the current amount of read-ahead: we just read a block that 418 * was previously ra. 419 */ 420 if (mip->ra_current) 421 mip->ra_current -= geo->fsbcount; 422 423 /* 424 * Do we need more readahead? 425 */ 426 blk_start_plug(&plug); 427 for (mip->ra_index = mip->ra_offset = i = 0; 428 mip->ra_want > mip->ra_current && i < mip->map_blocks; 429 i += geo->fsbcount) { 430 ASSERT(mip->ra_index < mip->map_valid); 431 /* 432 * Read-ahead a contiguous directory block. 433 */ 434 if (i > mip->ra_current && 435 map[mip->ra_index].br_blockcount >= geo->fsbcount) { 436 xfs_dir3_data_readahead(dp, 437 map[mip->ra_index].br_startoff + mip->ra_offset, 438 XFS_FSB_TO_DADDR(dp->i_mount, 439 map[mip->ra_index].br_startblock + 440 mip->ra_offset)); 441 mip->ra_current = i; 442 } 443 444 /* 445 * Read-ahead a non-contiguous directory block. This doesn't 446 * use our mapping, but this is a very rare case. 447 */ 448 else if (i > mip->ra_current) { 449 xfs_dir3_data_readahead(dp, 450 map[mip->ra_index].br_startoff + 451 mip->ra_offset, -1); 452 mip->ra_current = i; 453 } 454 455 /* 456 * Advance offset through the mapping table. 457 */ 458 for (j = 0; j < geo->fsbcount; j += length ) { 459 /* 460 * The rest of this extent but not more than a dir 461 * block. 462 */ 463 length = min_t(int, geo->fsbcount, 464 map[mip->ra_index].br_blockcount - 465 mip->ra_offset); 466 mip->ra_offset += length; 467 468 /* 469 * Advance to the next mapping if this one is used up. 470 */ 471 if (mip->ra_offset == map[mip->ra_index].br_blockcount) { 472 mip->ra_offset = 0; 473 mip->ra_index++; 474 } 475 } 476 } 477 blk_finish_plug(&plug); 478 479 out: 480 *bpp = bp; 481 return error; 482 } 483 484 /* 485 * Getdents (readdir) for leaf and node directories. 486 * This reads the data blocks only, so is the same for both forms. 487 */ 488 STATIC int 489 xfs_dir2_leaf_getdents( 490 struct xfs_da_args *args, 491 struct dir_context *ctx, 492 size_t bufsize) 493 { 494 struct xfs_inode *dp = args->dp; 495 struct xfs_buf *bp = NULL; /* data block buffer */ 496 xfs_dir2_data_hdr_t *hdr; /* data block header */ 497 xfs_dir2_data_entry_t *dep; /* data entry */ 498 xfs_dir2_data_unused_t *dup; /* unused entry */ 499 int error = 0; /* error return value */ 500 int length; /* temporary length value */ 501 int byteoff; /* offset in current block */ 502 xfs_dir2_off_t curoff; /* current overall offset */ 503 xfs_dir2_off_t newoff; /* new curoff after new blk */ 504 char *ptr = NULL; /* pointer to current data */ 505 struct xfs_dir2_leaf_map_info *map_info; 506 struct xfs_da_geometry *geo = args->geo; 507 508 /* 509 * If the offset is at or past the largest allowed value, 510 * give up right away. 511 */ 512 if (ctx->pos >= XFS_DIR2_MAX_DATAPTR) 513 return 0; 514 515 /* 516 * Set up to bmap a number of blocks based on the caller's 517 * buffer size, the directory block size, and the filesystem 518 * block size. 519 */ 520 length = howmany(bufsize + geo->blksize, (1 << geo->fsblog)); 521 map_info = kmem_zalloc(offsetof(struct xfs_dir2_leaf_map_info, map) + 522 (length * sizeof(struct xfs_bmbt_irec)), 523 KM_SLEEP | KM_NOFS); 524 map_info->map_size = length; 525 526 /* 527 * Inside the loop we keep the main offset value as a byte offset 528 * in the directory file. 529 */ 530 curoff = xfs_dir2_dataptr_to_byte(ctx->pos); 531 532 /* 533 * Force this conversion through db so we truncate the offset 534 * down to get the start of the data block. 535 */ 536 map_info->map_off = xfs_dir2_db_to_da(geo, 537 xfs_dir2_byte_to_db(geo, curoff)); 538 539 /* 540 * Loop over directory entries until we reach the end offset. 541 * Get more blocks and readahead as necessary. 542 */ 543 while (curoff < XFS_DIR2_LEAF_OFFSET) { 544 __uint8_t filetype; 545 546 /* 547 * If we have no buffer, or we're off the end of the 548 * current buffer, need to get another one. 549 */ 550 if (!bp || ptr >= (char *)bp->b_addr + geo->blksize) { 551 552 error = xfs_dir2_leaf_readbuf(args, bufsize, map_info, 553 &curoff, &bp); 554 if (error || !map_info->map_valid) 555 break; 556 557 /* 558 * Having done a read, we need to set a new offset. 559 */ 560 newoff = xfs_dir2_db_off_to_byte(geo, 561 map_info->curdb, 0); 562 /* 563 * Start of the current block. 564 */ 565 if (curoff < newoff) 566 curoff = newoff; 567 /* 568 * Make sure we're in the right block. 569 */ 570 else if (curoff > newoff) 571 ASSERT(xfs_dir2_byte_to_db(geo, curoff) == 572 map_info->curdb); 573 hdr = bp->b_addr; 574 xfs_dir3_data_check(dp, bp); 575 /* 576 * Find our position in the block. 577 */ 578 ptr = (char *)dp->d_ops->data_entry_p(hdr); 579 byteoff = xfs_dir2_byte_to_off(geo, curoff); 580 /* 581 * Skip past the header. 582 */ 583 if (byteoff == 0) 584 curoff += dp->d_ops->data_entry_offset; 585 /* 586 * Skip past entries until we reach our offset. 587 */ 588 else { 589 while ((char *)ptr - (char *)hdr < byteoff) { 590 dup = (xfs_dir2_data_unused_t *)ptr; 591 592 if (be16_to_cpu(dup->freetag) 593 == XFS_DIR2_DATA_FREE_TAG) { 594 595 length = be16_to_cpu(dup->length); 596 ptr += length; 597 continue; 598 } 599 dep = (xfs_dir2_data_entry_t *)ptr; 600 length = 601 dp->d_ops->data_entsize(dep->namelen); 602 ptr += length; 603 } 604 /* 605 * Now set our real offset. 606 */ 607 curoff = 608 xfs_dir2_db_off_to_byte(geo, 609 xfs_dir2_byte_to_db(geo, curoff), 610 (char *)ptr - (char *)hdr); 611 if (ptr >= (char *)hdr + geo->blksize) { 612 continue; 613 } 614 } 615 } 616 /* 617 * We have a pointer to an entry. 618 * Is it a live one? 619 */ 620 dup = (xfs_dir2_data_unused_t *)ptr; 621 /* 622 * No, it's unused, skip over it. 623 */ 624 if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) { 625 length = be16_to_cpu(dup->length); 626 ptr += length; 627 curoff += length; 628 continue; 629 } 630 631 dep = (xfs_dir2_data_entry_t *)ptr; 632 length = dp->d_ops->data_entsize(dep->namelen); 633 filetype = dp->d_ops->data_get_ftype(dep); 634 635 ctx->pos = xfs_dir2_byte_to_dataptr(curoff) & 0x7fffffff; 636 if (!dir_emit(ctx, (char *)dep->name, dep->namelen, 637 be64_to_cpu(dep->inumber), 638 xfs_dir3_get_dtype(dp->i_mount, filetype))) 639 break; 640 641 /* 642 * Advance to next entry in the block. 643 */ 644 ptr += length; 645 curoff += length; 646 /* bufsize may have just been a guess; don't go negative */ 647 bufsize = bufsize > length ? bufsize - length : 0; 648 } 649 650 /* 651 * All done. Set output offset value to current offset. 652 */ 653 if (curoff > xfs_dir2_dataptr_to_byte(XFS_DIR2_MAX_DATAPTR)) 654 ctx->pos = XFS_DIR2_MAX_DATAPTR & 0x7fffffff; 655 else 656 ctx->pos = xfs_dir2_byte_to_dataptr(curoff) & 0x7fffffff; 657 kmem_free(map_info); 658 if (bp) 659 xfs_trans_brelse(NULL, bp); 660 return error; 661 } 662 663 /* 664 * Read a directory. 665 */ 666 int 667 xfs_readdir( 668 struct xfs_inode *dp, 669 struct dir_context *ctx, 670 size_t bufsize) 671 { 672 struct xfs_da_args args = { NULL }; 673 int rval; 674 int v; 675 uint lock_mode; 676 677 trace_xfs_readdir(dp); 678 679 if (XFS_FORCED_SHUTDOWN(dp->i_mount)) 680 return -EIO; 681 682 ASSERT(S_ISDIR(dp->i_d.di_mode)); 683 XFS_STATS_INC(xs_dir_getdents); 684 685 args.dp = dp; 686 args.geo = dp->i_mount->m_dir_geo; 687 688 lock_mode = xfs_ilock_data_map_shared(dp); 689 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) 690 rval = xfs_dir2_sf_getdents(&args, ctx); 691 else if ((rval = xfs_dir2_isblock(&args, &v))) 692 ; 693 else if (v) 694 rval = xfs_dir2_block_getdents(&args, ctx); 695 else 696 rval = xfs_dir2_leaf_getdents(&args, ctx, bufsize); 697 xfs_iunlock(dp, lock_mode); 698 699 return rval; 700 } 701