History

idr: introduce idr_for_each_entry_continue_ul()

Similarly, other callers of idr_get_next_ul() suffer the same overflow bug as they don't handle it properly either. Introduce idr_for_each_entry_continue_ul() to help these callers iterate from a given ID. cls_flower needs more care here because it still has overflow when does arg->cookie++, we have to fold its nested loops into one and remove the arg->cookie++.

Cong Wang committed 7 years ago

Commit d39d7141 parent e33d2b73 files · +27 −24Browse files

Unified · Split

3 files
  1. drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c +6 −4
  2. include/linux/idr.h +14 −0
  3. net/sched/cls_flower.c +7 −20
drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c+6−4
@@ -102,13 +102,15 @@ static struct list_head *mlx5_fc_counters_lookup_next(struct mlx5_core_dev *dev, · 101 unmodified lines
102102 struct mlx5_fc_stats *fc_stats = &dev->priv.fc_stats;
103103 unsigned long next_id = (unsigned long)id + 1;
104104 struct mlx5_fc *counter;
105+ unsigned long tmp;
105106
106107 rcu_read_lock();
107108 /* skip counters that are in idr, but not yet in counters list */
108− while ((counter = idr_get_next_ul(&fc_stats->counters_idr,
109− &next_id)) != NULL &&
110− list_empty(&counter->list))
111− next_id++;
109+ idr_for_each_entry_continue_ul(&fc_stats->counters_idr,
110+ counter, tmp, next_id) {
111+ if (!list_empty(&counter->list))
112+ break;
113+ }
112114 rcu_read_unlock();
113115
114116 return counter ? &counter->list : &fc_stats->counters;
include/linux/idr.h+14−0
@@ -216,6 +216,20 @@ static inline void idr_preload_end(void) · 215 unmodified lines
216216 entry; \
217217 ++id, (entry) = idr_get_next((idr), &(id)))
218218
219+/**
220+ * idr_for_each_entry_continue_ul() - Continue iteration over an IDR's elements of a given type
221+ * @idr: IDR handle.
222+ * @entry: The type * to use as a cursor.
223+ * @tmp: A temporary placeholder for ID.
224+ * @id: Entry ID.
225+ *
226+ * Continue to iterate over entries, continuing after the current position.
227+ */
228+#define idr_for_each_entry_continue_ul(idr, entry, tmp, id) \
229+ for (tmp = id; \
230+ tmp <= id && ((entry) = idr_get_next_ul(idr, &(id))) != NULL; \
231+ tmp = id, ++id)
232+
219233 /*
220234 * IDA - ID Allocator, use when translation from id to pointer isn't necessary.
221235 */
net/sched/cls_flower.c+7−20
@@ -524,24 +524,6 @@ static struct cls_fl_filter *__fl_get(struct cls_fl_head *head, u32 handle) · 523 unmodified lines
524524 return f;
525525 }
526526
527−static struct cls_fl_filter *fl_get_next_filter(struct tcf_proto *tp,
528− unsigned long *handle)
529−{
530− struct cls_fl_head *head = fl_head_dereference(tp);
531− struct cls_fl_filter *f;
532−
533− rcu_read_lock();
534− while ((f = idr_get_next_ul(&head->handle_idr, handle))) {
535− /* don't return filters that are being deleted */
536− if (refcount_inc_not_zero(&f->refcnt))
537− break;
538− ++(*handle);
539− }
540− rcu_read_unlock();
541−
542− return f;
543−}
544−
545527 static int __fl_delete(struct tcf_proto *tp, struct cls_fl_filter *f,
546528 bool *last, bool rtnl_held,
547529 struct netlink_ext_ack *extack)
@@ -1691,20 +1673,25 @@ static int fl_delete(struct tcf_proto *tp, void *arg, bool *last, · 1143 unmodified lines
16911673 static void fl_walk(struct tcf_proto *tp, struct tcf_walker *arg,
16921674 bool rtnl_held)
16931675 {
1676+ struct cls_fl_head *head = fl_head_dereference(tp);
1677+ unsigned long id = arg->cookie, tmp;
16941678 struct cls_fl_filter *f;
16951679
16961680 arg->count = arg->skip;
16971681
1698− while ((f = fl_get_next_filter(tp, &arg->cookie)) != NULL) {
1682+ idr_for_each_entry_continue_ul(&head->handle_idr, f, tmp, id) {
1683+ /* don't return filters that are being deleted */
1684+ if (!refcount_inc_not_zero(&f->refcnt))
1685+ continue;
16991686 if (arg->fn(tp, f, arg) < 0) {
17001687 __fl_put(f);
17011688 arg->stop = 1;
17021689 break;
17031690 }
17041691 __fl_put(f);
1705− arg->cookie++;
17061692 arg->count++;
17071693 }
1694+ arg->cookie = id;
17081695 }
17091696
17101697 static struct cls_fl_filter *

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t