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