From be891954ad33efc87a8c8e70840c78787d627f6f Mon Sep 17 00:00:00 2001 From: bouyer Date: Sun, 7 Feb 2010 17:12:40 +0000 Subject: [PATCH] - ufs_balloc_range(): on error, only PG_RELEASED the pages that were allocated to extend the file to the new size. Releasing all pages may release pages that contains previously-written data not yet flushed to disk. Should fix PR kern/35704 - {ffs,lfs,ext2fs}_truncate(): Even if the inode's size is the same as the new length, call uvm_vnp_setsize(). *_truncate() may have been called by *_write() in the error path (e.g. block allocation failure because of quota of file system full), and at this point v_writesize has been set to the desired size of the file and not reverted to the old size. Not adjusting v_writesize to the real size cause genfs_do_io() to write to disk past the real end of the file. --- sys/ufs/ext2fs/ext2fs_inode.c | 6 ++++-- sys/ufs/ffs/ffs_inode.c | 6 ++++-- sys/ufs/lfs/lfs_inode.c | 9 ++++++--- sys/ufs/ufs/ufs_inode.c | 10 +++++----- 4 files changed, 19 insertions(+), 12 deletions(-) diff --git a/sys/ufs/ext2fs/ext2fs_inode.c b/sys/ufs/ext2fs/ext2fs_inode.c index e149978d42df..ed3e17935b33 100644 --- a/sys/ufs/ext2fs/ext2fs_inode.c +++ b/sys/ufs/ext2fs/ext2fs_inode.c @@ -1,4 +1,4 @@ -/* $NetBSD: ext2fs_inode.c,v 1.70 2009/10/19 18:41:17 bouyer Exp $ */ +/* $NetBSD: ext2fs_inode.c,v 1.71 2010/02/07 17:12:40 bouyer Exp $ */ /* * Copyright (c) 1982, 1986, 1989, 1993 @@ -60,7 +60,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: ext2fs_inode.c,v 1.70 2009/10/19 18:41:17 bouyer Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ext2fs_inode.c,v 1.71 2010/02/07 17:12:40 bouyer Exp $"); #include #include @@ -272,6 +272,8 @@ ext2fs_truncate(struct vnode *ovp, off_t length, int ioflag, return (ext2fs_update(ovp, NULL, NULL, 0)); } if (ext2fs_size(oip) == length) { + /* still do a uvm_vnp_setsize() as writesize may be larger */ + uvm_vnp_setsize(ovp, length); oip->i_flag |= IN_CHANGE | IN_UPDATE; return (ext2fs_update(ovp, NULL, NULL, 0)); } diff --git a/sys/ufs/ffs/ffs_inode.c b/sys/ufs/ffs/ffs_inode.c index b296a05b8762..f7f0aa6e2df0 100644 --- a/sys/ufs/ffs/ffs_inode.c +++ b/sys/ufs/ffs/ffs_inode.c @@ -1,4 +1,4 @@ -/* $NetBSD: ffs_inode.c,v 1.103 2009/02/22 20:28:06 ad Exp $ */ +/* $NetBSD: ffs_inode.c,v 1.104 2010/02/07 17:12:40 bouyer Exp $ */ /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. @@ -61,7 +61,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: ffs_inode.c,v 1.103 2009/02/22 20:28:06 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ffs_inode.c,v 1.104 2010/02/07 17:12:40 bouyer Exp $"); #if defined(_KERNEL_OPT) #include "opt_ffs.h" @@ -238,6 +238,8 @@ ffs_truncate(struct vnode *ovp, off_t length, int ioflag, kauth_cred_t cred) return (ffs_update(ovp, NULL, NULL, 0)); } if (oip->i_size == length) { + /* still do a uvm_vnp_setsize() as writesize may be larger */ + uvm_vnp_setsize(ovp, length); oip->i_flag |= IN_CHANGE | IN_UPDATE; return (ffs_update(ovp, NULL, NULL, 0)); } diff --git a/sys/ufs/lfs/lfs_inode.c b/sys/ufs/lfs/lfs_inode.c index 7e3eea4e1f55..b76b1f28a519 100644 --- a/sys/ufs/lfs/lfs_inode.c +++ b/sys/ufs/lfs/lfs_inode.c @@ -1,4 +1,4 @@ -/* $NetBSD: lfs_inode.c,v 1.120 2008/04/28 20:24:11 martin Exp $ */ +/* $NetBSD: lfs_inode.c,v 1.121 2010/02/07 17:12:40 bouyer Exp $ */ /*- * Copyright (c) 1999, 2000, 2001, 2002, 2003 The NetBSD Foundation, Inc. @@ -60,7 +60,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: lfs_inode.c,v 1.120 2008/04/28 20:24:11 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: lfs_inode.c,v 1.121 2010/02/07 17:12:40 bouyer Exp $"); #if defined(_KERNEL_OPT) #include "opt_quota.h" @@ -226,8 +226,11 @@ lfs_truncate(struct vnode *ovp, off_t length, int ioflag, kauth_cred_t cred) /* * Just return and not update modification times. */ - if (oip->i_size == length) + if (oip->i_size == length) { + /* still do a uvm_vnp_setsize() as writesize may be larger */ + uvm_vnp_setsize(ovp, length); return (0); + } if (ovp->v_type == VLNK && (oip->i_size < ump->um_maxsymlinklen || diff --git a/sys/ufs/ufs/ufs_inode.c b/sys/ufs/ufs/ufs_inode.c index a63a07e8ebc5..f0acd8ac606d 100644 --- a/sys/ufs/ufs/ufs_inode.c +++ b/sys/ufs/ufs/ufs_inode.c @@ -1,4 +1,4 @@ -/* $NetBSD: ufs_inode.c,v 1.78 2009/02/22 20:28:07 ad Exp $ */ +/* $NetBSD: ufs_inode.c,v 1.79 2010/02/07 17:12:40 bouyer Exp $ */ /* * Copyright (c) 1991, 1993 @@ -37,7 +37,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: ufs_inode.c,v 1.78 2009/02/22 20:28:07 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ufs_inode.c,v 1.79 2010/02/07 17:12:40 bouyer Exp $"); #if defined(_KERNEL_OPT) #include "opt_ffs.h" @@ -317,11 +317,11 @@ ufs_balloc_range(struct vnode *vp, off_t off, off_t len, kauth_cred_t cred, GOP_SIZE(vp, off + len, &eob, 0); mutex_enter(&uobj->vmobjlock); for (i = 0; i < npages; i++) { - if (error) { - pgs[i]->flags |= PG_RELEASED; - } else if (off <= pagestart + (i << PAGE_SHIFT) && + if (off <= pagestart + (i << PAGE_SHIFT) && pagestart + ((i + 1) << PAGE_SHIFT) <= eob) { pgs[i]->flags &= ~PG_RDONLY; + } else if (error) { + pgs[i]->flags |= PG_RELEASED; } } if (error) {