diff options
| author | Dimitri Sivanich <sivanich@sgi.com> | 2012-02-08 15:39:07 -0500 |
|---|---|---|
| committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-02-13 20:45:38 -0500 |
| commit | 074b85175a43a23fdbde60f55feea636e0bf0f85 (patch) | |
| tree | e6f6fdd82854b2bf25ea5b404cee010806a8fced | |
| parent | 1d6f2097865e64963e90cce04980dce2f9fc023f (diff) | |
vfs: fix panic in __d_lookup() with high dentry hashtable counts
When the number of dentry cache hash table entries gets too high
(2147483648 entries), as happens by default on a 16TB system, use of a
signed integer in the dcache_init() initialization loop prevents the
dentry_hashtable from getting initialized, causing a panic in
__d_lookup(). Fix this in dcache_init() and similar areas.
Signed-off-by: Dimitri Sivanich <sivanich@sgi.com>
Acked-by: David S. Miller <davem@davemloft.net>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
| -rw-r--r-- | fs/dcache.c | 8 | ||||
| -rw-r--r-- | fs/inode.c | 8 | ||||
| -rw-r--r-- | kernel/pid.c | 4 | ||||
| -rw-r--r-- | mm/page_alloc.c | 1 | ||||
| -rw-r--r-- | net/ipv4/tcp.c | 5 |
5 files changed, 14 insertions, 12 deletions
diff --git a/fs/dcache.c b/fs/dcache.c index 16a53cc2cc02..fe19ac13f75f 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
| @@ -2968,7 +2968,7 @@ __setup("dhash_entries=", set_dhash_entries); | |||
| 2968 | 2968 | ||
| 2969 | static void __init dcache_init_early(void) | 2969 | static void __init dcache_init_early(void) |
| 2970 | { | 2970 | { |
| 2971 | int loop; | 2971 | unsigned int loop; |
| 2972 | 2972 | ||
| 2973 | /* If hashes are distributed across NUMA nodes, defer | 2973 | /* If hashes are distributed across NUMA nodes, defer |
| 2974 | * hash allocation until vmalloc space is available. | 2974 | * hash allocation until vmalloc space is available. |
| @@ -2986,13 +2986,13 @@ static void __init dcache_init_early(void) | |||
| 2986 | &d_hash_mask, | 2986 | &d_hash_mask, |
| 2987 | 0); | 2987 | 0); |
| 2988 | 2988 | ||
| 2989 | for (loop = 0; loop < (1 << d_hash_shift); loop++) | 2989 | for (loop = 0; loop < (1U << d_hash_shift); loop++) |
| 2990 | INIT_HLIST_BL_HEAD(dentry_hashtable + loop); | 2990 | INIT_HLIST_BL_HEAD(dentry_hashtable + loop); |
| 2991 | } | 2991 | } |
| 2992 | 2992 | ||
| 2993 | static void __init dcache_init(void) | 2993 | static void __init dcache_init(void) |
| 2994 | { | 2994 | { |
| 2995 | int loop; | 2995 | unsigned int loop; |
| 2996 | 2996 | ||
| 2997 | /* | 2997 | /* |
| 2998 | * A constructor could be added for stable state like the lists, | 2998 | * A constructor could be added for stable state like the lists, |
| @@ -3016,7 +3016,7 @@ static void __init dcache_init(void) | |||
| 3016 | &d_hash_mask, | 3016 | &d_hash_mask, |
| 3017 | 0); | 3017 | 0); |
| 3018 | 3018 | ||
| 3019 | for (loop = 0; loop < (1 << d_hash_shift); loop++) | 3019 | for (loop = 0; loop < (1U << d_hash_shift); loop++) |
| 3020 | INIT_HLIST_BL_HEAD(dentry_hashtable + loop); | 3020 | INIT_HLIST_BL_HEAD(dentry_hashtable + loop); |
| 3021 | } | 3021 | } |
| 3022 | 3022 | ||
diff --git a/fs/inode.c b/fs/inode.c index fb10d86ffad7..d3ebdbe723d0 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
| @@ -1651,7 +1651,7 @@ __setup("ihash_entries=", set_ihash_entries); | |||
| 1651 | */ | 1651 | */ |
| 1652 | void __init inode_init_early(void) | 1652 | void __init inode_init_early(void) |
| 1653 | { | 1653 | { |
| 1654 | int loop; | 1654 | unsigned int loop; |
| 1655 | 1655 | ||
| 1656 | /* If hashes are distributed across NUMA nodes, defer | 1656 | /* If hashes are distributed across NUMA nodes, defer |
| 1657 | * hash allocation until vmalloc space is available. | 1657 | * hash allocation until vmalloc space is available. |
| @@ -1669,13 +1669,13 @@ void __init inode_init_early(void) | |||
| 1669 | &i_hash_mask, | 1669 | &i_hash_mask, |
| 1670 | 0); | 1670 | 0); |
| 1671 | 1671 | ||
| 1672 | for (loop = 0; loop < (1 << i_hash_shift); loop++) | 1672 | for (loop = 0; loop < (1U << i_hash_shift); loop++) |
| 1673 | INIT_HLIST_HEAD(&inode_hashtable[loop]); | 1673 | INIT_HLIST_HEAD(&inode_hashtable[loop]); |
| 1674 | } | 1674 | } |
| 1675 | 1675 | ||
| 1676 | void __init inode_init(void) | 1676 | void __init inode_init(void) |
| 1677 | { | 1677 | { |
| 1678 | int loop; | 1678 | unsigned int loop; |
| 1679 | 1679 | ||
| 1680 | /* inode slab cache */ | 1680 | /* inode slab cache */ |
| 1681 | inode_cachep = kmem_cache_create("inode_cache", | 1681 | inode_cachep = kmem_cache_create("inode_cache", |
| @@ -1699,7 +1699,7 @@ void __init inode_init(void) | |||
| 1699 | &i_hash_mask, | 1699 | &i_hash_mask, |
| 1700 | 0); | 1700 | 0); |
| 1701 | 1701 | ||
| 1702 | for (loop = 0; loop < (1 << i_hash_shift); loop++) | 1702 | for (loop = 0; loop < (1U << i_hash_shift); loop++) |
| 1703 | INIT_HLIST_HEAD(&inode_hashtable[loop]); | 1703 | INIT_HLIST_HEAD(&inode_hashtable[loop]); |
| 1704 | } | 1704 | } |
| 1705 | 1705 | ||
diff --git a/kernel/pid.c b/kernel/pid.c index ce8e00deaccb..9f08dfabaf13 100644 --- a/kernel/pid.c +++ b/kernel/pid.c | |||
| @@ -543,12 +543,12 @@ struct pid *find_ge_pid(int nr, struct pid_namespace *ns) | |||
| 543 | */ | 543 | */ |
| 544 | void __init pidhash_init(void) | 544 | void __init pidhash_init(void) |
| 545 | { | 545 | { |
| 546 | int i, pidhash_size; | 546 | unsigned int i, pidhash_size; |
| 547 | 547 | ||
| 548 | pid_hash = alloc_large_system_hash("PID", sizeof(*pid_hash), 0, 18, | 548 | pid_hash = alloc_large_system_hash("PID", sizeof(*pid_hash), 0, 18, |
| 549 | HASH_EARLY | HASH_SMALL, | 549 | HASH_EARLY | HASH_SMALL, |
| 550 | &pidhash_shift, NULL, 4096); | 550 | &pidhash_shift, NULL, 4096); |
| 551 | pidhash_size = 1 << pidhash_shift; | 551 | pidhash_size = 1U << pidhash_shift; |
| 552 | 552 | ||
| 553 | for (i = 0; i < pidhash_size; i++) | 553 | for (i = 0; i < pidhash_size; i++) |
| 554 | INIT_HLIST_HEAD(&pid_hash[i]); | 554 | INIT_HLIST_HEAD(&pid_hash[i]); |
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index d2186ecb36f7..a13ded1938f0 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
| @@ -5236,6 +5236,7 @@ void *__init alloc_large_system_hash(const char *tablename, | |||
| 5236 | max = ((unsigned long long)nr_all_pages << PAGE_SHIFT) >> 4; | 5236 | max = ((unsigned long long)nr_all_pages << PAGE_SHIFT) >> 4; |
| 5237 | do_div(max, bucketsize); | 5237 | do_div(max, bucketsize); |
| 5238 | } | 5238 | } |
| 5239 | max = min(max, 0x80000000ULL); | ||
| 5239 | 5240 | ||
| 5240 | if (numentries > max) | 5241 | if (numentries > max) |
| 5241 | numentries = max; | 5242 | numentries = max; |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 37755ccc0e96..22ef5f9fd2ff 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
| @@ -3240,7 +3240,8 @@ void __init tcp_init(void) | |||
| 3240 | { | 3240 | { |
| 3241 | struct sk_buff *skb = NULL; | 3241 | struct sk_buff *skb = NULL; |
| 3242 | unsigned long limit; | 3242 | unsigned long limit; |
| 3243 | int i, max_share, cnt; | 3243 | int max_share, cnt; |
| 3244 | unsigned int i; | ||
| 3244 | unsigned long jiffy = jiffies; | 3245 | unsigned long jiffy = jiffies; |
| 3245 | 3246 | ||
| 3246 | BUILD_BUG_ON(sizeof(struct tcp_skb_cb) > sizeof(skb->cb)); | 3247 | BUILD_BUG_ON(sizeof(struct tcp_skb_cb) > sizeof(skb->cb)); |
| @@ -3283,7 +3284,7 @@ void __init tcp_init(void) | |||
| 3283 | &tcp_hashinfo.bhash_size, | 3284 | &tcp_hashinfo.bhash_size, |
| 3284 | NULL, | 3285 | NULL, |
| 3285 | 64 * 1024); | 3286 | 64 * 1024); |
| 3286 | tcp_hashinfo.bhash_size = 1 << tcp_hashinfo.bhash_size; | 3287 | tcp_hashinfo.bhash_size = 1U << tcp_hashinfo.bhash_size; |
| 3287 | for (i = 0; i < tcp_hashinfo.bhash_size; i++) { | 3288 | for (i = 0; i < tcp_hashinfo.bhash_size; i++) { |
| 3288 | spin_lock_init(&tcp_hashinfo.bhash[i].lock); | 3289 | spin_lock_init(&tcp_hashinfo.bhash[i].lock); |
| 3289 | INIT_HLIST_HEAD(&tcp_hashinfo.bhash[i].chain); | 3290 | INIT_HLIST_HEAD(&tcp_hashinfo.bhash[i].chain); |
