summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorTed Unangst <tedu@cvs.openbsd.org>2019-02-17 22:17:29 +0000
committerTed Unangst <tedu@cvs.openbsd.org>2019-02-17 22:17:29 +0000
commit1940b4c4b0ca57afc7481e253a0db3ab28f400c4 (patch)
tree2a1ab4a8d9c03ed7213097c751dd9be930feec1f /sys
parentd175c749a6e191f19af3f89d60ecfa13edb39e02 (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.c7
-rw-r--r--sys/kern/vfs_subr.c3
-rw-r--r--sys/kern/vfs_vops.c8
-rw-r--r--sys/sys/vnode.h3
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