Re: ffs_truncate3 panics

From: Rick Macklem <rmacklem_at_uoguelph.ca>
Date: Sun, 12 Aug 2018 12:25:58 +0000
Konstantin Belousov  wrote:
[stuff snipped]
>Problem with this buffer is that BX_ALTDATA bit is not set.
>This is the reason why vinvalbuf(V_ALT) skips it.
[more stuff snipped]
>The vnode is exclusively locked. Other thread must not be able to
>instantiate a buffer under us.
That's what I thought, but I wasn't sure that UFS never did anything to the buffers
without the vnode lock.
[more stuff snipped]
>This is the patch that I posted long time ago.  It is obviously related
>to missed BX_ALTDATA.  Can you add this patch to your kernel ?
>
>diff --git a/sys/ufs/ffs/ffs_balloc.c b/sys/ufs/ffs/ffs_balloc.c
>index 552c295753d..6d89a229ea7 100644
>--- a/sys/ufs/ffs/ffs_balloc.c
>+++ b/sys/ufs/ffs/ffs_balloc.c
>_at__at_ -682,8 +682,16 _at__at_ 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)
>+                               if (error != 0) {
>+                                       /* getblk does truncation, if needed */
>+                                       bp = getblk(vp, -1 - lbn, osize, 0, 0,
>+                                           GB_NOCREAT);
>+                                       if (bp != NULL) {
>+                                               bp->b_xflags |= BX_ALTDATA;
>+                                               brelse(bp);
>+                                       }
>                                        return (error);
>+                               }
>                                bp->b_xflags |= BX_ALTDATA;
>                                if (DOINGSOFTDEP(vp))
>                                        softdep_setup_allocext(ip, lbn,
>_at__at_ -699,8 +707,17 _at__at_ 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)
>+                       if (error != 0) {
>+                               bp = getblk(vp, -1 - lbn, nsize, 0, 0,
>+                                   GB_NOCREAT);
>+                               if (bp != NULL) {
>+                                       bp->b_xflags |= BX_ALTDATA;
>+                                       bp->b_flags |= B_RELBUF | B_INVAL;
>+                                       bp->b_flags &= ~B_ASYNC;
>+                                       brelse(bp);
>+                               }
>                                return (error);
>+                       }
>                        bp = getblk(vp, -1 - lbn, nsize, 0, 0, gbflags);
>                        bp->b_blkno = fsbtodb(fs, newb);
>                        bp->b_xflags |= BX_ALTDATA;

I don't think this patch helped. I still get printf()s with b_xflags == clear with it
applied. I haven't gotten one that would cause the panic yet, but it didn't
make the BX_ALTDATA flag get set.

However, I have narrowed down how the ones that cause a panic() occur.
Turns out I was wrong when I said di_size == 0 for all these files.
They don't store any data, but if an application does a truncate(2) with length > 0,
the di_size does get set non-zero.
It is when one of these files hits the ffs_truncate() with the extended attribute
buffer on it, that the panic() happens.
(Most of them have di_size == 0 and return from the function in the code block
 that starts with "if (ip->I_size == length)" at around line#299, before the panic()
 check.)

rick
Received on Sun Aug 12 2018 - 10:26:00 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:41:17 UTC