tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
ffs disk corruption
Hello,
for some time, I've occasionally seen disk corruption on a NFS server
with quotas.
While working on PR 35704, I found something that could explain it, see
http://mail-index.netbsd.org/tech-kern/2010/02/02/msg007156.html
and with this patch the server stopped showing disk corruption issues.
But is has show up again, with always the same behavior: some directory
blocks are overwritten with 0 (data blocks may be overwritten too, but
I've not yet proof of this).
Locking back at the changes in
http://mail-index.netbsd.org/tech-kern/2010/02/02/msg007156.html
I found what I think are 2 problems, fixed with the attached patch:
- There are places where, after a ufs_balloc_range() erorr, ffs_truncate()
is not called. I guess this can cause the same issue as explained
in the above mail when ffs_truncate() didn't reset v_writesize.
- in ufs_inode.c:ufs_balloc_range(), we clear PG_RDONLY for all pages
up to the new size, even if block allocation failed. I think in this case
we should clear it up to the old size, PG_RELEASEDing all newly
allocated pages that have no data blocks on disk.
Does anyone see something wrong with this analysis or the attached patch ?
I've not tested this on the NFS server yet, but the test from PR 35704
still passes.
--
Manuel Bouyer <bouyer%antioche.eu.org@localhost>
NetBSD: 26 ans d'experience feront toujours la difference
--
Index: ffs/ffs_inode.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/ffs/ffs_inode.c,v
retrieving revision 1.99.4.1
diff -u -p -u -r1.99.4.1 ffs_inode.c
--- ffs/ffs_inode.c 22 Feb 2010 04:43:46 -0000 1.99.4.1
+++ ffs/ffs_inode.c 22 Nov 2011 12:35:00 -0000
@@ -273,8 +273,10 @@ ffs_truncate(struct vnode *ovp, off_t le
uvm_vnp_setwritesize(ovp, eob);
error = ufs_balloc_range(ovp, osize, eob - osize,
cred, aflag);
- if (error)
+ if (error) {
+ (void) ffs_truncate(ovp, osize, ioflag &
IO_SYNC, cred);
return error;
+ }
if (ioflag & IO_SYNC) {
mutex_enter(&ovp->v_interlock);
VOP_PUTPAGES(ovp,
Index: lfs/lfs_inode.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/lfs/lfs_inode.c,v
retrieving revision 1.120.10.1
diff -u -p -u -r1.120.10.1 lfs_inode.c
--- lfs/lfs_inode.c 22 Feb 2010 04:43:46 -0000 1.120.10.1
+++ lfs/lfs_inode.c 22 Nov 2011 12:35:00 -0000
@@ -276,8 +276,11 @@ lfs_truncate(struct vnode *ovp, off_t le
uvm_vnp_setwritesize(ovp, eob);
error = ufs_balloc_range(ovp, osize,
eob - osize, cred, aflags);
- if (error)
+ if (error) {
+ (void) lfs_truncate(ovp, osize,
+ ioflag & IO_SYNC, cred);
return error;
+ }
if (ioflag & IO_SYNC) {
mutex_enter(&ovp->v_interlock);
VOP_PUTPAGES(ovp,
Index: ufs/ufs_inode.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/ufs/ufs_inode.c,v
retrieving revision 1.76.4.5
diff -u -p -u -r1.76.4.5 ufs_inode.c
--- ufs/ufs_inode.c 16 Jul 2011 00:19:13 -0000 1.76.4.5
+++ ufs/ufs_inode.c 22 Nov 2011 12:35:00 -0000
@@ -306,7 +306,7 @@ ufs_balloc_range(struct vnode *vp, off_t
* (since they now have backing store) and unbusy them.
*/
- GOP_SIZE(vp, off + len, &eob, 0);
+ GOP_SIZE(vp, error ? off : (off + len), &eob, 0);
mutex_enter(&uobj->vmobjlock);
for (i = 0; i < npages; i++) {
if (off <= pagestart + (i << PAGE_SHIFT) &&
Home |
Main Index |
Thread Index |
Old Index