When can a struct buf's b_lblkno field by < 0 ?

Kirk McKusick mckusick at mckusick.com
Sat Apr 13 15:15:11 UTC 2019


> Date: Fri, 12 Apr 2019 18:41:17 +0300
> From: Konstantin Belousov <kostikbel at gmail.com>
> To: Alan Somers <asomers at freebsd.org>
> Cc: FreeBSD Hackers <freebsd-hackers at freebsd.org>,
>         Kirk McKusick <mckusick at mckusick.com>
> Subject: Re: When can a struct buf's b_lblkno field by < 0 ?
> 
> On Fri, Apr 12, 2019 at 09:10:58AM -0600, Alan Somers wrote:
>> In struct buf, b_lblkno is documented as "Logical block number".  I
>> would expect that to always be nonnegative.  However, vtruncbuf loops
>> through a list of buffers, skipping those where "bp->b_lblkno > 0".
>> Maybe that's just an awkward way of writing "do something for the
>> buffer where b_lblkno == 0", but SVN archaeology suggests otherwise.
>> Before r112182, the code looked like this, implying that the b_lblkno
>> could actually be negative:
>> 
>> if ((bp->b_flags & B_DELWRI) && (bp->b_lblkno < 0)) {
>> 
>> Does anybody know under what circumstances that field might be
>> negative?
> 
> Yes, somebody know.  Better list for such discussions is fs at .
> 
> It is up to the filesystem to use any values of b_lblkno as it finds
> suitable.  For instance, for UFS lblknos -1 and -2 are used for the
> blocks carrying the extended attributes of inode.  Lower values
> are used to cache indirect block' pages in the normal vnode page queue,
> so that the pages effectively appear as having very large page indexes.
> 
>>  Also, was r112182 a correct change?  It appears to have
>> negated "<" and gotten ">", neglecting the "==" case.
>> https://svnweb.freebsd.org/base/head/sys/kern/vfs_subr.c?r1=112182&r2=112181&pathrev=112182
> 
> This is innocent, in worst case it results in unneeded syncing.  But I
> wonder why do we still have this loop for 'if (length > 0)' case.  I do
> not quite follow the purpose of syncing all indirect and extended blocks
> on truncation.  It might somewhat help SU to ensure that dependencies
> carried by indirect blocks are flushed timely after truncation, but this
> is too vague.
> 
> I added Kirk who may know more history there.

I don't have much to add to kib's commentary. The change in -r112182
was not meant to have functional change, just reduce indentation and
get rid of unnecessary code. The change should have been to 
(bp->b_lblkno >= 0), but the effect is that if logical data block 0
is in the cache and dirty it will be unnecessarily written. At that
time all partial truncations were done synchronously, hence the
flushing of all the meta-data. With the additional of journaled soft
updates, it became possible to do partial truncations asynchronously.

	Kirk McKusick


More information about the freebsd-hackers mailing list