mirror of https://gitee.com/openkylin/linux.git
[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:
parent
b76963fac4
commit
7d04a335b6
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 *,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
/*
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue