diff options
| -rw-r--r-- | include/linux/netdevice.h | 8 | ||||
| -rw-r--r-- | net/core/net-sysfs.c | 44 |
2 files changed, 31 insertions, 21 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 603730804da5..a776a675c0e5 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h | |||
| @@ -597,7 +597,7 @@ struct rps_map { | |||
| 597 | struct rcu_head rcu; | 597 | struct rcu_head rcu; |
| 598 | u16 cpus[0]; | 598 | u16 cpus[0]; |
| 599 | }; | 599 | }; |
| 600 | #define RPS_MAP_SIZE(_num) (sizeof(struct rps_map) + (_num * sizeof(u16))) | 600 | #define RPS_MAP_SIZE(_num) (sizeof(struct rps_map) + ((_num) * sizeof(u16))) |
| 601 | 601 | ||
| 602 | /* | 602 | /* |
| 603 | * The rps_dev_flow structure contains the mapping of a flow to a CPU, the | 603 | * The rps_dev_flow structure contains the mapping of a flow to a CPU, the |
| @@ -621,7 +621,7 @@ struct rps_dev_flow_table { | |||
| 621 | struct rps_dev_flow flows[0]; | 621 | struct rps_dev_flow flows[0]; |
| 622 | }; | 622 | }; |
| 623 | #define RPS_DEV_FLOW_TABLE_SIZE(_num) (sizeof(struct rps_dev_flow_table) + \ | 623 | #define RPS_DEV_FLOW_TABLE_SIZE(_num) (sizeof(struct rps_dev_flow_table) + \ |
| 624 | (_num * sizeof(struct rps_dev_flow))) | 624 | ((_num) * sizeof(struct rps_dev_flow))) |
| 625 | 625 | ||
| 626 | /* | 626 | /* |
| 627 | * The rps_sock_flow_table contains mappings of flows to the last CPU | 627 | * The rps_sock_flow_table contains mappings of flows to the last CPU |
| @@ -632,7 +632,7 @@ struct rps_sock_flow_table { | |||
| 632 | u16 ents[0]; | 632 | u16 ents[0]; |
| 633 | }; | 633 | }; |
| 634 | #define RPS_SOCK_FLOW_TABLE_SIZE(_num) (sizeof(struct rps_sock_flow_table) + \ | 634 | #define RPS_SOCK_FLOW_TABLE_SIZE(_num) (sizeof(struct rps_sock_flow_table) + \ |
| 635 | (_num * sizeof(u16))) | 635 | ((_num) * sizeof(u16))) |
| 636 | 636 | ||
| 637 | #define RPS_NO_CPU 0xffff | 637 | #define RPS_NO_CPU 0xffff |
| 638 | 638 | ||
| @@ -684,7 +684,7 @@ struct xps_map { | |||
| 684 | struct rcu_head rcu; | 684 | struct rcu_head rcu; |
| 685 | u16 queues[0]; | 685 | u16 queues[0]; |
| 686 | }; | 686 | }; |
| 687 | #define XPS_MAP_SIZE(_num) (sizeof(struct xps_map) + (_num * sizeof(u16))) | 687 | #define XPS_MAP_SIZE(_num) (sizeof(struct xps_map) + ((_num) * sizeof(u16))) |
| 688 | #define XPS_MIN_MAP_ALLOC ((L1_CACHE_BYTES - sizeof(struct xps_map)) \ | 688 | #define XPS_MIN_MAP_ALLOC ((L1_CACHE_BYTES - sizeof(struct xps_map)) \ |
| 689 | / sizeof(u16)) | 689 | / sizeof(u16)) |
| 690 | 690 | ||
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 4b4d0b0a3543..abf4393a77b3 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c | |||
| @@ -622,15 +622,15 @@ static ssize_t show_rps_dev_flow_table_cnt(struct netdev_rx_queue *queue, | |||
| 622 | char *buf) | 622 | char *buf) |
| 623 | { | 623 | { |
| 624 | struct rps_dev_flow_table *flow_table; | 624 | struct rps_dev_flow_table *flow_table; |
| 625 | unsigned int val = 0; | 625 | unsigned long val = 0; |
| 626 | 626 | ||
| 627 | rcu_read_lock(); | 627 | rcu_read_lock(); |
| 628 | flow_table = rcu_dereference(queue->rps_flow_table); | 628 | flow_table = rcu_dereference(queue->rps_flow_table); |
| 629 | if (flow_table) | 629 | if (flow_table) |
| 630 | val = flow_table->mask + 1; | 630 | val = (unsigned long)flow_table->mask + 1; |
| 631 | rcu_read_unlock(); | 631 | rcu_read_unlock(); |
| 632 | 632 | ||
| 633 | return sprintf(buf, "%u\n", val); | 633 | return sprintf(buf, "%lu\n", val); |
| 634 | } | 634 | } |
| 635 | 635 | ||
| 636 | static void rps_dev_flow_table_release_work(struct work_struct *work) | 636 | static void rps_dev_flow_table_release_work(struct work_struct *work) |
| @@ -654,36 +654,46 @@ static ssize_t store_rps_dev_flow_table_cnt(struct netdev_rx_queue *queue, | |||
| 654 | struct rx_queue_attribute *attr, | 654 | struct rx_queue_attribute *attr, |
| 655 | const char *buf, size_t len) | 655 | const char *buf, size_t len) |
| 656 | { | 656 | { |
| 657 | unsigned int count; | 657 | unsigned long mask, count; |
| 658 | char *endp; | ||
| 659 | struct rps_dev_flow_table *table, *old_table; | 658 | struct rps_dev_flow_table *table, *old_table; |
| 660 | static DEFINE_SPINLOCK(rps_dev_flow_lock); | 659 | static DEFINE_SPINLOCK(rps_dev_flow_lock); |
| 660 | int rc; | ||
| 661 | 661 | ||
| 662 | if (!capable(CAP_NET_ADMIN)) | 662 | if (!capable(CAP_NET_ADMIN)) |
| 663 | return -EPERM; | 663 | return -EPERM; |
| 664 | 664 | ||
| 665 | count = simple_strtoul(buf, &endp, 0); | 665 | rc = kstrtoul(buf, 0, &count); |
| 666 | if (endp == buf) | 666 | if (rc < 0) |
| 667 | return -EINVAL; | 667 | return rc; |
| 668 | 668 | ||
| 669 | if (count) { | 669 | if (count) { |
| 670 | int i; | 670 | mask = count - 1; |
| 671 | 671 | /* mask = roundup_pow_of_two(count) - 1; | |
| 672 | if (count > INT_MAX) | 672 | * without overflows... |
| 673 | */ | ||
| 674 | while ((mask | (mask >> 1)) != mask) | ||
| 675 | mask |= (mask >> 1); | ||
| 676 | /* On 64 bit arches, must check mask fits in table->mask (u32), | ||
| 677 | * and on 32bit arches, must check RPS_DEV_FLOW_TABLE_SIZE(mask + 1) | ||
| 678 | * doesnt overflow. | ||
| 679 | */ | ||
| 680 | #if BITS_PER_LONG > 32 | ||
| 681 | if (mask > (unsigned long)(u32)mask) | ||
| 673 | return -EINVAL; | 682 | return -EINVAL; |
| 674 | count = roundup_pow_of_two(count); | 683 | #else |
| 675 | if (count > (ULONG_MAX - sizeof(struct rps_dev_flow_table)) | 684 | if (mask > (ULONG_MAX - RPS_DEV_FLOW_TABLE_SIZE(1)) |
| 676 | / sizeof(struct rps_dev_flow)) { | 685 | / sizeof(struct rps_dev_flow)) { |
| 677 | /* Enforce a limit to prevent overflow */ | 686 | /* Enforce a limit to prevent overflow */ |
| 678 | return -EINVAL; | 687 | return -EINVAL; |
| 679 | } | 688 | } |
| 680 | table = vmalloc(RPS_DEV_FLOW_TABLE_SIZE(count)); | 689 | #endif |
| 690 | table = vmalloc(RPS_DEV_FLOW_TABLE_SIZE(mask + 1)); | ||
| 681 | if (!table) | 691 | if (!table) |
| 682 | return -ENOMEM; | 692 | return -ENOMEM; |
| 683 | 693 | ||
| 684 | table->mask = count - 1; | 694 | table->mask = mask; |
| 685 | for (i = 0; i < count; i++) | 695 | for (count = 0; count <= mask; count++) |
| 686 | table->flows[i].cpu = RPS_NO_CPU; | 696 | table->flows[count].cpu = RPS_NO_CPU; |
| 687 | } else | 697 | } else |
| 688 | table = NULL; | 698 | table = NULL; |
| 689 | 699 | ||
