Skip to content

Commit

Permalink
[XFS] Shutdown the filesystem if all device paths have gone. Made
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Nathan Scott committed Jun 9, 2006
1 parent b76963f commit 7d04a33
Show file tree
Hide file tree
Showing 18 changed files with 78 additions and 57 deletions.
15 changes: 7 additions & 8 deletions fs/xfs/linux-2.6/xfs_aops.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
}
Expand All @@ -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);
Expand Down Expand Up @@ -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;
}
Expand Down
2 changes: 1 addition & 1 deletion fs/xfs/linux-2.6/xfs_aops.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
7 changes: 7 additions & 0 deletions fs/xfs/linux-2.6/xfs_vfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 *,
Expand Down
16 changes: 16 additions & 0 deletions fs/xfs/linux-2.6/xfs_vnode.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 2 additions & 0 deletions fs/xfs/linux-2.6/xfs_vnode.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion fs/xfs/quota/xfs_dquot.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
4 changes: 2 additions & 2 deletions fs/xfs/xfs_bmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion fs/xfs/xfs_buf_item.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
7 changes: 4 additions & 3 deletions fs/xfs/xfs_fsops.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
4 changes: 2 additions & 2 deletions fs/xfs/xfs_inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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) {
/*
Expand Down
10 changes: 5 additions & 5 deletions fs/xfs/xfs_log.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion fs/xfs/xfs_log_recover.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
9 changes: 0 additions & 9 deletions fs/xfs/xfs_mount.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/
Expand Down
36 changes: 20 additions & 16 deletions fs/xfs/xfs_rw.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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)");
}
}

Expand Down Expand Up @@ -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);
}
4 changes: 2 additions & 2 deletions fs/xfs/xfs_trans.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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)) {
Expand Down
5 changes: 3 additions & 2 deletions fs/xfs/xfs_trans_ail.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions fs/xfs/xfs_trans_buf.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
Expand Down Expand Up @@ -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;
}
Expand All @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion fs/xfs/xfs_vnodeops.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down

0 comments on commit 7d04a33

Please sign in to comment.