<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<meta name="Generator" content="Microsoft Exchange Server">
<!-- converted from text --><style><!-- .EmailQuote { margin-left: 1pt; padding-left: 4pt; border-left: #800000 2px solid; } --></style>
</head>
<body>
<div>
<div style="font-family:Calibri,sans-serif">
<div dir="ltr">So, actually the original comparison in the assert (dodgy scaling factor not withstanding) was probably correct in that we don't ever want to remove all blocks from the inode as one of them is used for the inode itself? Or do we still think it
 should allow for change to be the negative of current blocks?</div>
<br>
<div dir="ltr">Mark</div>
<hr>
<b>From:</b> Andreas Gruenbacher <agruenba@redhat.com><br>
<b>Sent:</b> Wednesday, 9 January 2019 17:24<br>
<b>To:</b> Tim Smith <tim.smith@citrix.com><br>
<b>CC:</b> Mark Syms <Mark.Syms@citrix.com>,cluster-devel <cluster-devel@redhat.com>,Igor Druzhinin <igor.druzhinin@citrix.com><br>
<b>Subject:</b> Re: [Cluster-devel] kernel BUG at fs/gfs2/inode.h:64<br>
<br>
<br>
</div>
</div>
<font size="2"><span style="font-size:10pt;">
<div class="PlainText">On Wed, 9 Jan 2019 at 18:14, Tim Smith <tim.smith@citrix.com> wrote:<br>
><br>
> On Wednesday, 9 January 2019 15:35:05 GMT Andreas Gruenbacher wrote:<br>
> > On Wed, 9 Jan 2019 at 14:43, Mark Syms <Mark.Syms@citrix.com> wrote:<br>
> > > We don't yet know how the assert got triggered as we've only seen it once<br>
> > > and in the original form it looks like it would be very hard to trigger in<br>
> > > any normal case (given that in default usage i_blocks should be at least 8<br>
> > > times what any putative value for change could be). So, for the assert to<br>
> > > have triggered we've been asked to remove at least 8 times the number of<br>
> > > blocks currently allocated to the inode. Possible causes could be a double<br>
> > > release or some other higher level bug that will require further<br>
> > > investigation to uncover.<br>
> ><br>
> > The following change has at least survived xfstests:<br>
> ><br>
> > --- a/fs/gfs2/inode.h<br>
> > +++ b/fs/gfs2/inode.h<br>
> > @@ -61,8 +61,8 @@ static inline u64 gfs2_get_inode_blocks(const struct<br>
> > inode *inode)<br>
> ><br>
> >  static inline void gfs2_add_inode_blocks(struct inode *inode, s64 change)<br>
> >  {<br>
> > -    gfs2_assert(GFS2_SB(inode), (change >= 0 || inode->i_blocks ><br>
> > -change));<br>
> > -    change *= (GFS2_SB(inode)->sd_sb.sb_bsize/GFS2_BASIC_BLOCK);<br>
> > +    change <<= inode->i_blkbits - 9;<br>
> > +    gfs2_assert(GFS2_SB(inode), change >= 0 || inode->i_blocks >= -change);<br>
> > inode->i_blocks += change;<br>
> >  }<br>
> ><br>
> > Andreas<br>
><br>
> I'll use<br>
><br>
> change <<= (GFS2_SB(inode)->sd_sb.sb_bsize_shift - GFS2_BASIC_BLOCK_SHIFT);<br>
><br>
> for consistency with the gfs2_get/set_inode_blocks(). I'll send the patch in a<br>
> bit.<br>
><br>
> Given what it was like before, either i_blocks was already 0 or -change<br>
> somehow became stupidly huge. Anything else looks like it would be hard to<br>
> reproduce without mkfs.gfs2 -b 512 (so that GFS2_SB(inode)->sd_sb.sb_bsize ==<br>
> GFS2_BASIC_BLOCK) which we don't do.<br>
><br>
> I'll try to work out what could have caused it and see if we can provoke it<br>
> again.<br>
><br>
> Out of curiosity I did a few tests where I created a file on GFS2, copied /<br>
> dev/null on top of it, and then ran stat on the file. It seems like GFS2 never<br>
> frees the last allocation on truncate; stat always reports 1, 2, 4 or 8 blocks<br>
> in use for a zero-length file depending on the underlying filesystem block<br>
> size, unlike (say) ext3/4 where it reports 0. I presume this is intentional so<br>
> maybe some corner case where it *is* trying to do that is the root of the<br>
> problem.<br>
<br>
Yes, that's intentional. An empty file without extended attributes<br>
consumes one block. Extended attributes consume at least one<br>
additional block.<br>
<br>
Andreas<br>
</div>
</span></font>
</body>
</html>