panic ffs_truncate3 (maybe fuse being evil)
Konstantin Belousov
kostikbel at gmail.com
Wed Feb 3 15:38:59 UTC 2016
On Tue, Feb 02, 2016 at 06:19:28PM -0500, Rick Macklem wrote:
> Kostik wrote:
> > I do think that the IO_UNIT patch fixes some situations where the buffer
> > can be left on the vnode queue. I did not found any other places so far.
Could you, please, try the following explicit buffer relse patch in
addition to the IO_UNIT patch ? This is as similar to r174973 for IO_EXT
ffs2_balloc() as I can do.
diff --git a/sys/ufs/ffs/ffs_balloc.c b/sys/ufs/ffs/ffs_balloc.c
index 8551085..0df0e677 100644
--- a/sys/ufs/ffs/ffs_balloc.c
+++ b/sys/ufs/ffs/ffs_balloc.c
@@ -597,8 +597,10 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size,
ffs_blkpref_ufs2(ip, lastlbn, (int)nb,
&dp->di_extb[0]), osize,
(int)fs->fs_bsize, flags, cred, &bp);
- if (error)
- return (error);
+ if (error != 0) {
+ nsize = fs->fs_bsize;
+ goto fail_ext;
+ }
if (DOINGSOFTDEP(vp))
softdep_setup_allocext(ip, nb,
dbtofsb(fs, bp->b_blkno),
@@ -623,9 +625,9 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size,
if (nb != 0 && dp->di_extsize >= smalllblktosize(fs, lbn + 1)) {
error = bread_gb(vp, -1 - lbn, fs->fs_bsize, NOCRED,
gbflags, &bp);
- if (error) {
- brelse(bp);
- return (error);
+ if (error != 0) {
+ nsize = fs->fs_bsize;
+ goto fail_ext;
}
bp->b_blkno = fsbtodb(fs, nb);
bp->b_xflags |= BX_ALTDATA;
@@ -641,10 +643,8 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size,
if (nsize <= osize) {
error = bread_gb(vp, -1 - lbn, osize, NOCRED,
gbflags, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
+ if (error != 0)
+ goto fail_ext;
bp->b_blkno = fsbtodb(fs, nb);
bp->b_xflags |= BX_ALTDATA;
} else {
@@ -654,8 +654,8 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size,
ffs_blkpref_ufs2(ip, lbn, (int)lbn,
&dp->di_extb[0]), osize, nsize, flags,
cred, &bp);
- if (error)
- return (error);
+ if (error != 0)
+ goto fail_ext;
bp->b_xflags |= BX_ALTDATA;
if (DOINGSOFTDEP(vp))
softdep_setup_allocext(ip, lbn,
@@ -671,8 +671,8 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size,
error = ffs_alloc(ip, lbn,
ffs_blkpref_ufs2(ip, lbn, (int)lbn, &dp->di_extb[0]),
nsize, flags, cred, &newb);
- if (error)
- return (error);
+ if (error != 0)
+ goto fail_ext;
bp = getblk(vp, -1 - lbn, nsize, 0, 0, gbflags);
bp->b_blkno = fsbtodb(fs, newb);
bp->b_xflags |= BX_ALTDATA;
@@ -686,6 +686,14 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size,
ip->i_flag |= IN_CHANGE;
*bpp = bp;
return (0);
+fail_ext:
+ bp = getblk(vp, -1 - lbn, nsize, 0, 0, GB_NOCREAT);
+ if (bp != NULL) {
+ bp->b_flags |= B_RELBUF;
+ bp->b_flags &= ~B_ASYNC;
+ brelse(bp);
+ }
+ return (error);
}
/*
* If the next write will extend the file into a new block,
diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c
index 5a70e5c..ecc3f9b 100644
--- a/sys/ufs/ffs/ffs_vnops.c
+++ b/sys/ufs/ffs/ffs_vnops.c
@@ -1311,7 +1313,8 @@ ffs_close_ea(struct vnode *vp, int commit, struct ucred *cred, struct thread *td
/* XXX: I'm not happy about truncating to zero size */
if (ip->i_ea_len < dp->di_extsize)
error = ffs_truncate(vp, 0, IO_EXT, cred);
- error = ffs_extwrite(vp, &luio, IO_EXT | IO_SYNC, cred);
+ error = ffs_extwrite(vp, &luio, IO_EXT | IO_SYNC | IO_UNIT,
+ cred);
}
if (--ip->i_ea_refs == 0) {
free(ip->i_ea_area, M_TEMP);
More information about the freebsd-fs
mailing list