Commit 4a8af273 authored by Dave Chinner's avatar Dave Chinner Committed by Ben Myers

xfs: move getdents code into it's own file

The directory readdir code is not used by userspace, but it is
intermingled with files that are shared with userspace. This makes
it difficult to compare the differences between the userspac eand
kernel files are the userspace files don't have the getdents code in
them. Move all the kernel getdents code to a separate file to bring
the shared content between userspace and kernel files closer
together.
Signed-off-by: default avatarDave Chinner <dchinner@redhat.com>
Reviewed-by: default avatarBrian Foster <bfoster@redhat.com>
Reviewed-by: default avatarMark Tinguely <tinguely@sgi.com>
Signed-off-by: default avatarBen Myers <bpm@sgi.com>
parent 1fd7115e
......@@ -30,6 +30,7 @@ xfs-y += xfs_aops.o \
xfs_bit.o \
xfs_buf.o \
xfs_dfrag.o \
xfs_dir2_readdir.o \
xfs_discard.o \
xfs_error.o \
xfs_export.o \
......
......@@ -362,37 +362,6 @@ xfs_dir_removename(
return rval;
}
/*
* Read a directory.
*/
int
xfs_readdir(
xfs_inode_t *dp,
struct dir_context *ctx,
size_t bufsize)
{
int rval; /* return value */
int v; /* type-checking value */
trace_xfs_readdir(dp);
if (XFS_FORCED_SHUTDOWN(dp->i_mount))
return XFS_ERROR(EIO);
ASSERT(S_ISDIR(dp->i_d.di_mode));
XFS_STATS_INC(xs_dir_getdents);
if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
rval = xfs_dir2_sf_getdents(dp, ctx);
else if ((rval = xfs_dir2_isblock(NULL, dp, &v)))
;
else if (v)
rval = xfs_dir2_block_getdents(dp, ctx);
else
rval = xfs_dir2_leaf_getdents(dp, ctx, bufsize);
return rval;
}
/*
* Replace the inode number of a directory entry.
*/
......
......@@ -126,7 +126,7 @@ const struct xfs_buf_ops xfs_dir3_block_buf_ops = {
.verify_write = xfs_dir3_block_write_verify,
};
static int
int
xfs_dir3_block_read(
struct xfs_trans *tp,
struct xfs_inode *dp,
......@@ -564,101 +564,6 @@ xfs_dir2_block_addname(
return 0;
}
/*
* Readdir for block directories.
*/
int /* error */
xfs_dir2_block_getdents(
xfs_inode_t *dp, /* incore inode */
struct dir_context *ctx)
{
xfs_dir2_data_hdr_t *hdr; /* block header */
struct xfs_buf *bp; /* buffer for block */
xfs_dir2_block_tail_t *btp; /* block tail */
xfs_dir2_data_entry_t *dep; /* block data entry */
xfs_dir2_data_unused_t *dup; /* block unused entry */
char *endptr; /* end of the data entries */
int error; /* error return value */
xfs_mount_t *mp; /* filesystem mount point */
char *ptr; /* current data entry */
int wantoff; /* starting block offset */
xfs_off_t cook;
mp = dp->i_mount;
/*
* If the block number in the offset is out of range, we're done.
*/
if (xfs_dir2_dataptr_to_db(mp, ctx->pos) > mp->m_dirdatablk)
return 0;
error = xfs_dir3_block_read(NULL, dp, &bp);
if (error)
return error;
/*
* Extract the byte offset we start at from the seek pointer.
* We'll skip entries before this.
*/
wantoff = xfs_dir2_dataptr_to_off(mp, ctx->pos);
hdr = bp->b_addr;
xfs_dir3_data_check(dp, bp);
/*
* Set up values for the loop.
*/
btp = xfs_dir2_block_tail_p(mp, hdr);
ptr = (char *)xfs_dir3_data_entry_p(hdr);
endptr = (char *)xfs_dir2_block_leaf_p(btp);
/*
* Loop over the data portion of the block.
* Each object is a real entry (dep) or an unused one (dup).
*/
while (ptr < endptr) {
dup = (xfs_dir2_data_unused_t *)ptr;
/*
* Unused, skip it.
*/
if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
ptr += be16_to_cpu(dup->length);
continue;
}
dep = (xfs_dir2_data_entry_t *)ptr;
/*
* Bump pointer for the next iteration.
*/
ptr += xfs_dir2_data_entsize(dep->namelen);
/*
* The entry is before the desired starting point, skip it.
*/
if ((char *)dep - (char *)hdr < wantoff)
continue;
cook = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
(char *)dep - (char *)hdr);
ctx->pos = cook & 0x7fffffff;
/*
* If it didn't fit, set the final offset to here & return.
*/
if (!dir_emit(ctx, (char *)dep->name, dep->namelen,
be64_to_cpu(dep->inumber), DT_UNKNOWN)) {
xfs_trans_brelse(NULL, bp);
return 0;
}
}
/*
* Reached the end of the block.
* Set the offset to a non-existent block 1 and return.
*/
ctx->pos = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk + 1, 0) &
0x7fffffff;
xfs_trans_brelse(NULL, bp);
return 0;
}
/*
* Log leaf entries from the block.
*/
......
This diff is collapsed.
......@@ -32,9 +32,9 @@ extern int xfs_dir_cilookup_result(struct xfs_da_args *args,
/* xfs_dir2_block.c */
extern const struct xfs_buf_ops xfs_dir3_block_buf_ops;
extern int xfs_dir3_block_read(struct xfs_trans *tp, struct xfs_inode *dp,
struct xfs_buf **bpp);
extern int xfs_dir2_block_addname(struct xfs_da_args *args);
extern int xfs_dir2_block_getdents(struct xfs_inode *dp,
struct dir_context *ctx);
extern int xfs_dir2_block_lookup(struct xfs_da_args *args);
extern int xfs_dir2_block_removename(struct xfs_da_args *args);
extern int xfs_dir2_block_replace(struct xfs_da_args *args);
......@@ -91,8 +91,6 @@ extern void xfs_dir3_leaf_compact(struct xfs_da_args *args,
extern void xfs_dir3_leaf_compact_x1(struct xfs_dir3_icleaf_hdr *leafhdr,
struct xfs_dir2_leaf_entry *ents, int *indexp,
int *lowstalep, int *highstalep, int *lowlogp, int *highlogp);
extern int xfs_dir2_leaf_getdents(struct xfs_inode *dp, struct dir_context *ctx,
size_t bufsize);
extern int xfs_dir3_leaf_get_buf(struct xfs_da_args *args, xfs_dir2_db_t bno,
struct xfs_buf **bpp, __uint16_t magic);
extern void xfs_dir3_leaf_log_ents(struct xfs_trans *tp, struct xfs_buf *bp,
......@@ -153,7 +151,6 @@ extern int xfs_dir2_block_to_sf(struct xfs_da_args *args, struct xfs_buf *bp,
int size, xfs_dir2_sf_hdr_t *sfhp);
extern int xfs_dir2_sf_addname(struct xfs_da_args *args);
extern int xfs_dir2_sf_create(struct xfs_da_args *args, xfs_ino_t pino);
extern int xfs_dir2_sf_getdents(struct xfs_inode *dp, struct dir_context *ctx);
extern int xfs_dir2_sf_lookup(struct xfs_da_args *args);
extern int xfs_dir2_sf_removename(struct xfs_da_args *args);
extern int xfs_dir2_sf_replace(struct xfs_da_args *args);
......
This diff is collapsed.
......@@ -765,100 +765,6 @@ xfs_dir2_sf_create(
return 0;
}
int /* error */
xfs_dir2_sf_getdents(
xfs_inode_t *dp, /* incore directory inode */
struct dir_context *ctx)
{
int i; /* shortform entry number */
xfs_mount_t *mp; /* filesystem mount point */
xfs_dir2_dataptr_t off; /* current entry's offset */
xfs_dir2_sf_entry_t *sfep; /* shortform directory entry */
xfs_dir2_sf_hdr_t *sfp; /* shortform structure */
xfs_dir2_dataptr_t dot_offset;
xfs_dir2_dataptr_t dotdot_offset;
xfs_ino_t ino;
mp = dp->i_mount;
ASSERT(dp->i_df.if_flags & XFS_IFINLINE);
/*
* Give up if the directory is way too short.
*/
if (dp->i_d.di_size < offsetof(xfs_dir2_sf_hdr_t, parent)) {
ASSERT(XFS_FORCED_SHUTDOWN(mp));
return XFS_ERROR(EIO);
}
ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
ASSERT(dp->i_df.if_u1.if_data != NULL);
sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
ASSERT(dp->i_d.di_size >= xfs_dir2_sf_hdr_size(sfp->i8count));
/*
* If the block number in the offset is out of range, we're done.
*/
if (xfs_dir2_dataptr_to_db(mp, ctx->pos) > mp->m_dirdatablk)
return 0;
/*
* Precalculate offsets for . and .. as we will always need them.
*
* XXX(hch): the second argument is sometimes 0 and sometimes
* mp->m_dirdatablk.
*/
dot_offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
XFS_DIR3_DATA_DOT_OFFSET(mp));
dotdot_offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
XFS_DIR3_DATA_DOTDOT_OFFSET(mp));
/*
* Put . entry unless we're starting past it.
*/
if (ctx->pos <= dot_offset) {
ctx->pos = dot_offset & 0x7fffffff;
if (!dir_emit(ctx, ".", 1, dp->i_ino, DT_DIR))
return 0;
}
/*
* Put .. entry unless we're starting past it.
*/
if (ctx->pos <= dotdot_offset) {
ino = xfs_dir2_sf_get_parent_ino(sfp);
ctx->pos = dotdot_offset & 0x7fffffff;
if (!dir_emit(ctx, "..", 2, ino, DT_DIR))
return 0;
}
/*
* Loop while there are more entries and put'ing works.
*/
sfep = xfs_dir2_sf_firstentry(sfp);
for (i = 0; i < sfp->count; i++) {
off = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
xfs_dir2_sf_get_offset(sfep));
if (ctx->pos > off) {
sfep = xfs_dir2_sf_nextentry(sfp, sfep);
continue;
}
ino = xfs_dir2_sfe_get_ino(sfp, sfep);
ctx->pos = off & 0x7fffffff;
if (!dir_emit(ctx, (char *)sfep->name, sfep->namelen,
ino, DT_UNKNOWN))
return 0;
sfep = xfs_dir2_sf_nextentry(sfp, sfep);
}
ctx->pos = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk + 1, 0) &
0x7fffffff;
return 0;
}
/*
* Lookup an entry in a shortform directory.
* Returns EEXIST if found, ENOENT if not found.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment