Skip to content

Commit acb9553

Browse files
committed
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: Darrick J. Wong <[email protected]> Reviewed-by: Brian Foster <[email protected]>
1 parent 8e8877e commit acb9553

File tree

3 files changed

+14
-7
lines changed

3 files changed

+14
-7
lines changed

fs/xfs/libxfs/xfs_dir2_priv.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ extern int xfs_dir2_sf_replace(struct xfs_da_args *args);
130130
extern int xfs_dir2_sf_verify(struct xfs_inode *ip);
131131

132132
/* xfs_dir2_readdir.c */
133-
extern int xfs_readdir(struct xfs_inode *dp, struct dir_context *ctx,
134-
size_t bufsize);
133+
extern int xfs_readdir(struct xfs_trans *tp, struct xfs_inode *dp,
134+
struct dir_context *ctx, size_t bufsize);
135135

136136
#endif /* __XFS_DIR2_PRIV_H__ */

fs/xfs/xfs_dir2_readdir.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ xfs_dir2_block_getdents(
170170
return 0;
171171

172172
lock_mode = xfs_ilock_data_map_shared(dp);
173-
error = xfs_dir3_block_read(NULL, dp, &bp);
173+
error = xfs_dir3_block_read(args->trans, dp, &bp);
174174
xfs_iunlock(dp, lock_mode);
175175
if (error)
176176
return error;
@@ -228,7 +228,7 @@ xfs_dir2_block_getdents(
228228
if (!dir_emit(ctx, (char *)dep->name, dep->namelen,
229229
be64_to_cpu(dep->inumber),
230230
xfs_dir3_get_dtype(dp->i_mount, filetype))) {
231-
xfs_trans_brelse(NULL, bp);
231+
xfs_trans_brelse(args->trans, bp);
232232
return 0;
233233
}
234234
}
@@ -239,7 +239,7 @@ xfs_dir2_block_getdents(
239239
*/
240240
ctx->pos = xfs_dir2_db_off_to_dataptr(geo, geo->datablk + 1, 0) &
241241
0x7fffffff;
242-
xfs_trans_brelse(NULL, bp);
242+
xfs_trans_brelse(args->trans, bp);
243243
return 0;
244244
}
245245

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

502502
/*
503503
* Read a directory.
504+
*
505+
* If supplied, the transaction collects locked dir buffers to avoid
506+
* nested buffer deadlocks. This function does not dirty the
507+
* transaction. The caller should ensure that the inode is locked
508+
* before calling this function.
504509
*/
505510
int
506511
xfs_readdir(
512+
struct xfs_trans *tp,
507513
struct xfs_inode *dp,
508514
struct dir_context *ctx,
509515
size_t bufsize)
@@ -522,6 +528,7 @@ xfs_readdir(
522528

523529
args.dp = dp;
524530
args.geo = dp->i_mount->m_dir_geo;
531+
args.trans = tp;
525532

526533
if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
527534
rval = xfs_dir2_sf_getdents(&args, ctx);

fs/xfs/xfs_file.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -950,7 +950,7 @@ xfs_file_readdir(
950950
*/
951951
bufsize = (size_t)min_t(loff_t, 32768, ip->i_d.di_size);
952952

953-
return xfs_readdir(ip, ctx, bufsize);
953+
return xfs_readdir(NULL, ip, ctx, bufsize);
954954
}
955955

956956
/*

0 commit comments

Comments
 (0)