Fix off by one in pfn_valid From Jim Paradis When I gave proposed the fix to pfn_valid() for RHEL4, Stephen Tweedie's sharp eyes caught this: --- quote --- > -#define pfn_valid(pfn) ((pfn) < num_physpages) > +#define pfn_valid(pfn) ((pfn) >= num_physpages ? 0 : \ > + ({ u8 nid__ = pfn_to_nid(pfn); \ > + nid__ != 0xff && (pfn) >= node_start_pfn(nid__) && (pfn) <= node_end_pfn(nid__); })) That's an off-by-one error, isn't it? Looking at some of the setup code for i386 srat.c: start_pfn = paddr >> PAGE_SHIFT; end_pfn = (paddr + size) >> PAGE_SHIFT; which gets pushed unmodified into the node data; so end_pfn is the pfn *after* the last valid one, isn't it? If so, (pfn) <= node_end_pfn(nid__) needs to use "<", not "<=". Other code in x86_64 numa also seems to be making the assumption that size = end_pfn - start_pfn. --- end quote --- (even though x86_64 node_end_pfn() uses node_spanned_pages rather than end_pfn, the issue is exactly the same; node_end_pfn(nid) points to the page *after* the end of the node). Signed-off-by: Andi Kleen Index: linux/include/asm-x86_64/mmzone.h =================================================================== --- linux.orig/include/asm-x86_64/mmzone.h +++ linux/include/asm-x86_64/mmzone.h @@ -54,7 +54,7 @@ static inline __attribute__((pure)) int #define pfn_valid(pfn) ((pfn) >= num_physpages ? 0 : \ ({ u8 nid__ = pfn_to_nid(pfn); \ - nid__ != 0xff && (pfn) >= node_start_pfn(nid__) && (pfn) <= node_end_pfn(nid__); })) + nid__ != 0xff && (pfn) >= node_start_pfn(nid__) && (pfn) < node_end_pfn(nid__); })) #endif #define local_mapnr(kvaddr) \