- 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.
This commit is contained in:
bouyer 2010-02-07 17:12:40 +00:00
parent 1ce16876f7
commit be891954ad
4 changed files with 19 additions and 12 deletions

View File

@ -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 * Copyright (c) 1982, 1986, 1989, 1993
@ -60,7 +60,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__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 <sys/param.h> #include <sys/param.h>
#include <sys/systm.h> #include <sys/systm.h>
@ -272,6 +272,8 @@ ext2fs_truncate(struct vnode *ovp, off_t length, int ioflag,
return (ext2fs_update(ovp, NULL, NULL, 0)); return (ext2fs_update(ovp, NULL, NULL, 0));
} }
if (ext2fs_size(oip) == length) { 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; oip->i_flag |= IN_CHANGE | IN_UPDATE;
return (ext2fs_update(ovp, NULL, NULL, 0)); return (ext2fs_update(ovp, NULL, NULL, 0));
} }

View File

@ -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. * Copyright (c) 2008 The NetBSD Foundation, Inc.
@ -61,7 +61,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__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) #if defined(_KERNEL_OPT)
#include "opt_ffs.h" #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)); return (ffs_update(ovp, NULL, NULL, 0));
} }
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);
oip->i_flag |= IN_CHANGE | IN_UPDATE; oip->i_flag |= IN_CHANGE | IN_UPDATE;
return (ffs_update(ovp, NULL, NULL, 0)); return (ffs_update(ovp, NULL, NULL, 0));
} }

View File

@ -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. * Copyright (c) 1999, 2000, 2001, 2002, 2003 The NetBSD Foundation, Inc.
@ -60,7 +60,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__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) #if defined(_KERNEL_OPT)
#include "opt_quota.h" #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. * 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); return (0);
}
if (ovp->v_type == VLNK && if (ovp->v_type == VLNK &&
(oip->i_size < ump->um_maxsymlinklen || (oip->i_size < ump->um_maxsymlinklen ||

View File

@ -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 * Copyright (c) 1991, 1993
@ -37,7 +37,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__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) #if defined(_KERNEL_OPT)
#include "opt_ffs.h" #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); GOP_SIZE(vp, off + len, &eob, 0);
mutex_enter(&uobj->vmobjlock); mutex_enter(&uobj->vmobjlock);
for (i = 0; i < npages; i++) { for (i = 0; i < npages; i++) {
if (error) { if (off <= pagestart + (i << PAGE_SHIFT) &&
pgs[i]->flags |= PG_RELEASED;
} else if (off <= pagestart + (i << PAGE_SHIFT) &&
pagestart + ((i + 1) << PAGE_SHIFT) <= eob) { pagestart + ((i + 1) << PAGE_SHIFT) <= eob) {
pgs[i]->flags &= ~PG_RDONLY; pgs[i]->flags &= ~PG_RDONLY;
} else if (error) {
pgs[i]->flags |= PG_RELEASED;
} }
} }
if (error) { if (error) {