order-5 allocations can fail with current kernels, we should try vmalloc() as well.
Unified · Split
| @@ -1,7 +1,6 @@ | ||
| 1 | 1 | #include <linux/rcupdate.h> |
| 2 | 2 | #include <linux/spinlock.h> |
| 3 | 3 | #include <linux/jiffies.h> |
| 4 | −#include <linux/bootmem.h> | |
| 5 | 4 | #include <linux/module.h> |
| 6 | 5 | #include <linux/cache.h> |
| 7 | 6 | #include <linux/slab.h> |
| @@ -9,6 +8,7 @@ · 1 unmodified line | ||
| 9 | 8 | #include <linux/tcp.h> |
| 10 | 9 | #include <linux/hash.h> |
| 11 | 10 | #include <linux/tcp_metrics.h> |
| 11 | +#include <linux/vmalloc.h> | |
| 12 | 12 | |
| 13 | 13 | #include <net/inet_connection_sock.h> |
| 14 | 14 | #include <net/net_namespace.h> |
| @@ -1034,7 +1034,10 @@ static int __net_init tcp_net_metrics_init(struct net *net) · 1019 unmodified lines | ||
| 1034 | 1034 | net->ipv4.tcp_metrics_hash_log = order_base_2(slots); |
| 1035 | 1035 | size = sizeof(struct tcpm_hash_bucket) << net->ipv4.tcp_metrics_hash_log; |
| 1036 | 1036 | |
| 1037 | − net->ipv4.tcp_metrics_hash = kzalloc(size, GFP_KERNEL); | |
| 1037 | + net->ipv4.tcp_metrics_hash = kzalloc(size, GFP_KERNEL | __GFP_NOWARN); | |
| 1038 | + if (!net->ipv4.tcp_metrics_hash) | |
| 1039 | + net->ipv4.tcp_metrics_hash = vzalloc(size); | |
| 1040 | + | |
| 1038 | 1041 | if (!net->ipv4.tcp_metrics_hash) |
| 1039 | 1042 | return -ENOMEM; |
| 1040 | 1043 | |
| @@ -1055,7 +1058,10 @@ static void __net_exit tcp_net_metrics_exit(struct net *net) · 14 unmodified lines | ||
| 1055 | 1058 | tm = next; |
| 1056 | 1059 | } |
| 1057 | 1060 | } |
| 1058 | − kfree(net->ipv4.tcp_metrics_hash); | |
| 1061 | + if (is_vmalloc_addr(net->ipv4.tcp_metrics_hash)) | |
| 1062 | + vfree(net->ipv4.tcp_metrics_hash); | |
| 1063 | + else | |
| 1064 | + kfree(net->ipv4.tcp_metrics_hash); | |
| 1059 | 1065 | } |
| 1060 | 1066 | |
| 1061 | 1067 | static __net_initdata struct pernet_operations tcp_net_metrics_ops = { |