Lines Matching +full:block +full:- +full:offset

1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2000-2005 Silicon Graphics, Inc.
51 struct xfs_inode *dp = args->dp; /* incore directory inode */ in xfs_dir2_sf_getdents()
52 struct xfs_mount *mp = dp->i_mount; in xfs_dir2_sf_getdents()
53 xfs_dir2_dataptr_t off; /* current entry's offset */ in xfs_dir2_sf_getdents()
55 struct xfs_dir2_sf_hdr *sfp = dp->i_df.if_data; in xfs_dir2_sf_getdents()
59 struct xfs_da_geometry *geo = args->geo; in xfs_dir2_sf_getdents()
61 ASSERT(dp->i_df.if_format == XFS_DINODE_FMT_LOCAL); in xfs_dir2_sf_getdents()
62 ASSERT(dp->i_df.if_bytes == dp->i_disk_size); in xfs_dir2_sf_getdents()
66 * If the block number in the offset is out of range, we're done. in xfs_dir2_sf_getdents()
68 if (xfs_dir2_dataptr_to_db(geo, ctx->pos) > geo->datablk) in xfs_dir2_sf_getdents()
76 dot_offset = xfs_dir2_db_off_to_dataptr(geo, geo->datablk, in xfs_dir2_sf_getdents()
77 geo->data_entry_offset); in xfs_dir2_sf_getdents()
78 dotdot_offset = xfs_dir2_db_off_to_dataptr(geo, geo->datablk, in xfs_dir2_sf_getdents()
79 geo->data_entry_offset + in xfs_dir2_sf_getdents()
80 xfs_dir2_data_entsize(mp, sizeof(".") - 1)); in xfs_dir2_sf_getdents()
85 if (ctx->pos <= dot_offset) { in xfs_dir2_sf_getdents()
86 ctx->pos = dot_offset & 0x7fffffff; in xfs_dir2_sf_getdents()
87 if (!dir_emit(ctx, ".", 1, dp->i_ino, DT_DIR)) in xfs_dir2_sf_getdents()
94 if (ctx->pos <= dotdot_offset) { in xfs_dir2_sf_getdents()
96 ctx->pos = dotdot_offset & 0x7fffffff; in xfs_dir2_sf_getdents()
105 for (i = 0; i < sfp->count; i++) { in xfs_dir2_sf_getdents()
108 off = xfs_dir2_db_off_to_dataptr(geo, geo->datablk, in xfs_dir2_sf_getdents()
111 if (ctx->pos > off) { in xfs_dir2_sf_getdents()
118 ctx->pos = off & 0x7fffffff; in xfs_dir2_sf_getdents()
119 if (XFS_IS_CORRUPT(dp->i_mount, in xfs_dir2_sf_getdents()
120 !xfs_dir2_namecheck(sfep->name, in xfs_dir2_sf_getdents()
121 sfep->namelen))) { in xfs_dir2_sf_getdents()
123 return -EFSCORRUPTED; in xfs_dir2_sf_getdents()
125 if (!dir_emit(ctx, (char *)sfep->name, sfep->namelen, ino, in xfs_dir2_sf_getdents()
131 ctx->pos = xfs_dir2_db_off_to_dataptr(geo, geo->datablk + 1, 0) & in xfs_dir2_sf_getdents()
137 * Readdir for block directories.
145 struct xfs_inode *dp = args->dp; /* incore directory inode */ in xfs_dir2_block_getdents()
146 struct xfs_buf *bp; /* buffer for block */ in xfs_dir2_block_getdents()
148 int wantoff; /* starting block offset */ in xfs_dir2_block_getdents()
150 struct xfs_da_geometry *geo = args->geo; in xfs_dir2_block_getdents()
151 unsigned int offset, next_offset; in xfs_dir2_block_getdents() local
155 * If the block number in the offset is out of range, we're done. in xfs_dir2_block_getdents()
157 if (xfs_dir2_dataptr_to_db(geo, ctx->pos) > geo->datablk) in xfs_dir2_block_getdents()
160 error = xfs_dir3_block_read(args->trans, dp, args->owner, &bp); in xfs_dir2_block_getdents()
168 * Extract the byte offset we start at from the seek pointer. in xfs_dir2_block_getdents()
171 wantoff = xfs_dir2_dataptr_to_off(geo, ctx->pos); in xfs_dir2_block_getdents()
175 * Loop over the data portion of the block. in xfs_dir2_block_getdents()
178 end = xfs_dir3_data_end_offset(geo, bp->b_addr); in xfs_dir2_block_getdents()
179 for (offset = geo->data_entry_offset; in xfs_dir2_block_getdents()
180 offset < end; in xfs_dir2_block_getdents()
181 offset = next_offset) { in xfs_dir2_block_getdents()
182 struct xfs_dir2_data_unused *dup = bp->b_addr + offset; in xfs_dir2_block_getdents()
183 struct xfs_dir2_data_entry *dep = bp->b_addr + offset; in xfs_dir2_block_getdents()
189 if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) { in xfs_dir2_block_getdents()
190 next_offset = offset + be16_to_cpu(dup->length); in xfs_dir2_block_getdents()
197 next_offset = offset + in xfs_dir2_block_getdents()
198 xfs_dir2_data_entsize(dp->i_mount, dep->namelen); in xfs_dir2_block_getdents()
203 if (offset < wantoff) in xfs_dir2_block_getdents()
206 cook = xfs_dir2_db_off_to_dataptr(geo, geo->datablk, offset); in xfs_dir2_block_getdents()
208 ctx->pos = cook & 0x7fffffff; in xfs_dir2_block_getdents()
209 filetype = xfs_dir2_data_get_ftype(dp->i_mount, dep); in xfs_dir2_block_getdents()
211 * If it didn't fit, set the final offset to here & return. in xfs_dir2_block_getdents()
213 if (XFS_IS_CORRUPT(dp->i_mount, in xfs_dir2_block_getdents()
214 !xfs_dir2_namecheck(dep->name, in xfs_dir2_block_getdents()
215 dep->namelen))) { in xfs_dir2_block_getdents()
217 error = -EFSCORRUPTED; in xfs_dir2_block_getdents()
220 if (!dir_emit(ctx, (char *)dep->name, dep->namelen, in xfs_dir2_block_getdents()
221 be64_to_cpu(dep->inumber), in xfs_dir2_block_getdents()
222 xfs_dir3_get_dtype(dp->i_mount, filetype))) in xfs_dir2_block_getdents()
227 * Reached the end of the block. in xfs_dir2_block_getdents()
228 * Set the offset to a non-existent block 1 and return. in xfs_dir2_block_getdents()
230 ctx->pos = xfs_dir2_db_off_to_dataptr(geo, geo->datablk + 1, 0) & in xfs_dir2_block_getdents()
233 xfs_trans_brelse(args->trans, bp); in xfs_dir2_block_getdents()
238 * Read a directory block and initiate readahead for blocks beyond that.
240 * buffer rounded up to the nearest block.
250 struct xfs_inode *dp = args->dp; in xfs_dir2_leaf_readbuf()
252 struct xfs_da_geometry *geo = args->geo; in xfs_dir2_leaf_readbuf()
264 error = xfs_iread_extents(args->trans, dp, XFS_DATA_FORK); in xfs_dir2_leaf_readbuf()
269 * Look for mapped directory blocks at or above the current offset. in xfs_dir2_leaf_readbuf()
270 * Truncate down to the nearest directory block to start the scanning in xfs_dir2_leaf_readbuf()
279 xfs_trim_extent(&map, map_off, last_da - map_off); in xfs_dir2_leaf_readbuf()
281 /* Read the directory block of that first mapping. */ in xfs_dir2_leaf_readbuf()
285 error = xfs_dir3_data_read(args->trans, dp, args->owner, in xfs_dir2_leaf_readbuf()
293 * ra_blk tracks the last block we tried to read(ahead). in xfs_dir2_leaf_readbuf()
295 ra_want = howmany(bufsize + geo->blksize, (1 << geo->fsblog)); in xfs_dir2_leaf_readbuf()
300 next_ra = map.br_startoff + geo->fsbcount; in xfs_dir2_leaf_readbuf()
303 if (map.br_blockcount < geo->fsbcount && in xfs_dir2_leaf_readbuf()
308 xfs_trim_extent(&map, next_ra, last_da - next_ra); in xfs_dir2_leaf_readbuf()
310 /* Start ra for each dir (not fs) block that has a mapping. */ in xfs_dir2_leaf_readbuf()
313 next_ra = roundup((xfs_dablk_t)map.br_startoff, geo->fsbcount); in xfs_dir2_leaf_readbuf()
325 ra_want -= geo->fsbcount; in xfs_dir2_leaf_readbuf()
326 next_ra += geo->fsbcount; in xfs_dir2_leaf_readbuf()
354 struct xfs_inode *dp = args->dp; in xfs_dir2_leaf_getdents()
355 struct xfs_mount *mp = dp->i_mount; in xfs_dir2_leaf_getdents()
356 struct xfs_buf *bp = NULL; /* data block buffer */ in xfs_dir2_leaf_getdents()
359 struct xfs_da_geometry *geo = args->geo; in xfs_dir2_leaf_getdents()
360 xfs_dablk_t rablk = 0; /* current readahead block */ in xfs_dir2_leaf_getdents()
361 xfs_dir2_off_t curoff; /* current overall offset */ in xfs_dir2_leaf_getdents()
363 int byteoff; /* offset in current block */ in xfs_dir2_leaf_getdents()
364 unsigned int offset = 0; in xfs_dir2_leaf_getdents() local
368 * If the offset is at or past the largest allowed value, in xfs_dir2_leaf_getdents()
371 if (ctx->pos >= XFS_DIR2_MAX_DATAPTR) in xfs_dir2_leaf_getdents()
375 * Inside the loop we keep the main offset value as a byte offset in xfs_dir2_leaf_getdents()
378 curoff = xfs_dir2_dataptr_to_byte(ctx->pos); in xfs_dir2_leaf_getdents()
381 * Loop over directory entries until we reach the end offset. in xfs_dir2_leaf_getdents()
391 if (!bp || offset >= geo->blksize) { in xfs_dir2_leaf_getdents()
393 xfs_trans_brelse(args->trans, bp); in xfs_dir2_leaf_getdents()
409 * Find our position in the block. in xfs_dir2_leaf_getdents()
411 offset = geo->data_entry_offset; in xfs_dir2_leaf_getdents()
417 curoff += geo->data_entry_offset; in xfs_dir2_leaf_getdents()
419 * Skip past entries until we reach our offset. in xfs_dir2_leaf_getdents()
422 while (offset < byteoff) { in xfs_dir2_leaf_getdents()
423 dup = bp->b_addr + offset; in xfs_dir2_leaf_getdents()
425 if (be16_to_cpu(dup->freetag) in xfs_dir2_leaf_getdents()
428 length = be16_to_cpu(dup->length); in xfs_dir2_leaf_getdents()
429 offset += length; in xfs_dir2_leaf_getdents()
432 dep = bp->b_addr + offset; in xfs_dir2_leaf_getdents()
434 dep->namelen); in xfs_dir2_leaf_getdents()
435 offset += length; in xfs_dir2_leaf_getdents()
438 * Now set our real offset. in xfs_dir2_leaf_getdents()
443 offset); in xfs_dir2_leaf_getdents()
444 if (offset >= geo->blksize) in xfs_dir2_leaf_getdents()
452 dup = bp->b_addr + offset; in xfs_dir2_leaf_getdents()
457 if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) { in xfs_dir2_leaf_getdents()
458 length = be16_to_cpu(dup->length); in xfs_dir2_leaf_getdents()
459 offset += length; in xfs_dir2_leaf_getdents()
464 dep = bp->b_addr + offset; in xfs_dir2_leaf_getdents()
465 length = xfs_dir2_data_entsize(mp, dep->namelen); in xfs_dir2_leaf_getdents()
468 ctx->pos = xfs_dir2_byte_to_dataptr(curoff) & 0x7fffffff; in xfs_dir2_leaf_getdents()
469 if (XFS_IS_CORRUPT(dp->i_mount, in xfs_dir2_leaf_getdents()
470 !xfs_dir2_namecheck(dep->name, in xfs_dir2_leaf_getdents()
471 dep->namelen))) { in xfs_dir2_leaf_getdents()
473 error = -EFSCORRUPTED; in xfs_dir2_leaf_getdents()
476 if (!dir_emit(ctx, (char *)dep->name, dep->namelen, in xfs_dir2_leaf_getdents()
477 be64_to_cpu(dep->inumber), in xfs_dir2_leaf_getdents()
478 xfs_dir3_get_dtype(dp->i_mount, filetype))) in xfs_dir2_leaf_getdents()
482 * Advance to next entry in the block. in xfs_dir2_leaf_getdents()
484 offset += length; in xfs_dir2_leaf_getdents()
487 bufsize = bufsize > length ? bufsize - length : 0; in xfs_dir2_leaf_getdents()
491 * All done. Set output offset value to current offset. in xfs_dir2_leaf_getdents()
494 ctx->pos = XFS_DIR2_MAX_DATAPTR & 0x7fffffff; in xfs_dir2_leaf_getdents()
496 ctx->pos = xfs_dir2_byte_to_dataptr(curoff) & 0x7fffffff; in xfs_dir2_leaf_getdents()
498 xfs_trans_brelse(args->trans, bp); in xfs_dir2_leaf_getdents()
523 if (xfs_is_shutdown(dp->i_mount)) in xfs_readdir()
524 return -EIO; in xfs_readdir()
526 return -EIO; in xfs_readdir()
528 ASSERT(S_ISDIR(VFS_I(dp)->i_mode)); in xfs_readdir()
530 XFS_STATS_INC(dp->i_mount, xs_dir_getdents); in xfs_readdir()
533 args.geo = dp->i_mount->m_dir_geo; in xfs_readdir()
535 args.owner = dp->i_ino; in xfs_readdir()
537 if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) in xfs_readdir()