struct btrfs_stripe_hash *h;
int num_entries = 1 << BTRFS_STRIPE_HASH_TABLE_BITS;
int i;
+ int table_size;
if (info->stripe_hash_table)
return 0;
- table = kzalloc(sizeof(*table) + sizeof(*h) * num_entries, GFP_NOFS);
- if (!table)
- return -ENOMEM;
+ /*
+ * The table is large, starting with order 4 and can go as high as
+ * order 7 in case lock debugging is turned on.
+ *
+ * Try harder to allocate and fallback to vmalloc to lower the chance
+ * of a failing mount.
+ */
+ table_size = sizeof(*table) + sizeof(*h) * num_entries;
+ table = kzalloc(table_size, GFP_KERNEL | __GFP_NOWARN | __GFP_REPEAT);
+ if (!table) {
+ table = vzalloc(table_size);
+ if (!table)
+ return -ENOMEM;
+ }
spin_lock_init(&table->cache_lock);
INIT_LIST_HEAD(&table->stripe_cache);
}
x = cmpxchg(&info->stripe_hash_table, NULL, table);
- if (x)
- kfree(x);
+ if (x) {
+ if (is_vmalloc_addr(x))
+ vfree(x);
+ else
+ kfree(x);
+ }
return 0;
}
if (!info->stripe_hash_table)
return;
btrfs_clear_rbio_cache(info);
- kfree(info->stripe_hash_table);
+ if (is_vmalloc_addr(info->stripe_hash_table))
+ vfree(info->stripe_hash_table);
+ else
+ kfree(info->stripe_hash_table);
info->stripe_hash_table = NULL;
}