[XFS] Shutdown the filesystem if all device paths have gone. Made

shutdown vop flags consistent with sync vop flags declarations too.

SGI-PV: 939911
SGI-Modid: xfs-linux-melb:xfs-kern:26096a

Signed-off-by: Nathan Scott <nathans@sgi.com>
This commit is contained in:
Nathan Scott 2006-06-09 14:58:38 +10:00
parent b76963fac4
commit 7d04a335b6
18 changed files with 78 additions and 57 deletions

View File

@ -136,9 +136,10 @@ xfs_destroy_ioend(
for (bh = ioend->io_buffer_head; bh; bh = next) {
next = bh->b_private;
bh->b_end_io(bh, ioend->io_uptodate);
bh->b_end_io(bh, !ioend->io_error);
}
if (unlikely(ioend->io_error))
vn_ioerror(ioend->io_vnode, ioend->io_error, __FILE__,__LINE__);
vn_iowake(ioend->io_vnode);
mempool_free(ioend, xfs_ioend_pool);
}
@ -185,7 +186,7 @@ xfs_end_bio_unwritten(
size_t size = ioend->io_size;
int error;
if (ioend->io_uptodate)
if (likely(!ioend->io_error))
VOP_BMAP(vp, offset, size, BMAPI_UNWRITTEN, NULL, NULL, error);
xfs_destroy_ioend(ioend);
}
@ -211,7 +212,7 @@ xfs_alloc_ioend(
* all the I/O from calling the completion routine too early.
*/
atomic_set(&ioend->io_remaining, 1);
ioend->io_uptodate = 1; /* cleared if any I/O fails */
ioend->io_error = 0;
ioend->io_list = NULL;
ioend->io_type = type;
ioend->io_vnode = vn_from_inode(inode);
@ -271,16 +272,14 @@ xfs_end_bio(
if (bio->bi_size)
return 1;
ASSERT(ioend);
ASSERT(atomic_read(&bio->bi_cnt) >= 1);
ioend->io_error = test_bit(BIO_UPTODATE, &bio->bi_flags) ? 0 : error;
/* Toss bio and pass work off to an xfsdatad thread */
if (!test_bit(BIO_UPTODATE, &bio->bi_flags))
ioend->io_uptodate = 0;
bio->bi_private = NULL;
bio->bi_end_io = NULL;
bio_put(bio);
xfs_finish_ioend(ioend);
return 0;
}

View File

@ -30,7 +30,7 @@ typedef void (*xfs_ioend_func_t)(void *);
typedef struct xfs_ioend {
struct xfs_ioend *io_list; /* next ioend in chain */
unsigned int io_type; /* delalloc / unwritten */
unsigned int io_uptodate; /* I/O status register */
int io_error; /* I/O error code */
atomic_t io_remaining; /* hold count */
struct vnode *io_vnode; /* file being written to */
struct buffer_head *io_buffer_head;/* buffer linked list head */

View File

@ -94,6 +94,13 @@ typedef enum {
#define SYNC_REMOUNT 0x0080 /* remount readonly, no dummy LRs */
#define SYNC_QUIESCE 0x0100 /* quiesce filesystem for a snapshot */
#define SHUTDOWN_META_IO_ERROR 0x0001 /* write attempt to metadata failed */
#define SHUTDOWN_LOG_IO_ERROR 0x0002 /* write attempt to the log failed */
#define SHUTDOWN_FORCE_UMOUNT 0x0004 /* shutdown from a forced unmount */
#define SHUTDOWN_CORRUPT_INCORE 0x0008 /* corrupt in-memory data structures */
#define SHUTDOWN_REMOTE_REQ 0x0010 /* shutdown came from remote cell */
#define SHUTDOWN_DEVICE_REQ 0x0020 /* failed all paths to the device */
typedef int (*vfs_mount_t)(bhv_desc_t *,
struct xfs_mount_args *, struct cred *);
typedef int (*vfs_parseargs_t)(bhv_desc_t *, char *,

View File

@ -54,6 +54,22 @@ vn_iowake(
wake_up(vptosync(vp));
}
/*
* Volume managers supporting multiple paths can send back ENODEV when the
* final path disappears. In this case continuing to fill the page cache
* with dirty data which cannot be written out is evil, so prevent that.
*/
void
vn_ioerror(
struct vnode *vp,
int error,
char *f,
int l)
{
if (unlikely(error == -ENODEV))
VFS_FORCE_SHUTDOWN(vp->v_vfsp, SHUTDOWN_DEVICE_REQ, f, l);
}
struct vnode *
vn_initialize(
struct inode *inode)

View File

@ -514,6 +514,8 @@ extern void vn_revalidate_core(struct vnode *, vattr_t *);
extern void vn_iowait(struct vnode *vp);
extern void vn_iowake(struct vnode *vp);
extern void vn_ioerror(struct vnode *vp, int error, char *f, int l);
static inline int vn_count(struct vnode *vp)
{
return atomic_read(&vn_to_inode(vp)->i_count);

View File

@ -1261,7 +1261,7 @@ xfs_qm_dqflush(
if (xfs_qm_dqcheck(&dqp->q_core, be32_to_cpu(ddqp->d_id),
0, XFS_QMOPT_DOWARN, "dqflush (incore copy)")) {
xfs_force_shutdown(dqp->q_mount, XFS_CORRUPT_INCORE);
xfs_force_shutdown(dqp->q_mount, SHUTDOWN_CORRUPT_INCORE);
return XFS_ERROR(EIO);
}

View File

@ -4263,8 +4263,8 @@ xfs_bmap_finish(
if (!XFS_FORCED_SHUTDOWN(mp))
xfs_force_shutdown(mp,
(error == EFSCORRUPTED) ?
XFS_CORRUPT_INCORE :
XFS_METADATA_IO_ERROR);
SHUTDOWN_CORRUPT_INCORE :
SHUTDOWN_META_IO_ERROR);
return error;
}
xfs_trans_log_efd_extent(ntp, efd, free->xbfi_startblock,

View File

@ -1108,7 +1108,7 @@ xfs_buf_error_relse(
XFS_BUF_ERROR(bp,0);
xfs_buftrace("BUF_ERROR_RELSE", bp);
if (! XFS_FORCED_SHUTDOWN(mp))
xfs_force_shutdown(mp, XFS_METADATA_IO_ERROR);
xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR);
/*
* We have to unpin the pinned buffers so do the
* callbacks.

View File

@ -578,17 +578,18 @@ xfs_fs_goingdown(
struct super_block *sb = freeze_bdev(vfsp->vfs_super->s_bdev);
if (sb && !IS_ERR(sb)) {
xfs_force_shutdown(mp, XFS_FORCE_UMOUNT);
xfs_force_shutdown(mp, SHUTDOWN_FORCE_UMOUNT);
thaw_bdev(sb->s_bdev, sb);
}
break;
}
case XFS_FSOP_GOING_FLAGS_LOGFLUSH:
xfs_force_shutdown(mp, XFS_FORCE_UMOUNT);
xfs_force_shutdown(mp, SHUTDOWN_FORCE_UMOUNT);
break;
case XFS_FSOP_GOING_FLAGS_NOLOGFLUSH:
xfs_force_shutdown(mp, XFS_FORCE_UMOUNT|XFS_LOG_IO_ERROR);
xfs_force_shutdown(mp,
SHUTDOWN_FORCE_UMOUNT | SHUTDOWN_LOG_IO_ERROR);
break;
default:
return XFS_ERROR(EINVAL);

View File

@ -3206,7 +3206,7 @@ xfs_iflush(
corrupt_out:
xfs_buf_relse(bp);
xfs_force_shutdown(mp, XFS_CORRUPT_INCORE);
xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
xfs_iflush_abort(ip);
/*
* Unlocks the flush lock
@ -3228,7 +3228,7 @@ xfs_iflush(
xfs_buf_relse(bp);
}
xfs_force_shutdown(mp, XFS_CORRUPT_INCORE);
xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
if(!bufwasdelwri) {
/*

View File

@ -402,7 +402,7 @@ xfs_log_release_iclog(xfs_mount_t *mp,
xlog_in_core_t *iclog = (xlog_in_core_t *)iclog_hndl;
if (xlog_state_release_iclog(log, iclog)) {
xfs_force_shutdown(mp, XFS_LOG_IO_ERROR);
xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR);
return EIO;
}
@ -726,7 +726,7 @@ xfs_log_write(xfs_mount_t * mp,
return XFS_ERROR(EIO);
if ((error = xlog_write(mp, reg, nentries, tic, start_lsn, NULL, 0))) {
xfs_force_shutdown(mp, XFS_LOG_IO_ERROR);
xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR);
}
return error;
} /* xfs_log_write */
@ -956,7 +956,7 @@ xlog_iodone(xfs_buf_t *bp)
XFS_ERRTAG_IODONE_IOERR, XFS_RANDOM_IODONE_IOERR)) {
xfs_ioerror_alert("xlog_iodone", l->l_mp, bp, XFS_BUF_ADDR(bp));
XFS_BUF_STALE(bp);
xfs_force_shutdown(l->l_mp, XFS_LOG_IO_ERROR);
xfs_force_shutdown(l->l_mp, SHUTDOWN_LOG_IO_ERROR);
/*
* This flag will be propagated to the trans-committed
* callback routines to let them know that the log-commit
@ -1261,7 +1261,7 @@ xlog_commit_record(xfs_mount_t *mp,
ASSERT_ALWAYS(iclog);
if ((error = xlog_write(mp, reg, 1, ticket, commitlsnp,
iclog, XLOG_COMMIT_TRANS))) {
xfs_force_shutdown(mp, XFS_LOG_IO_ERROR);
xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR);
}
return error;
} /* xlog_commit_record */
@ -1790,7 +1790,7 @@ xlog_write(xfs_mount_t * mp,
xfs_cmn_err(XFS_PTAG_LOGRES, CE_ALERT, mp,
"xfs_log_write: reservation ran out. Need to up reservation");
/* If we did not panic, shutdown the filesystem */
xfs_force_shutdown(mp, XFS_CORRUPT_INCORE);
xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
#endif
} else
ticket->t_curr_res -= len;

View File

@ -282,7 +282,7 @@ xlog_recover_iodone(
mp = XFS_BUF_FSPRIVATE(bp, xfs_mount_t *);
xfs_ioerror_alert("xlog_recover_iodone",
mp, bp, XFS_BUF_ADDR(bp));
xfs_force_shutdown(mp, XFS_METADATA_IO_ERROR);
xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR);
}
XFS_BUF_SET_FSPRIVATE(bp, NULL);
XFS_BUF_CLR_IODONE_FUNC(bp);

View File

@ -513,15 +513,6 @@ xfs_preferred_iosize(xfs_mount_t *mp)
#define xfs_force_shutdown(m,f) \
VFS_FORCE_SHUTDOWN((XFS_MTOVFS(m)), f, __FILE__, __LINE__)
/*
* Flags sent to xfs_force_shutdown.
*/
#define XFS_METADATA_IO_ERROR 0x1
#define XFS_LOG_IO_ERROR 0x2
#define XFS_FORCE_UMOUNT 0x4
#define XFS_CORRUPT_INCORE 0x8 /* Corrupt in-memory data structures */
#define XFS_SHUTDOWN_REMOTE_REQ 0x10 /* Shutdown came from remote cell */
/*
* Flags for xfs_mountfs
*/

View File

@ -109,12 +109,12 @@ xfs_do_force_shutdown(
xfs_mount_t *mp;
mp = XFS_BHVTOM(bdp);
logerror = flags & XFS_LOG_IO_ERROR;
logerror = flags & SHUTDOWN_LOG_IO_ERROR;
if (!(flags & XFS_FORCE_UMOUNT)) {
cmn_err(CE_NOTE,
"xfs_force_shutdown(%s,0x%x) called from line %d of file %s. Return address = 0x%p",
mp->m_fsname,flags,lnnum,fname,__return_address);
if (!(flags & SHUTDOWN_FORCE_UMOUNT)) {
cmn_err(CE_NOTE, "xfs_force_shutdown(%s,0x%x) called from "
"line %d of file %s. Return address = 0x%p",
mp->m_fsname, flags, lnnum, fname, __return_address);
}
/*
* No need to duplicate efforts.
@ -125,33 +125,37 @@ xfs_do_force_shutdown(
/*
* This flags XFS_MOUNT_FS_SHUTDOWN, makes sure that we don't
* queue up anybody new on the log reservations, and wakes up
* everybody who's sleeping on log reservations and tells
* them the bad news.
* everybody who's sleeping on log reservations to tell them
* the bad news.
*/
if (xfs_log_force_umount(mp, logerror))
return;
if (flags & XFS_CORRUPT_INCORE) {
if (flags & SHUTDOWN_CORRUPT_INCORE) {
xfs_cmn_err(XFS_PTAG_SHUTDOWN_CORRUPT, CE_ALERT, mp,
"Corruption of in-memory data detected. Shutting down filesystem: %s",
mp->m_fsname);
if (XFS_ERRLEVEL_HIGH <= xfs_error_level) {
xfs_stack_trace();
}
} else if (!(flags & XFS_FORCE_UMOUNT)) {
} else if (!(flags & SHUTDOWN_FORCE_UMOUNT)) {
if (logerror) {
xfs_cmn_err(XFS_PTAG_SHUTDOWN_LOGERROR, CE_ALERT, mp,
"Log I/O Error Detected. Shutting down filesystem: %s",
"Log I/O Error Detected. Shutting down filesystem: %s",
mp->m_fsname);
} else if (!(flags & XFS_SHUTDOWN_REMOTE_REQ)) {
} else if (flags & SHUTDOWN_DEVICE_REQ) {
xfs_cmn_err(XFS_PTAG_SHUTDOWN_IOERROR, CE_ALERT, mp,
"I/O Error Detected. Shutting down filesystem: %s",
"All device paths lost. Shutting down filesystem: %s",
mp->m_fsname);
} else if (!(flags & SHUTDOWN_REMOTE_REQ)) {
xfs_cmn_err(XFS_PTAG_SHUTDOWN_IOERROR, CE_ALERT, mp,
"I/O Error Detected. Shutting down filesystem: %s",
mp->m_fsname);
}
}
if (!(flags & XFS_FORCE_UMOUNT)) {
cmn_err(CE_ALERT,
"Please umount the filesystem, and rectify the problem(s)");
if (!(flags & SHUTDOWN_FORCE_UMOUNT)) {
cmn_err(CE_ALERT, "Please umount the filesystem, "
"and rectify the problem(s)");
}
}
@ -335,7 +339,7 @@ xfs_bwrite(
* from bwrite and we could be tracing a buffer that has
* been reused.
*/
xfs_force_shutdown(mp, XFS_METADATA_IO_ERROR);
xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR);
}
return (error);
}

View File

@ -846,7 +846,7 @@ _xfs_trans_commit(
*/
nvec = xfs_trans_count_vecs(tp);
if (nvec == 0) {
xfs_force_shutdown(mp, XFS_LOG_IO_ERROR);
xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR);
goto shut_us_down;
} else if (nvec <= XFS_TRANS_LOGVEC_COUNT) {
log_vector = log_vector_fast;
@ -1148,7 +1148,7 @@ xfs_trans_cancel(
*/
if ((tp->t_flags & XFS_TRANS_DIRTY) && !XFS_FORCED_SHUTDOWN(mp)) {
XFS_ERROR_REPORT("xfs_trans_cancel", XFS_ERRLEVEL_LOW, mp);
xfs_force_shutdown(mp, XFS_CORRUPT_INCORE);
xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
}
#ifdef DEBUG
if (!(flags & XFS_TRANS_ABORT)) {

View File

@ -363,9 +363,10 @@ xfs_trans_delete_ail(
AIL_UNLOCK(mp, s);
else {
xfs_cmn_err(XFS_PTAG_AILDELETE, CE_ALERT, mp,
"xfs_trans_delete_ail: attempting to delete a log item that is not in the AIL");
"%s: attempting to delete a log item that is not in the AIL",
__FUNCTION__);
AIL_UNLOCK(mp, s);
xfs_force_shutdown(mp, XFS_CORRUPT_INCORE);
xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
}
}
}

View File

@ -369,7 +369,7 @@ xfs_trans_read_buf(
*/
if (tp->t_flags & XFS_TRANS_DIRTY)
xfs_force_shutdown(tp->t_mountp,
XFS_METADATA_IO_ERROR);
SHUTDOWN_META_IO_ERROR);
return error;
}
}
@ -414,7 +414,7 @@ xfs_trans_read_buf(
xfs_ioerror_alert("xfs_trans_read_buf", mp,
bp, blkno);
if (tp->t_flags & XFS_TRANS_DIRTY)
xfs_force_shutdown(tp->t_mountp, XFS_METADATA_IO_ERROR);
xfs_force_shutdown(tp->t_mountp, SHUTDOWN_META_IO_ERROR);
xfs_buf_relse(bp);
return error;
}
@ -423,7 +423,7 @@ xfs_trans_read_buf(
if (xfs_error_target == target) {
if (((xfs_req_num++) % xfs_error_mod) == 0) {
xfs_force_shutdown(tp->t_mountp,
XFS_METADATA_IO_ERROR);
SHUTDOWN_META_IO_ERROR);
xfs_buf_relse(bp);
printk("Returning error in trans!\n");
return XFS_ERROR(EIO);

View File

@ -1761,7 +1761,7 @@ xfs_inactive(
cmn_err(CE_NOTE,
"xfs_inactive: xfs_ifree() returned an error = %d on %s",
error, mp->m_fsname);
xfs_force_shutdown(mp, XFS_METADATA_IO_ERROR);
xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR);
}
xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT);
} else {