Skip to content

Commit

Permalink
vfs: fix panic in __d_lookup() with high dentry hashtable counts
Browse files Browse the repository at this point in the history
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 <[email protected]>
Acked-by: David S. Miller <[email protected]>
Cc: Al Viro <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Al Viro <[email protected]>
  • Loading branch information
Dimitri Sivanich authored and Al Viro committed Feb 14, 2012
1 parent 1d6f209 commit 074b851
Show file tree
Hide file tree
Showing 5 changed files with 14 additions and 12 deletions.
8 changes: 4 additions & 4 deletions fs/dcache.c
Original file line number Diff line number Diff line change
Expand Up @@ -2968,7 +2968,7 @@ __setup("dhash_entries=", set_dhash_entries);

static void __init dcache_init_early(void)
{
int loop;
unsigned int loop;

/* If hashes are distributed across NUMA nodes, defer
* hash allocation until vmalloc space is available.
Expand All @@ -2986,13 +2986,13 @@ static void __init dcache_init_early(void)
&d_hash_mask,
0);

for (loop = 0; loop < (1 << d_hash_shift); loop++)
for (loop = 0; loop < (1U << d_hash_shift); loop++)
INIT_HLIST_BL_HEAD(dentry_hashtable + loop);
}

static void __init dcache_init(void)
{
int loop;
unsigned int loop;

/*
* A constructor could be added for stable state like the lists,
Expand All @@ -3016,7 +3016,7 @@ static void __init dcache_init(void)
&d_hash_mask,
0);

for (loop = 0; loop < (1 << d_hash_shift); loop++)
for (loop = 0; loop < (1U << d_hash_shift); loop++)
INIT_HLIST_BL_HEAD(dentry_hashtable + loop);
}

Expand Down
8 changes: 4 additions & 4 deletions fs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1651,7 +1651,7 @@ __setup("ihash_entries=", set_ihash_entries);
*/
void __init inode_init_early(void)
{
int loop;
unsigned int loop;

/* If hashes are distributed across NUMA nodes, defer
* hash allocation until vmalloc space is available.
Expand All @@ -1669,13 +1669,13 @@ void __init inode_init_early(void)
&i_hash_mask,
0);

for (loop = 0; loop < (1 << i_hash_shift); loop++)
for (loop = 0; loop < (1U << i_hash_shift); loop++)
INIT_HLIST_HEAD(&inode_hashtable[loop]);
}

void __init inode_init(void)
{
int loop;
unsigned int loop;

/* inode slab cache */
inode_cachep = kmem_cache_create("inode_cache",
Expand All @@ -1699,7 +1699,7 @@ void __init inode_init(void)
&i_hash_mask,
0);

for (loop = 0; loop < (1 << i_hash_shift); loop++)
for (loop = 0; loop < (1U << i_hash_shift); loop++)
INIT_HLIST_HEAD(&inode_hashtable[loop]);
}

Expand Down
4 changes: 2 additions & 2 deletions kernel/pid.c
Original file line number Diff line number Diff line change
Expand Up @@ -543,12 +543,12 @@ struct pid *find_ge_pid(int nr, struct pid_namespace *ns)
*/
void __init pidhash_init(void)
{
int i, pidhash_size;
unsigned int i, pidhash_size;

pid_hash = alloc_large_system_hash("PID", sizeof(*pid_hash), 0, 18,
HASH_EARLY | HASH_SMALL,
&pidhash_shift, NULL, 4096);
pidhash_size = 1 << pidhash_shift;
pidhash_size = 1U << pidhash_shift;

for (i = 0; i < pidhash_size; i++)
INIT_HLIST_HEAD(&pid_hash[i]);
Expand Down
1 change: 1 addition & 0 deletions mm/page_alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -5236,6 +5236,7 @@ void *__init alloc_large_system_hash(const char *tablename,
max = ((unsigned long long)nr_all_pages << PAGE_SHIFT) >> 4;
do_div(max, bucketsize);
}
max = min(max, 0x80000000ULL);

if (numentries > max)
numentries = max;
Expand Down
5 changes: 3 additions & 2 deletions net/ipv4/tcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -3240,7 +3240,8 @@ void __init tcp_init(void)
{
struct sk_buff *skb = NULL;
unsigned long limit;
int i, max_share, cnt;
int max_share, cnt;
unsigned int i;
unsigned long jiffy = jiffies;

BUILD_BUG_ON(sizeof(struct tcp_skb_cb) > sizeof(skb->cb));
Expand Down Expand Up @@ -3283,7 +3284,7 @@ void __init tcp_init(void)
&tcp_hashinfo.bhash_size,
NULL,
64 * 1024);
tcp_hashinfo.bhash_size = 1 << tcp_hashinfo.bhash_size;
tcp_hashinfo.bhash_size = 1U << tcp_hashinfo.bhash_size;
for (i = 0; i < tcp_hashinfo.bhash_size; i++) {
spin_lock_init(&tcp_hashinfo.bhash[i].lock);
INIT_HLIST_HEAD(&tcp_hashinfo.bhash[i].chain);
Expand Down

0 comments on commit 074b851

Please sign in to comment.