• Andres Freund's avatar
    Don't open formally non-existent segments in _mdfd_getseg(). · 72a98a63
    Andres Freund authored
    Before this commit _mdfd_getseg(), in contrast to mdnblocks(), did not
    verify whether all segments leading up to the to-be-opened one, were
    RELSEG_SIZE sized. That is e.g. not the case after truncating a
    relation, because later segments just get truncated to zero length, not
    removed.
    
    Once a "non-existent" segment has been opened in a session, mdnblocks()
    will return wrong results, causing errors like "could not read block %u
    in file" when accessing blocks. Closing the session, or the later
    arrival of relevant invalidation messages, would "fix" the problem.
    
    That, so far, was mostly harmless, because most segment accesses are
    only done after an mdnblocks() call. But since 428b1d6b we try to
    open segments that might have been deleted, to trigger kernel writeback
    from a backend's queue of recent writes.
    
    To fix check segment sizes in _mdfd_getseg() when opening previously
    unopened segments. In practice this shouldn't imply a lot of additional
    lseek() calls, because mdnblocks() will most of the time already have
    opened all relevant segments.
    
    This commit also fixes a second problem, namely that _mdfd_getseg(
    EXTENSION_RETURN_NULL) extends files during recovery, which is not
    desirable for the mdwriteback() case.  Add EXTENSION_REALLY_RETURN_NULL,
    which does not behave that way, and use it.
    
    Reported-By: Thom Brown
    Author: Andres Freund, Abhijit Menon-Sen
    Reviewd-By: Robert Haas, Fabien Coehlo
    Discussion: CAA-aLv6Dp_ZsV-44QA-2zgkqWKQq=GedBX2dRSrWpxqovXK=Pg@mail.gmail.com
    Fixes: 428b1d6b
    72a98a63
md.c 57.9 KB