postgres.git / summary / log / commit / refs

commit    a50d97625497b76e3dc7c4aa22cd2c70317ec54d
Author:   Alvaro Herrera <alvherre@alvh.no-ip.org>
Date:     Thu Jan 02 21:17:07 2014 +0000
First released in: 9.4.0, 9.3.3

    Wrap multixact/members correctly during extension
    
    In the 9.2 code for extending multixact/members, the logic was very
    simple because the number of entries in a members page was a proper
    divisor of 2^32, and thus at 2^32 wraparound the logic for page switch
    was identical than at any other page boundary.  In commit 0ac5ad5134f I
    failed to realize this and introduced code that was not able to go over
    the 2^32 boundary.  Fix that by ensuring that when we reach the last
    page of the last segment we correctly zero the initial page of the
    initial segment, using correct uint32-wraparound-safe arithmetic.
    
    Noticed while investigating bug #8673 reported by Serge Negodyuck, as
    diagnosed by Andres Freund.


src/backend/access/transam/multixact.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c index 60c3370ece2..e2b31ee441f 100644 --- a/src/backend/access/transam/multixact.c +++ b/src/backend/access/transam/multixact.c @@ -2259,7 +2259,6 @@ ExtendMultiXactMember(MultiXactOffset offset, int nmembers) { int flagsoff; int flagsbit; - int difference; /* * Only zero when at first entry of a page. @@ -2280,10 +2279,25 @@ ExtendMultiXactMember(MultiXactOffset offset, int nmembers) LWLockRelease(MultiXactMemberControlLock); } - /* Advance to next page (OK if nmembers goes negative) */ - difference = MULTIXACT_MEMBERS_PER_PAGE - offset % MULTIXACT_MEMBERS_PER_PAGE; - offset += difference; - nmembers -= difference; + /* + * Advance to next page, taking care to properly handle the wraparound + * case. OK if nmembers goes negative. + */ + if ((unsigned int) (offset + nmembers) < offset) + { + uint32 difference = offset + MULTIXACT_MEMBERS_PER_PAGE; + + nmembers -= (unsigned int) (MULTIXACT_MEMBERS_PER_PAGE - difference); + offset = 0; + } + else + { + int difference; + + difference = MULTIXACT_MEMBERS_PER_PAGE - offset % MULTIXACT_MEMBERS_PER_PAGE; + nmembers -= difference; + offset += difference; + } } } [parent: 722acf51a0d0]