xfs: allow parent directory scans to be interrupted with fatal signals
Allow a fatal signal to interrupt us when we're scanning a directory to verify a parent pointer. Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> Reviewed-by: Brian Foster <bfoster@redhat.com>
This commit is contained in:
@ -32,8 +32,10 @@ xchk_setup_parent(
|
|||||||
|
|
||||||
struct xchk_parent_ctx {
|
struct xchk_parent_ctx {
|
||||||
struct dir_context dc;
|
struct dir_context dc;
|
||||||
|
struct xfs_scrub *sc;
|
||||||
xfs_ino_t ino;
|
xfs_ino_t ino;
|
||||||
xfs_nlink_t nlink;
|
xfs_nlink_t nlink;
|
||||||
|
bool cancelled;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Look for a single entry in a directory pointing to an inode. */
|
/* Look for a single entry in a directory pointing to an inode. */
|
||||||
@ -47,11 +49,21 @@ xchk_parent_actor(
|
|||||||
unsigned type)
|
unsigned type)
|
||||||
{
|
{
|
||||||
struct xchk_parent_ctx *spc;
|
struct xchk_parent_ctx *spc;
|
||||||
|
int error = 0;
|
||||||
|
|
||||||
spc = container_of(dc, struct xchk_parent_ctx, dc);
|
spc = container_of(dc, struct xchk_parent_ctx, dc);
|
||||||
if (spc->ino == ino)
|
if (spc->ino == ino)
|
||||||
spc->nlink++;
|
spc->nlink++;
|
||||||
return 0;
|
|
||||||
|
/*
|
||||||
|
* If we're facing a fatal signal, bail out. Store the cancellation
|
||||||
|
* status separately because the VFS readdir code squashes error codes
|
||||||
|
* into short directory reads.
|
||||||
|
*/
|
||||||
|
if (xchk_should_terminate(spc->sc, &error))
|
||||||
|
spc->cancelled = true;
|
||||||
|
|
||||||
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Count the number of dentries in the parent dir that point to this inode. */
|
/* Count the number of dentries in the parent dir that point to this inode. */
|
||||||
@ -62,10 +74,9 @@ xchk_parent_count_parent_dentries(
|
|||||||
xfs_nlink_t *nlink)
|
xfs_nlink_t *nlink)
|
||||||
{
|
{
|
||||||
struct xchk_parent_ctx spc = {
|
struct xchk_parent_ctx spc = {
|
||||||
.dc.actor = xchk_parent_actor,
|
.dc.actor = xchk_parent_actor,
|
||||||
.dc.pos = 0,
|
.ino = sc->ip->i_ino,
|
||||||
.ino = sc->ip->i_ino,
|
.sc = sc,
|
||||||
.nlink = 0,
|
|
||||||
};
|
};
|
||||||
size_t bufsize;
|
size_t bufsize;
|
||||||
loff_t oldpos;
|
loff_t oldpos;
|
||||||
@ -97,6 +108,10 @@ xchk_parent_count_parent_dentries(
|
|||||||
error = xfs_readdir(sc->tp, parent, &spc.dc, bufsize);
|
error = xfs_readdir(sc->tp, parent, &spc.dc, bufsize);
|
||||||
if (error)
|
if (error)
|
||||||
goto out;
|
goto out;
|
||||||
|
if (spc.cancelled) {
|
||||||
|
error = -EAGAIN;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
if (oldpos == spc.dc.pos)
|
if (oldpos == spc.dc.pos)
|
||||||
break;
|
break;
|
||||||
oldpos = spc.dc.pos;
|
oldpos = spc.dc.pos;
|
||||||
|
Reference in New Issue
Block a user