diff options
author | Ted Unangst <tedu@cvs.openbsd.org> | 2019-02-17 22:17:29 +0000 |
---|---|---|
committer | Ted Unangst <tedu@cvs.openbsd.org> | 2019-02-17 22:17:29 +0000 |
commit | 1940b4c4b0ca57afc7481e253a0db3ab28f400c4 (patch) | |
tree | 2a1ab4a8d9c03ed7213097c751dd9be930feec1f /sys | |
parent | d175c749a6e191f19af3f89d60ecfa13edb39e02 (diff) |
if a write fails, we mark the buffer invalid and throw it away. this can
lead to lost errors, where a later fsync will return success. to fix this,
set a flag on the vnode indicating a past error has occurred, and return
an error for future fsync calls.
ok bluhm deraadt visa
Diffstat (limited to 'sys')
-rw-r--r-- | sys/kern/vfs_bio.c | 7 | ||||
-rw-r--r-- | sys/kern/vfs_subr.c | 3 | ||||
-rw-r--r-- | sys/kern/vfs_vops.c | 8 | ||||
-rw-r--r-- | sys/sys/vnode.h | 3 |
4 files changed, 16 insertions, 5 deletions
diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c index ea42c50f73d..a02bf70e354 100644 --- a/sys/kern/vfs_bio.c +++ b/sys/kern/vfs_bio.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vfs_bio.c,v 1.187 2018/11/21 16:14:43 mpi Exp $ */ +/* $OpenBSD: vfs_bio.c,v 1.188 2019/02/17 22:17:28 tedu Exp $ */ /* $NetBSD: vfs_bio.c,v 1.44 1996/06/11 11:15:36 pk Exp $ */ /* @@ -867,6 +867,11 @@ brelse(struct buf *bp) /* If it's not cacheable, or an error, mark it invalid. */ if (ISSET(bp->b_flags, (B_NOCACHE|B_ERROR))) SET(bp->b_flags, B_INVAL); + /* If it's a write error, also mark the vnode as damaged. */ + if (ISSET(bp->b_flags, B_ERROR) && !ISSET(bp->b_flags, B_READ)) { + if (bp->b_vp && bp->b_vp->v_type == VREG) + SET(bp->b_vp->v_bioflag, VBIOERROR); + } if (ISSET(bp->b_flags, B_INVAL)) { /* diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index a15481c73f9..ed5bbd1be61 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vfs_subr.c,v 1.285 2019/01/21 18:09:21 anton Exp $ */ +/* $OpenBSD: vfs_subr.c,v 1.286 2019/02/17 22:17:28 tedu Exp $ */ /* $NetBSD: vfs_subr.c,v 1.53 1996/04/22 01:39:13 christos Exp $ */ /* @@ -712,6 +712,7 @@ vputonfreelist(struct vnode *vp) #endif vp->v_bioflag |= VBIOONFREELIST; + vp->v_bioflag &= ~VBIOERROR; if (vp->v_holdcnt > 0) lst = &vnode_hold_list; diff --git a/sys/kern/vfs_vops.c b/sys/kern/vfs_vops.c index 32fcb4a24cc..7b9cf43dfc4 100644 --- a/sys/kern/vfs_vops.c +++ b/sys/kern/vfs_vops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vfs_vops.c,v 1.19 2018/06/21 14:17:23 visa Exp $ */ +/* $OpenBSD: vfs_vops.c,v 1.20 2019/02/17 22:17:28 tedu Exp $ */ /* * Copyright (c) 2010 Thordur I. Bjornsson <thib@openbsd.org> * @@ -336,7 +336,7 @@ int VOP_FSYNC(struct vnode *vp, struct ucred *cred, int waitfor, struct proc *p) { - int r; + int r, s; struct vop_fsync_args a; a.a_vp = vp; a.a_cred = cred; @@ -351,6 +351,10 @@ VOP_FSYNC(struct vnode *vp, struct ucred *cred, int waitfor, vp->v_inflight++; r = (vp->v_op->vop_fsync)(&a); vp->v_inflight--; + s = splbio(); + if (r == 0 && vp->v_bioflag & VBIOERROR) + r = EIO; + splx(s); return r; } diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index f060698367d..c7d6964d056 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -1,4 +1,4 @@ -/* $OpenBSD: vnode.h,v 1.149 2018/12/23 10:46:51 natano Exp $ */ +/* $OpenBSD: vnode.h,v 1.150 2019/02/17 22:17:28 tedu Exp $ */ /* $NetBSD: vnode.h,v 1.38 1996/02/29 20:59:05 cgd Exp $ */ /* @@ -149,6 +149,7 @@ struct vnode { #define VBIOWAIT 0x0001 /* waiting for output to complete */ #define VBIOONSYNCLIST 0x0002 /* Vnode is on syncer worklist */ #define VBIOONFREELIST 0x0004 /* Vnode is on a free list */ +#define VBIOERROR 0x0008 /* A write failed */ /* * Vnode attributes. A field value of VNOVAL represents a field whose value |