1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2000-2005 Silicon Graphics, Inc. 4 * Copyright (c) 2013 Red Hat, Inc. 5 * All Rights Reserved. 6 */ 7 #include "xfs.h" 8 #include "xfs_fs.h" 9 #include "xfs_shared.h" 10 #include "xfs_format.h" 11 #include "xfs_log_format.h" 12 #include "xfs_trans_resv.h" 13 #include "xfs_mount.h" 14 #include "xfs_inode.h" 15 #include "xfs_dir2.h" 16 #include "xfs_dir2_priv.h" 17 #include "xfs_trace.h" 18 #include "xfs_bmap.h" 19 #include "xfs_trans.h" 20 #include "xfs_error.h" 21 #include "xfs_health.h" 22 23 /* 24 * Directory file type support functions 25 */ 26 static unsigned char xfs_dir3_filetype_table[] = { 27 DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, 28 DT_FIFO, DT_SOCK, DT_LNK, DT_WHT, 29 }; 30 31 unsigned char 32 xfs_dir3_get_dtype( 33 struct xfs_mount *mp, 34 uint8_t filetype) 35 { 36 if (!xfs_has_ftype(mp)) 37 return DT_UNKNOWN; 38 39 if (filetype >= XFS_DIR3_FT_MAX) 40 return DT_UNKNOWN; 41 42 return xfs_dir3_filetype_table[filetype]; 43 } 44 45 STATIC int 46 xfs_dir2_sf_getdents( 47 struct xfs_da_args *args, 48 struct dir_context *ctx) 49 { 50 int i; /* shortform entry number */ 51 struct xfs_inode *dp = args->dp; /* incore directory inode */ 52 struct xfs_mount *mp = dp->i_mount; 53 xfs_dir2_dataptr_t off; /* current entry's offset */ 54 xfs_dir2_sf_entry_t *sfep; /* shortform directory entry */ 55 struct xfs_dir2_sf_hdr *sfp = dp->i_df.if_data; 56 xfs_dir2_dataptr_t dot_offset; 57 xfs_dir2_dataptr_t dotdot_offset; 58 xfs_ino_t ino; 59 struct xfs_da_geometry *geo = args->geo; 60 61 ASSERT(dp->i_df.if_format == XFS_DINODE_FMT_LOCAL); 62 ASSERT(dp->i_df.if_bytes == dp->i_disk_size); 63 ASSERT(sfp != NULL); 64 65 /* 66 * If the block number in the offset is out of range, we're done. 67 */ 68 if (xfs_dir2_dataptr_to_db(geo, ctx->pos) > geo->datablk) 69 return 0; 70 71 /* 72 * Precalculate offsets for "." and ".." as we will always need them. 73 * This relies on the fact that directories always start with the 74 * entries for "." and "..". 75 */ 76 dot_offset = xfs_dir2_db_off_to_dataptr(geo, geo->datablk, 77 geo->data_entry_offset); 78 dotdot_offset = xfs_dir2_db_off_to_dataptr(geo, geo->datablk, 79 geo->data_entry_offset + 80 xfs_dir2_data_entsize(mp, sizeof(".") - 1)); 81 82 /* 83 * Put . entry unless we're starting past it. 84 */ 85 if (ctx->pos <= dot_offset) { 86 ctx->pos = dot_offset & 0x7fffffff; 87 if (!dir_emit(ctx, ".", 1, dp->i_ino, DT_DIR)) 88 return 0; 89 } 90 91 /* 92 * Put .. entry unless we're starting past it. 93 */ 94 if (ctx->pos <= dotdot_offset) { 95 ino = xfs_dir2_sf_get_parent_ino(sfp); 96 ctx->pos = dotdot_offset & 0x7fffffff; 97 if (!dir_emit(ctx, "..", 2, ino, DT_DIR)) 98 return 0; 99 } 100 101 /* 102 * Loop while there are more entries and put'ing works. 103 */ 104 sfep = xfs_dir2_sf_firstentry(sfp); 105 for (i = 0; i < sfp->count; i++) { 106 uint8_t filetype; 107 108 off = xfs_dir2_db_off_to_dataptr(geo, geo->datablk, 109 xfs_dir2_sf_get_offset(sfep)); 110 111 if (ctx->pos > off) { 112 sfep = xfs_dir2_sf_nextentry(mp, sfp, sfep); 113 continue; 114 } 115 116 ino = xfs_dir2_sf_get_ino(mp, sfp, sfep); 117 filetype = xfs_dir2_sf_get_ftype(mp, sfep); 118 ctx->pos = off & 0x7fffffff; 119 if (XFS_IS_CORRUPT(dp->i_mount, 120 !xfs_dir2_namecheck(sfep->name, 121 sfep->namelen))) { 122 xfs_dirattr_mark_sick(dp, XFS_DATA_FORK); 123 return -EFSCORRUPTED; 124 } 125 if (!dir_emit(ctx, (char *)sfep->name, sfep->namelen, ino, 126 xfs_dir3_get_dtype(mp, filetype))) 127 return 0; 128 sfep = xfs_dir2_sf_nextentry(mp, sfp, sfep); 129 } 130 131 ctx->pos = xfs_dir2_db_off_to_dataptr(geo, geo->datablk + 1, 0) & 132 0x7fffffff; 133 return 0; 134 } 135 136 /* 137 * Readdir for block directories. 138 */ 139 STATIC int 140 xfs_dir2_block_getdents( 141 struct xfs_da_args *args, 142 struct dir_context *ctx, 143 unsigned int *lock_mode) 144 { 145 struct xfs_inode *dp = args->dp; /* incore directory inode */ 146 struct xfs_buf *bp; /* buffer for block */ 147 int error; /* error return value */ 148 int wantoff; /* starting block offset */ 149 xfs_off_t cook; 150 struct xfs_da_geometry *geo = args->geo; 151 unsigned int offset, next_offset; 152 unsigned int end; 153 154 /* 155 * If the block number in the offset is out of range, we're done. 156 */ 157 if (xfs_dir2_dataptr_to_db(geo, ctx->pos) > geo->datablk) 158 return 0; 159 160 error = xfs_dir3_block_read(args->trans, dp, args->owner, &bp); 161 if (error) 162 return error; 163 164 xfs_iunlock(dp, *lock_mode); 165 *lock_mode = 0; 166 167 /* 168 * Extract the byte offset we start at from the seek pointer. 169 * We'll skip entries before this. 170 */ 171 wantoff = xfs_dir2_dataptr_to_off(geo, ctx->pos); 172 xfs_dir3_data_check(dp, bp); 173 174 /* 175 * Loop over the data portion of the block. 176 * Each object is a real entry (dep) or an unused one (dup). 177 */ 178 end = xfs_dir3_data_end_offset(geo, bp->b_addr); 179 for (offset = geo->data_entry_offset; 180 offset < end; 181 offset = next_offset) { 182 struct xfs_dir2_data_unused *dup = bp->b_addr + offset; 183 struct xfs_dir2_data_entry *dep = bp->b_addr + offset; 184 uint8_t filetype; 185 186 /* 187 * Unused, skip it. 188 */ 189 if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) { 190 next_offset = offset + be16_to_cpu(dup->length); 191 continue; 192 } 193 194 /* 195 * Bump pointer for the next iteration. 196 */ 197 next_offset = offset + 198 xfs_dir2_data_entsize(dp->i_mount, dep->namelen); 199 200 /* 201 * The entry is before the desired starting point, skip it. 202 */ 203 if (offset < wantoff) 204 continue; 205 206 cook = xfs_dir2_db_off_to_dataptr(geo, geo->datablk, offset); 207 208 ctx->pos = cook & 0x7fffffff; 209 filetype = xfs_dir2_data_get_ftype(dp->i_mount, dep); 210 /* 211 * If it didn't fit, set the final offset to here & return. 212 */ 213 if (XFS_IS_CORRUPT(dp->i_mount, 214 !xfs_dir2_namecheck(dep->name, 215 dep->namelen))) { 216 xfs_dirattr_mark_sick(dp, XFS_DATA_FORK); 217 error = -EFSCORRUPTED; 218 goto out_rele; 219 } 220 if (!dir_emit(ctx, (char *)dep->name, dep->namelen, 221 be64_to_cpu(dep->inumber), 222 xfs_dir3_get_dtype(dp->i_mount, filetype))) 223 goto out_rele; 224 } 225 226 /* 227 * Reached the end of the block. 228 * Set the offset to a non-existent block 1 and return. 229 */ 230 ctx->pos = xfs_dir2_db_off_to_dataptr(geo, geo->datablk + 1, 0) & 231 0x7fffffff; 232 out_rele: 233 xfs_trans_brelse(args->trans, bp); 234 return error; 235 } 236 237 /* 238 * Read a directory block and initiate readahead for blocks beyond that. 239 * We maintain a sliding readahead window of the remaining space in the 240 * buffer rounded up to the nearest block. 241 */ 242 STATIC int 243 xfs_dir2_leaf_readbuf( 244 struct xfs_da_args *args, 245 size_t bufsize, 246 xfs_dir2_off_t *cur_off, 247 xfs_dablk_t *ra_blk, 248 struct xfs_buf **bpp) 249 { 250 struct xfs_inode *dp = args->dp; 251 struct xfs_buf *bp = NULL; 252 struct xfs_da_geometry *geo = args->geo; 253 struct xfs_ifork *ifp = xfs_ifork_ptr(dp, XFS_DATA_FORK); 254 struct xfs_bmbt_irec map; 255 struct blk_plug plug; 256 xfs_dir2_off_t new_off; 257 xfs_dablk_t next_ra; 258 xfs_dablk_t map_off; 259 xfs_dablk_t last_da; 260 struct xfs_iext_cursor icur; 261 int ra_want; 262 int error = 0; 263 264 error = xfs_iread_extents(args->trans, dp, XFS_DATA_FORK); 265 if (error) 266 goto out; 267 268 /* 269 * Look for mapped directory blocks at or above the current offset. 270 * Truncate down to the nearest directory block to start the scanning 271 * operation. 272 */ 273 last_da = xfs_dir2_byte_to_da(geo, XFS_DIR2_LEAF_OFFSET); 274 map_off = xfs_dir2_db_to_da(geo, xfs_dir2_byte_to_db(geo, *cur_off)); 275 if (!xfs_iext_lookup_extent(dp, ifp, map_off, &icur, &map)) 276 goto out; 277 if (map.br_startoff >= last_da) 278 goto out; 279 xfs_trim_extent(&map, map_off, last_da - map_off); 280 281 /* Read the directory block of that first mapping. */ 282 new_off = xfs_dir2_da_to_byte(geo, map.br_startoff); 283 if (new_off > *cur_off) 284 *cur_off = new_off; 285 error = xfs_dir3_data_read(args->trans, dp, args->owner, 286 map.br_startoff, 0, &bp); 287 if (error) 288 goto out; 289 290 /* 291 * Start readahead for the next bufsize's worth of dir data blocks. 292 * We may have already issued readahead for some of that range; 293 * ra_blk tracks the last block we tried to read(ahead). 294 */ 295 ra_want = howmany(bufsize + geo->blksize, (1 << geo->fsblog)); 296 if (*ra_blk >= last_da) 297 goto out; 298 else if (*ra_blk == 0) 299 *ra_blk = map.br_startoff; 300 next_ra = map.br_startoff + geo->fsbcount; 301 if (next_ra >= last_da) 302 goto out_no_ra; 303 if (map.br_blockcount < geo->fsbcount && 304 !xfs_iext_next_extent(ifp, &icur, &map)) 305 goto out_no_ra; 306 if (map.br_startoff >= last_da) 307 goto out_no_ra; 308 xfs_trim_extent(&map, next_ra, last_da - next_ra); 309 310 /* Start ra for each dir (not fs) block that has a mapping. */ 311 blk_start_plug(&plug); 312 while (ra_want > 0) { 313 next_ra = roundup((xfs_dablk_t)map.br_startoff, geo->fsbcount); 314 while (ra_want > 0 && 315 next_ra < map.br_startoff + map.br_blockcount) { 316 if (next_ra >= last_da) { 317 *ra_blk = last_da; 318 break; 319 } 320 if (next_ra > *ra_blk) { 321 xfs_dir3_data_readahead(dp, next_ra, 322 XFS_DABUF_MAP_HOLE_OK); 323 *ra_blk = next_ra; 324 } 325 ra_want -= geo->fsbcount; 326 next_ra += geo->fsbcount; 327 } 328 if (!xfs_iext_next_extent(ifp, &icur, &map)) { 329 *ra_blk = last_da; 330 break; 331 } 332 } 333 blk_finish_plug(&plug); 334 335 out: 336 *bpp = bp; 337 return error; 338 out_no_ra: 339 *ra_blk = last_da; 340 goto out; 341 } 342 343 /* 344 * Getdents (readdir) for leaf and node directories. 345 * This reads the data blocks only, so is the same for both forms. 346 */ 347 STATIC int 348 xfs_dir2_leaf_getdents( 349 struct xfs_da_args *args, 350 struct dir_context *ctx, 351 size_t bufsize, 352 unsigned int *lock_mode) 353 { 354 struct xfs_inode *dp = args->dp; 355 struct xfs_mount *mp = dp->i_mount; 356 struct xfs_buf *bp = NULL; /* data block buffer */ 357 xfs_dir2_data_entry_t *dep; /* data entry */ 358 xfs_dir2_data_unused_t *dup; /* unused entry */ 359 struct xfs_da_geometry *geo = args->geo; 360 xfs_dablk_t rablk = 0; /* current readahead block */ 361 xfs_dir2_off_t curoff; /* current overall offset */ 362 int length; /* temporary length value */ 363 int byteoff; /* offset in current block */ 364 unsigned int offset = 0; 365 int error = 0; /* error return value */ 366 367 /* 368 * If the offset is at or past the largest allowed value, 369 * give up right away. 370 */ 371 if (ctx->pos >= XFS_DIR2_MAX_DATAPTR) 372 return 0; 373 374 /* 375 * Inside the loop we keep the main offset value as a byte offset 376 * in the directory file. 377 */ 378 curoff = xfs_dir2_dataptr_to_byte(ctx->pos); 379 380 /* 381 * Loop over directory entries until we reach the end offset. 382 * Get more blocks and readahead as necessary. 383 */ 384 while (curoff < XFS_DIR2_LEAF_OFFSET) { 385 uint8_t filetype; 386 387 /* 388 * If we have no buffer, or we're off the end of the 389 * current buffer, need to get another one. 390 */ 391 if (!bp || offset >= geo->blksize) { 392 if (bp) { 393 xfs_trans_brelse(args->trans, bp); 394 bp = NULL; 395 } 396 397 if (*lock_mode == 0) 398 *lock_mode = xfs_ilock_data_map_shared(dp); 399 error = xfs_dir2_leaf_readbuf(args, bufsize, &curoff, 400 &rablk, &bp); 401 if (error || !bp) 402 break; 403 404 xfs_iunlock(dp, *lock_mode); 405 *lock_mode = 0; 406 407 xfs_dir3_data_check(dp, bp); 408 /* 409 * Find our position in the block. 410 */ 411 offset = geo->data_entry_offset; 412 byteoff = xfs_dir2_byte_to_off(geo, curoff); 413 /* 414 * Skip past the header. 415 */ 416 if (byteoff == 0) 417 curoff += geo->data_entry_offset; 418 /* 419 * Skip past entries until we reach our offset. 420 */ 421 else { 422 while (offset < byteoff) { 423 dup = bp->b_addr + offset; 424 425 if (be16_to_cpu(dup->freetag) 426 == XFS_DIR2_DATA_FREE_TAG) { 427 428 length = be16_to_cpu(dup->length); 429 offset += length; 430 continue; 431 } 432 dep = bp->b_addr + offset; 433 length = xfs_dir2_data_entsize(mp, 434 dep->namelen); 435 offset += length; 436 } 437 /* 438 * Now set our real offset. 439 */ 440 curoff = 441 xfs_dir2_db_off_to_byte(geo, 442 xfs_dir2_byte_to_db(geo, curoff), 443 offset); 444 if (offset >= geo->blksize) 445 continue; 446 } 447 } 448 449 /* 450 * We have a pointer to an entry. Is it a live one? 451 */ 452 dup = bp->b_addr + offset; 453 454 /* 455 * No, it's unused, skip over it. 456 */ 457 if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) { 458 length = be16_to_cpu(dup->length); 459 offset += length; 460 curoff += length; 461 continue; 462 } 463 464 dep = bp->b_addr + offset; 465 length = xfs_dir2_data_entsize(mp, dep->namelen); 466 filetype = xfs_dir2_data_get_ftype(mp, dep); 467 468 ctx->pos = xfs_dir2_byte_to_dataptr(curoff) & 0x7fffffff; 469 if (XFS_IS_CORRUPT(dp->i_mount, 470 !xfs_dir2_namecheck(dep->name, 471 dep->namelen))) { 472 xfs_dirattr_mark_sick(dp, XFS_DATA_FORK); 473 error = -EFSCORRUPTED; 474 break; 475 } 476 if (!dir_emit(ctx, (char *)dep->name, dep->namelen, 477 be64_to_cpu(dep->inumber), 478 xfs_dir3_get_dtype(dp->i_mount, filetype))) 479 break; 480 481 /* 482 * Advance to next entry in the block. 483 */ 484 offset += length; 485 curoff += length; 486 /* bufsize may have just been a guess; don't go negative */ 487 bufsize = bufsize > length ? bufsize - length : 0; 488 } 489 490 /* 491 * All done. Set output offset value to current offset. 492 */ 493 if (curoff > xfs_dir2_dataptr_to_byte(XFS_DIR2_MAX_DATAPTR)) 494 ctx->pos = XFS_DIR2_MAX_DATAPTR & 0x7fffffff; 495 else 496 ctx->pos = xfs_dir2_byte_to_dataptr(curoff) & 0x7fffffff; 497 if (bp) 498 xfs_trans_brelse(args->trans, bp); 499 return error; 500 } 501 502 /* 503 * Read a directory. 504 * 505 * If supplied, the transaction collects locked dir buffers to avoid 506 * nested buffer deadlocks. This function does not dirty the 507 * transaction. The caller must hold the IOLOCK (shared or exclusive) 508 * before calling this function. 509 */ 510 int 511 xfs_readdir( 512 struct xfs_trans *tp, 513 struct xfs_inode *dp, 514 struct dir_context *ctx, 515 size_t bufsize) 516 { 517 struct xfs_da_args args = { NULL }; 518 unsigned int lock_mode; 519 int error; 520 521 trace_xfs_readdir(dp); 522 523 if (xfs_is_shutdown(dp->i_mount)) 524 return -EIO; 525 if (xfs_ifork_zapped(dp, XFS_DATA_FORK)) 526 return -EIO; 527 528 ASSERT(S_ISDIR(VFS_I(dp)->i_mode)); 529 xfs_assert_ilocked(dp, XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL); 530 XFS_STATS_INC(dp->i_mount, xs_dir_getdents); 531 532 args.dp = dp; 533 args.geo = dp->i_mount->m_dir_geo; 534 args.trans = tp; 535 args.owner = dp->i_ino; 536 537 if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) 538 return xfs_dir2_sf_getdents(&args, ctx); 539 540 lock_mode = xfs_ilock_data_map_shared(dp); 541 switch (xfs_dir2_format(&args, &error)) { 542 case XFS_DIR2_FMT_BLOCK: 543 error = xfs_dir2_block_getdents(&args, ctx, &lock_mode); 544 break; 545 case XFS_DIR2_FMT_LEAF: 546 case XFS_DIR2_FMT_NODE: 547 error = xfs_dir2_leaf_getdents(&args, ctx, bufsize, &lock_mode); 548 break; 549 default: 550 break; 551 } 552 553 if (lock_mode) 554 xfs_iunlock(dp, lock_mode); 555 return error; 556 } 557
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.