Skip to content
  • Alex Elder's avatar
    xfs: simplify XLOG_SECTOR_ROUND*() · 8511998b
    Alex Elder authored
    
    
    XLOG_SECTOR_ROUNDUP_BBCOUNT() is defined in "fs/xfs/xfs_log_recover.c"
    in an overly-complicated way.  It is basically roundup(), but that
    is not at all clear from its definition.  (Actually, there is
    another macro round_up() that applies for power-of-two-based masks
    which I'll be using here.)
    
    The operands in XLOG_SECTOR_ROUNDUP_BBCOUNT() are basically the
    block number (bbs) and the log sector basic block mask
    (log->l_sectbb_mask).  I'll call them B and M for this discussion.
    
    The macro computes is value this way:
    	M && (B & M) ? (B + M + 1) & ~M : B
    
    Put another way, we can break it into 3 cases:
    	1)  ! M          -> B			# 0 mask, no effect
    	2)  ! (B & M)    -> B			# sector aligned
    	3)  M && (B & M) -> (B + M + 1) & ~M	# round up otherwise
    
    The round_up() macro is cleverly defined using a value, v, and a
    power-of-2, p, and the result is the nearest multiple of p greater
    than or equal to v.  Its value is computed something like this:
    	((v - 1) | (p - 1)) + 1
    Let's consider using this in the context of the 3 cases above.
    
    When p = 2^0 = 1, the result boils down to ((v - 1) | 0) + 1, so it
    just translates any value v to itself.  That handles case (1) above.
    
    When p = 2^n, n > 0, we know that (p - 1) will be a mask with all n
    bits 0..n-1 set.  The condition in this case occurs when none of
    those mask bits is set in the value v provided.  If that is the
    case, subtracting 1 from v will have 1's in all those lower bits (at
    least).  Therefore, OR-ing the mask with that decremented value has
    no effect, so adding the 1 back again will just translate the v to
    itself.  This handles case (2).
    
    Otherwise, the value v is greater than some multiple of p, and
    decrementing it will produce a result greater than or equal to that
    multiple.  OR-ing in the mask will produce a value 1 less than the
    next multiple of p, so finally adding 1 back will result in the
    desired rounded-up value.  This handles case (3).
    
    Hopefully this is convincing.
    
    While I was at it, I converted XLOG_SECTOR_ROUNDDOWN_BLKNO() to use
    the round_down() macro.
    
    Signed-off-by: default avatarAlex Elder <aelder@sgi.com>
    Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
    Signed-off-by: default avatarDave Chinner <dchinner@redhat.com>
    8511998b