aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
authorEric Dumazet <eric.dumazet@gmail.com>2011-12-24 01:56:49 -0500
committerDavid S. Miller <davem@davemloft.net>2011-12-24 16:13:27 -0500
commit60b778ce519625102d3f72a2071ea72a05e990ce (patch)
treeecae42cc8809809287e10007643370eaed7e3055 /net/core
parent035c4c16bea2814890c64c657d177e91cec1f473 (diff)
rfs: better sizing of dev_flow_table
Aim of this patch is to provide full range of rps_flow_cnt on 64bit arches. Theorical limit on number of flows is 2^32 Fix some buggy RPS/RFS macros as well. Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> CC: Tom Herbert <therbert@google.com> CC: Xi Wang <xi.wang@gmail.com> CC: Laurent Chavey <chavey@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r--net/core/net-sysfs.c44
1 files changed, 27 insertions, 17 deletions
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
636static void rps_dev_flow_table_release_work(struct work_struct *work) 636static 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