X-Spam-Checker-Version: SpamAssassin 3.3.0-rupdated (updated) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=-2.4 required=5.0 tests=AWL,BAYES_00,J_CHICKENPOX_35, J_CHICKENPOX_66 autolearn=no version=3.3.0-rupdated Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (8.12.11.20060308/8.12.11/SuSE Linux 0.7) with ESMTP id mB47mXcP003069 for ; Thu, 4 Dec 2008 01:48:39 -0600 Received: from larry.melbourne.sgi.com (larry.melbourne.sgi.com [134.14.52.130]) by relay1.corp.sgi.com (Postfix) with SMTP id A43978F8081 for ; Wed, 3 Dec 2008 23:48:26 -0800 (PST) Received: from [134.14.55.78] (redback.melbourne.sgi.com [134.14.55.78]) by larry.melbourne.sgi.com (950413.SGI.8.6.12/950213.SGI.AUTOCF) via ESMTP id SAA21936 for ; Thu, 4 Dec 2008 18:48:25 +1100 Message-ID: <49378B60.1060603@sgi.com> Date: Thu, 04 Dec 2008 18:48:48 +1100 From: Lachlan McIlroy Reply-To: lachlan@sgi.com User-Agent: Thunderbird 2.0.0.18 (X11/20081105) MIME-Version: 1.0 To: xfs-oss Subject: [PATCH] Fix off by one error in page_region_mask() Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit final is calculated to be the last bit to set (ie inclusive) but when we do the mask shifting final really needs to be first bit not to set. For example if first and final are both bit 0 (ie only first bit to be set) then mask is completely shifted and becomes all zeroes. Or if first is 0 and final is 63 then the mask is shifted one bit when it shouldn't be shifted at all. --- xfs-fix.orig/fs/xfs/linux-2.6/xfs_buf.c +++ xfs-fix/fs/xfs/linux-2.6/xfs_buf.c @@ -129,15 +129,17 @@ page_region_mask( int first, final; first = BTOPR(offset); - final = BTOPRT(offset + length - 1); - first = min(first, final); + final = BTOPRT(offset + length); + + if (first >= final) + return 0UL; mask = ~0UL; mask <<= BITS_PER_LONG - (final - first); mask >>= BITS_PER_LONG - (final); ASSERT(offset + length <= PAGE_CACHE_SIZE); - ASSERT((final - first) < BITS_PER_LONG && (final - first) >= 0); + ASSERT((final - first) <= BITS_PER_LONG && (final - first) > 0); return mask; }