aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namei.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-05-03 13:16:43 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-05-03 17:01:40 -0400
commite419b4cc585680940bc42f8ca8a071d6023fb1bb (patch)
tree8fce0f12b7b2a0fdca7a937af137910011efa783 /fs/namei.c
parentac001e76546523ec2ef05b2f7001d8fdc588d069 (diff)
vfs: make word-at-a-time accesses handle a non-existing page
It turns out that there are more cases than CONFIG_DEBUG_PAGEALLOC that can have holes in the kernel address space: it seems to happen easily with Xen, and it looks like the AMD gart64 code will also punch holes dynamically. Actually hitting that case is still very unlikely, so just do the access, and take an exception and fix it up for the very unlikely case of it being a page-crosser with no next page. And hey, this abstraction might even help other architectures that have other issues with unaligned word accesses than the possible missing next page. IOW, this could do the byte order magic too. Peter Anvin fixed a thinko in the shifting for the exception case. Reported-and-tested-by: Jana Saout <jana@saout.de> Cc: Peter Anvin <hpa@zytor.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/namei.c')
-rw-r--r--fs/namei.c4
1 files changed, 2 insertions, 2 deletions
diff --git a/fs/namei.c b/fs/namei.c
index 0062dd17eb55..c42791914f82 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1429,7 +1429,7 @@ unsigned int full_name_hash(const unsigned char *name, unsigned int len)
1429 unsigned long hash = 0; 1429 unsigned long hash = 0;
1430 1430
1431 for (;;) { 1431 for (;;) {
1432 a = *(unsigned long *)name; 1432 a = load_unaligned_zeropad(name);
1433 if (len < sizeof(unsigned long)) 1433 if (len < sizeof(unsigned long))
1434 break; 1434 break;
1435 hash += a; 1435 hash += a;
@@ -1459,7 +1459,7 @@ static inline unsigned long hash_name(const char *name, unsigned int *hashp)
1459 do { 1459 do {
1460 hash = (hash + a) * 9; 1460 hash = (hash + a) * 9;
1461 len += sizeof(unsigned long); 1461 len += sizeof(unsigned long);
1462 a = *(unsigned long *)(name+len); 1462 a = load_unaligned_zeropad(name+len);
1463 /* Do we have any NUL or '/' bytes in this word? */ 1463 /* Do we have any NUL or '/' bytes in this word? */
1464 mask = has_zero(a) | has_zero(a ^ REPEAT_BYTE('/')); 1464 mask = has_zero(a) | has_zero(a ^ REPEAT_BYTE('/'));
1465 } while (!mask); 1465 } while (!mask);