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