Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit acb9553c authored by Darrick J. Wong's avatar Darrick J. Wong
Browse files

xfs: pass along transaction context when reading directory block buffers



Teach the directory reading functions to pass along a transaction context
if one was supplied.  The directory scrub code will use transactions to
lock buffers and avoid deadlocking with itself in the case of loops.

Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: default avatarBrian Foster <bfoster@redhat.com>
parent 8e8877e6
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -130,7 +130,7 @@ extern int xfs_dir2_sf_replace(struct xfs_da_args *args);
extern int xfs_dir2_sf_verify(struct xfs_inode *ip);

/* xfs_dir2_readdir.c */
extern int xfs_readdir(struct xfs_inode *dp, struct dir_context *ctx,
		       size_t bufsize);
extern int xfs_readdir(struct xfs_trans *tp, struct xfs_inode *dp,
		       struct dir_context *ctx, size_t bufsize);

#endif /* __XFS_DIR2_PRIV_H__ */
+11 −4
Original line number Diff line number Diff line
@@ -170,7 +170,7 @@ xfs_dir2_block_getdents(
		return 0;

	lock_mode = xfs_ilock_data_map_shared(dp);
	error = xfs_dir3_block_read(NULL, dp, &bp);
	error = xfs_dir3_block_read(args->trans, dp, &bp);
	xfs_iunlock(dp, lock_mode);
	if (error)
		return error;
@@ -228,7 +228,7 @@ xfs_dir2_block_getdents(
		if (!dir_emit(ctx, (char *)dep->name, dep->namelen,
			    be64_to_cpu(dep->inumber),
			    xfs_dir3_get_dtype(dp->i_mount, filetype))) {
			xfs_trans_brelse(NULL, bp);
			xfs_trans_brelse(args->trans, bp);
			return 0;
		}
	}
@@ -239,7 +239,7 @@ xfs_dir2_block_getdents(
	 */
	ctx->pos = xfs_dir2_db_off_to_dataptr(geo, geo->datablk + 1, 0) &
								0x7fffffff;
	xfs_trans_brelse(NULL, bp);
	xfs_trans_brelse(args->trans, bp);
	return 0;
}

@@ -495,15 +495,21 @@ xfs_dir2_leaf_getdents(
	else
		ctx->pos = xfs_dir2_byte_to_dataptr(curoff) & 0x7fffffff;
	if (bp)
		xfs_trans_brelse(NULL, bp);
		xfs_trans_brelse(args->trans, bp);
	return error;
}

/*
 * Read a directory.
 *
 * If supplied, the transaction collects locked dir buffers to avoid
 * nested buffer deadlocks.  This function does not dirty the
 * transaction.  The caller should ensure that the inode is locked
 * before calling this function.
 */
int
xfs_readdir(
	struct xfs_trans	*tp,
	struct xfs_inode	*dp,
	struct dir_context	*ctx,
	size_t			bufsize)
@@ -522,6 +528,7 @@ xfs_readdir(

	args.dp = dp;
	args.geo = dp->i_mount->m_dir_geo;
	args.trans = tp;

	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
		rval = xfs_dir2_sf_getdents(&args, ctx);
+1 −1
Original line number Diff line number Diff line
@@ -950,7 +950,7 @@ xfs_file_readdir(
	 */
	bufsize = (size_t)min_t(loff_t, 32768, ip->i_d.di_size);

	return xfs_readdir(ip, ctx, bufsize);
	return xfs_readdir(NULL, ip, ctx, bufsize);
}

/*