|
@@ -3327,7 +3327,7 @@ xfs_iflush(
|
|
struct xfs_buf **bpp)
|
|
struct xfs_buf **bpp)
|
|
{
|
|
{
|
|
struct xfs_mount *mp = ip->i_mount;
|
|
struct xfs_mount *mp = ip->i_mount;
|
|
- struct xfs_buf *bp;
|
|
|
|
|
|
+ struct xfs_buf *bp = NULL;
|
|
struct xfs_dinode *dip;
|
|
struct xfs_dinode *dip;
|
|
int error;
|
|
int error;
|
|
|
|
|
|
@@ -3369,14 +3369,22 @@ xfs_iflush(
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
- * Get the buffer containing the on-disk inode.
|
|
|
|
|
|
+ * Get the buffer containing the on-disk inode. We are doing a try-lock
|
|
|
|
+ * operation here, so we may get an EAGAIN error. In that case, we
|
|
|
|
+ * simply want to return with the inode still dirty.
|
|
|
|
+ *
|
|
|
|
+ * If we get any other error, we effectively have a corruption situation
|
|
|
|
+ * and we cannot flush the inode, so we treat it the same as failing
|
|
|
|
+ * xfs_iflush_int().
|
|
*/
|
|
*/
|
|
error = xfs_imap_to_bp(mp, NULL, &ip->i_imap, &dip, &bp, XBF_TRYLOCK,
|
|
error = xfs_imap_to_bp(mp, NULL, &ip->i_imap, &dip, &bp, XBF_TRYLOCK,
|
|
0);
|
|
0);
|
|
- if (error || !bp) {
|
|
|
|
|
|
+ if (error == -EAGAIN) {
|
|
xfs_ifunlock(ip);
|
|
xfs_ifunlock(ip);
|
|
return error;
|
|
return error;
|
|
}
|
|
}
|
|
|
|
+ if (error)
|
|
|
|
+ goto corrupt_out;
|
|
|
|
|
|
/*
|
|
/*
|
|
* First flush out the inode that xfs_iflush was called with.
|
|
* First flush out the inode that xfs_iflush was called with.
|
|
@@ -3404,7 +3412,8 @@ xfs_iflush(
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
corrupt_out:
|
|
corrupt_out:
|
|
- xfs_buf_relse(bp);
|
|
|
|
|
|
+ if (bp)
|
|
|
|
+ xfs_buf_relse(bp);
|
|
xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
|
|
xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
|
|
cluster_corrupt_out:
|
|
cluster_corrupt_out:
|
|
error = -EFSCORRUPTED;
|
|
error = -EFSCORRUPTED;
|