* [PATCH v3 06/17] tracepoint: use new hashtable implementation
From: Sasha Levin @ 2012-08-22 2:27 UTC (permalink / raw)
To: torvalds
Cc: tj, akpm, linux-kernel, linux-mm, paul.gortmaker, davem, rostedt,
mingo, ebiederm, aarcange, ericvh, netdev, josh, eric.dumazet,
mathieu.desnoyers, axboe, agk, dm-devel, neilb, ccaulfie,
teigland, Trond.Myklebust, bfields, fweisbec, jesse,
venkat.x.venkatsubra, ejt, snitzer, edumazet, linux-nfs, dev,
rds-devel, lw, Sasha Levin
In-Reply-To: <1345602432-27673-1-git-send-email-levinsasha928@gmail.com>
Switch tracepoints to use the new hashtable implementation. This reduces the amount of
generic unrelated code in the tracepoints.
Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
---
kernel/tracepoint.c | 27 +++++++++++----------------
1 files changed, 11 insertions(+), 16 deletions(-)
diff --git a/kernel/tracepoint.c b/kernel/tracepoint.c
index d96ba22..854df92 100644
--- a/kernel/tracepoint.c
+++ b/kernel/tracepoint.c
@@ -26,6 +26,7 @@
#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/static_key.h>
+#include <linux/hashtable.h>
extern struct tracepoint * const __start___tracepoints_ptrs[];
extern struct tracepoint * const __stop___tracepoints_ptrs[];
@@ -49,8 +50,7 @@ static LIST_HEAD(tracepoint_module_list);
* Protected by tracepoints_mutex.
*/
#define TRACEPOINT_HASH_BITS 6
-#define TRACEPOINT_TABLE_SIZE (1 << TRACEPOINT_HASH_BITS)
-static struct hlist_head tracepoint_table[TRACEPOINT_TABLE_SIZE];
+static DEFINE_HASHTABLE(tracepoint_table, TRACEPOINT_HASH_BITS);
/*
* Note about RCU :
@@ -191,16 +191,15 @@ tracepoint_entry_remove_probe(struct tracepoint_entry *entry,
*/
static struct tracepoint_entry *get_tracepoint(const char *name)
{
- struct hlist_head *head;
struct hlist_node *node;
struct tracepoint_entry *e;
u32 hash = jhash(name, strlen(name), 0);
- head = &tracepoint_table[hash & (TRACEPOINT_TABLE_SIZE - 1)];
- hlist_for_each_entry(e, node, head, hlist) {
+ hash_for_each_possible(tracepoint_table, e, node, hlist, hash) {
if (!strcmp(name, e->name))
return e;
}
+
return NULL;
}
@@ -210,19 +209,13 @@ static struct tracepoint_entry *get_tracepoint(const char *name)
*/
static struct tracepoint_entry *add_tracepoint(const char *name)
{
- struct hlist_head *head;
- struct hlist_node *node;
struct tracepoint_entry *e;
size_t name_len = strlen(name) + 1;
u32 hash = jhash(name, name_len-1, 0);
- head = &tracepoint_table[hash & (TRACEPOINT_TABLE_SIZE - 1)];
- hlist_for_each_entry(e, node, head, hlist) {
- if (!strcmp(name, e->name)) {
- printk(KERN_NOTICE
- "tracepoint %s busy\n", name);
- return ERR_PTR(-EEXIST); /* Already there */
- }
+ if (get_tracepoint(name)) {
+ printk(KERN_NOTICE "tracepoint %s busy\n", name);
+ return ERR_PTR(-EEXIST); /* Already there */
}
/*
* Using kmalloc here to allocate a variable length element. Could
@@ -234,7 +227,7 @@ static struct tracepoint_entry *add_tracepoint(const char *name)
memcpy(&e->name[0], name, name_len);
e->funcs = NULL;
e->refcount = 0;
- hlist_add_head(&e->hlist, head);
+ hash_add(tracepoint_table, &e->hlist, hash);
return e;
}
@@ -244,7 +237,7 @@ static struct tracepoint_entry *add_tracepoint(const char *name)
*/
static inline void remove_tracepoint(struct tracepoint_entry *e)
{
- hlist_del(&e->hlist);
+ hash_del(&e->hlist);
kfree(e);
}
@@ -722,6 +715,8 @@ struct notifier_block tracepoint_module_nb = {
static int init_tracepoints(void)
{
+ hash_init(tracepoint_table);
+
return register_module_notifier(&tracepoint_module_nb);
}
__initcall(init_tracepoints);
--
1.7.8.6
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply related
* [PATCH v3 05/17] mm/huge_memory: use new hashtable implementation
From: Sasha Levin @ 2012-08-22 2:27 UTC (permalink / raw)
To: torvalds-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b
Cc: snitzer-H+wXaHxf7aLQT0dZR+AlfA, neilb-l3A5Bk7waGM,
fweisbec-Re5JQEeQqe8AvxtiuMwx3w,
Trond.Myklebust-HgOvQuBEEgTQT0dZR+AlfA,
bfields-uC3wQj2KruNg9hUCZPvPmw,
paul.gortmaker-CWA4WttNNZF54TAoqtyWWQ,
dm-devel-H+wXaHxf7aLQT0dZR+AlfA, agk-H+wXaHxf7aLQT0dZR+AlfA,
aarcange-H+wXaHxf7aLQT0dZR+AlfA, rds-devel-N0ozoZBvEnrZJqsBc5GL+g,
eric.dumazet-Re5JQEeQqe8AvxtiuMwx3w,
venkat.x.venkatsubra-QHcLZuEGTsvQT0dZR+AlfA,
ccaulfie-H+wXaHxf7aLQT0dZR+AlfA, mingo-X9Un+BFzKDI,
dev-yBygre7rU0TnMu66kgdUjQ, ericvh-Re5JQEeQqe8AvxtiuMwx3w,
josh-iaAMLnmF4UmaiuxdJuQwMA, rostedt-nx8X9YLhiw1AfugRpC6u6w,
lw-BthXqXjhjHXQFUHtdCDX3A,
mathieu.desnoyers-vg+e7yoeK/dWk0Htik3J/w, Sasha Levin,
axboe-tSWWG44O7X1aa/9Udqfwiw, linux-nfs-u79uwXL29TY76Z2rM5mHXA,
edumazet-hpIqsD4AKlfQT0dZR+AlfA, linux-mm-Bw31MaZKKs3YtjvyW6yDsg,
netdev-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, ejt-H+wXaHxf7aLQT0dZR+AlfA,
ebiederm-aS9lmoZGLiVWk0Htik3J/w, tj-DgEjT+Ai2ygdnm+yROfE0A,
teigland-H+wXaHxf7aLQT0dZR+AlfA,
akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
davem-fT/PcQaiUtIeIZ0/mPfg9Q
In-Reply-To: <1345602432-27673-1-git-send-email-levinsasha928-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Switch hugemem to use the new hashtable implementation. This reduces the amount of
generic unrelated code in the hugemem.
This also removes the dymanic allocation of the hash table. The size of the table is
constant so there's no point in paying the price of an extra dereference when accessing
it.
Signed-off-by: Sasha Levin <levinsasha928-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
mm/huge_memory.c | 57 ++++++++++++++---------------------------------------
1 files changed, 15 insertions(+), 42 deletions(-)
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 8b3c55a..cebe345 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -17,6 +17,7 @@
#include <linux/khugepaged.h>
#include <linux/freezer.h>
#include <linux/mman.h>
+#include <linux/hashtable.h>
#include <asm/tlb.h>
#include <asm/pgalloc.h>
#include "internal.h"
@@ -57,12 +58,12 @@ static DECLARE_WAIT_QUEUE_HEAD(khugepaged_wait);
static unsigned int khugepaged_max_ptes_none __read_mostly = HPAGE_PMD_NR-1;
static int khugepaged(void *none);
-static int mm_slots_hash_init(void);
static int khugepaged_slab_init(void);
static void khugepaged_slab_free(void);
-#define MM_SLOTS_HASH_HEADS 1024
-static struct hlist_head *mm_slots_hash __read_mostly;
+#define MM_SLOTS_HASH_BITS 10
+static DEFINE_HASHTABLE(mm_slots_hash, MM_SLOTS_HASH_BITS);
+
static struct kmem_cache *mm_slot_cache __read_mostly;
/**
@@ -140,7 +141,7 @@ static int start_khugepaged(void)
int err = 0;
if (khugepaged_enabled()) {
int wakeup;
- if (unlikely(!mm_slot_cache || !mm_slots_hash)) {
+ if (unlikely(!mm_slot_cache)) {
err = -ENOMEM;
goto out;
}
@@ -554,12 +555,6 @@ static int __init hugepage_init(void)
if (err)
goto out;
- err = mm_slots_hash_init();
- if (err) {
- khugepaged_slab_free();
- goto out;
- }
-
/*
* By default disable transparent hugepages on smaller systems,
* where the extra memory used could hurt more than TLB overhead
@@ -1540,6 +1535,8 @@ static int __init khugepaged_slab_init(void)
if (!mm_slot_cache)
return -ENOMEM;
+ hash_init(mm_slots_hash);
+
return 0;
}
@@ -1561,47 +1558,23 @@ static inline void free_mm_slot(struct mm_slot *mm_slot)
kmem_cache_free(mm_slot_cache, mm_slot);
}
-static int __init mm_slots_hash_init(void)
-{
- mm_slots_hash = kzalloc(MM_SLOTS_HASH_HEADS * sizeof(struct hlist_head),
- GFP_KERNEL);
- if (!mm_slots_hash)
- return -ENOMEM;
- return 0;
-}
-
-#if 0
-static void __init mm_slots_hash_free(void)
-{
- kfree(mm_slots_hash);
- mm_slots_hash = NULL;
-}
-#endif
-
static struct mm_slot *get_mm_slot(struct mm_struct *mm)
{
- struct mm_slot *mm_slot;
- struct hlist_head *bucket;
+ struct mm_slot *slot;
struct hlist_node *node;
- bucket = &mm_slots_hash[((unsigned long)mm / sizeof(struct mm_struct))
- % MM_SLOTS_HASH_HEADS];
- hlist_for_each_entry(mm_slot, node, bucket, hash) {
- if (mm == mm_slot->mm)
- return mm_slot;
- }
+ hash_for_each_possible(mm_slots_hash, slot, node, hash, (unsigned long) mm)
+ if (slot->mm == mm)
+ return slot;
+
return NULL;
}
static void insert_to_mm_slots_hash(struct mm_struct *mm,
struct mm_slot *mm_slot)
{
- struct hlist_head *bucket;
-
- bucket = &mm_slots_hash[((unsigned long)mm / sizeof(struct mm_struct))
- % MM_SLOTS_HASH_HEADS];
mm_slot->mm = mm;
- hlist_add_head(&mm_slot->hash, bucket);
+ hash_add(mm_slots_hash, &mm_slot->hash, (long)mm);
}
static inline int khugepaged_test_exit(struct mm_struct *mm)
@@ -1670,7 +1643,7 @@ void __khugepaged_exit(struct mm_struct *mm)
spin_lock(&khugepaged_mm_lock);
mm_slot = get_mm_slot(mm);
if (mm_slot && khugepaged_scan.mm_slot != mm_slot) {
- hlist_del(&mm_slot->hash);
+ hash_del(&mm_slot->hash);
list_del(&mm_slot->mm_node);
free = 1;
}
@@ -2080,7 +2053,7 @@ static void collect_mm_slot(struct mm_slot *mm_slot)
if (khugepaged_test_exit(mm)) {
/* free mm_slot */
- hlist_del(&mm_slot->hash);
+ hash_del(&mm_slot->hash);
list_del(&mm_slot->mm_node);
/*
--
1.7.8.6
^ permalink raw reply related
* [PATCH v3 04/17] workqueue: use new hashtable implementation
From: Sasha Levin @ 2012-08-22 2:26 UTC (permalink / raw)
To: torvalds-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b
Cc: snitzer-H+wXaHxf7aLQT0dZR+AlfA, neilb-l3A5Bk7waGM,
fweisbec-Re5JQEeQqe8AvxtiuMwx3w,
Trond.Myklebust-HgOvQuBEEgTQT0dZR+AlfA,
bfields-uC3wQj2KruNg9hUCZPvPmw,
paul.gortmaker-CWA4WttNNZF54TAoqtyWWQ,
dm-devel-H+wXaHxf7aLQT0dZR+AlfA, agk-H+wXaHxf7aLQT0dZR+AlfA,
aarcange-H+wXaHxf7aLQT0dZR+AlfA, rds-devel-N0ozoZBvEnrZJqsBc5GL+g,
eric.dumazet-Re5JQEeQqe8AvxtiuMwx3w,
venkat.x.venkatsubra-QHcLZuEGTsvQT0dZR+AlfA,
ccaulfie-H+wXaHxf7aLQT0dZR+AlfA, mingo-X9Un+BFzKDI,
dev-yBygre7rU0TnMu66kgdUjQ, ericvh-Re5JQEeQqe8AvxtiuMwx3w,
josh-iaAMLnmF4UmaiuxdJuQwMA, rostedt-nx8X9YLhiw1AfugRpC6u6w,
lw-BthXqXjhjHXQFUHtdCDX3A,
mathieu.desnoyers-vg+e7yoeK/dWk0Htik3J/w, Sasha Levin,
axboe-tSWWG44O7X1aa/9Udqfwiw, linux-nfs-u79uwXL29TY76Z2rM5mHXA,
edumazet-hpIqsD4AKlfQT0dZR+AlfA, linux-mm-Bw31MaZKKs3YtjvyW6yDsg,
netdev-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, ejt-H+wXaHxf7aLQT0dZR+AlfA,
ebiederm-aS9lmoZGLiVWk0Htik3J/w, tj-DgEjT+Ai2ygdnm+yROfE0A,
teigland-H+wXaHxf7aLQT0dZR+AlfA,
akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
davem-fT/PcQaiUtIeIZ0/mPfg9Q
In-Reply-To: <1345602432-27673-1-git-send-email-levinsasha928-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Switch workqueues to use the new hashtable implementation. This reduces the amount of
generic unrelated code in the workqueues.
Signed-off-by: Sasha Levin <levinsasha928-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
kernel/workqueue.c | 86 +++++++++-------------------------------------------
1 files changed, 15 insertions(+), 71 deletions(-)
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 11723c5..fca751e 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -41,6 +41,7 @@
#include <linux/debug_locks.h>
#include <linux/lockdep.h>
#include <linux/idr.h>
+#include <linux/hashtable.h>
#include "workqueue_sched.h"
@@ -82,8 +83,6 @@ enum {
NR_WORKER_POOLS = 2, /* # worker pools per gcwq */
BUSY_WORKER_HASH_ORDER = 6, /* 64 pointers */
- BUSY_WORKER_HASH_SIZE = 1 << BUSY_WORKER_HASH_ORDER,
- BUSY_WORKER_HASH_MASK = BUSY_WORKER_HASH_SIZE - 1,
MAX_IDLE_WORKERS_RATIO = 4, /* 1/4 of busy can be idle */
IDLE_WORKER_TIMEOUT = 300 * HZ, /* keep idle ones for 5 mins */
@@ -180,7 +179,7 @@ struct global_cwq {
unsigned int flags; /* L: GCWQ_* flags */
/* workers are chained either in busy_hash or pool idle_list */
- struct hlist_head busy_hash[BUSY_WORKER_HASH_SIZE];
+ DEFINE_HASHTABLE(busy_hash, BUSY_WORKER_HASH_ORDER);
/* L: hash of busy workers */
struct worker_pool pools[2]; /* normal and highpri pools */
@@ -288,8 +287,7 @@ EXPORT_SYMBOL_GPL(system_nrt_freezable_wq);
(pool) < &(gcwq)->pools[NR_WORKER_POOLS]; (pool)++)
#define for_each_busy_worker(worker, i, pos, gcwq) \
- for (i = 0; i < BUSY_WORKER_HASH_SIZE; i++) \
- hlist_for_each_entry(worker, pos, &gcwq->busy_hash[i], hentry)
+ hash_for_each(gcwq->busy_hash, i, pos, worker, hentry)
static inline int __next_gcwq_cpu(int cpu, const struct cpumask *mask,
unsigned int sw)
@@ -845,63 +843,6 @@ static inline void worker_clr_flags(struct worker *worker, unsigned int flags)
}
/**
- * busy_worker_head - return the busy hash head for a work
- * @gcwq: gcwq of interest
- * @work: work to be hashed
- *
- * Return hash head of @gcwq for @work.
- *
- * CONTEXT:
- * spin_lock_irq(gcwq->lock).
- *
- * RETURNS:
- * Pointer to the hash head.
- */
-static struct hlist_head *busy_worker_head(struct global_cwq *gcwq,
- struct work_struct *work)
-{
- const int base_shift = ilog2(sizeof(struct work_struct));
- unsigned long v = (unsigned long)work;
-
- /* simple shift and fold hash, do we need something better? */
- v >>= base_shift;
- v += v >> BUSY_WORKER_HASH_ORDER;
- v &= BUSY_WORKER_HASH_MASK;
-
- return &gcwq->busy_hash[v];
-}
-
-/**
- * __find_worker_executing_work - find worker which is executing a work
- * @gcwq: gcwq of interest
- * @bwh: hash head as returned by busy_worker_head()
- * @work: work to find worker for
- *
- * Find a worker which is executing @work on @gcwq. @bwh should be
- * the hash head obtained by calling busy_worker_head() with the same
- * work.
- *
- * CONTEXT:
- * spin_lock_irq(gcwq->lock).
- *
- * RETURNS:
- * Pointer to worker which is executing @work if found, NULL
- * otherwise.
- */
-static struct worker *__find_worker_executing_work(struct global_cwq *gcwq,
- struct hlist_head *bwh,
- struct work_struct *work)
-{
- struct worker *worker;
- struct hlist_node *tmp;
-
- hlist_for_each_entry(worker, tmp, bwh, hentry)
- if (worker->current_work == work)
- return worker;
- return NULL;
-}
-
-/**
* find_worker_executing_work - find worker which is executing a work
* @gcwq: gcwq of interest
* @work: work to find worker for
@@ -920,8 +861,14 @@ static struct worker *__find_worker_executing_work(struct global_cwq *gcwq,
static struct worker *find_worker_executing_work(struct global_cwq *gcwq,
struct work_struct *work)
{
- return __find_worker_executing_work(gcwq, busy_worker_head(gcwq, work),
- work);
+ struct worker *worker;
+ struct hlist_node *tmp;
+
+ hash_for_each_possible(gcwq->busy_hash, worker, tmp, hentry, (unsigned long)work)
+ if (worker->current_work == work)
+ return worker;
+
+ return NULL;
}
/**
@@ -2120,7 +2067,6 @@ __acquires(&gcwq->lock)
struct cpu_workqueue_struct *cwq = get_work_cwq(work);
struct worker_pool *pool = worker->pool;
struct global_cwq *gcwq = pool->gcwq;
- struct hlist_head *bwh = busy_worker_head(gcwq, work);
bool cpu_intensive = cwq->wq->flags & WQ_CPU_INTENSIVE;
work_func_t f = work->func;
int work_color;
@@ -2152,7 +2098,7 @@ __acquires(&gcwq->lock)
* already processing the work. If so, defer the work to the
* currently executing one.
*/
- collision = __find_worker_executing_work(gcwq, bwh, work);
+ collision = find_worker_executing_work(gcwq, work);
if (unlikely(collision)) {
move_linked_works(work, &collision->scheduled, NULL);
return;
@@ -2160,7 +2106,7 @@ __acquires(&gcwq->lock)
/* claim and dequeue */
debug_work_deactivate(work);
- hlist_add_head(&worker->hentry, bwh);
+ hash_add(gcwq->busy_hash, &worker->hentry, (unsigned long)worker);
worker->current_work = work;
worker->current_cwq = cwq;
work_color = get_work_color(work);
@@ -2223,7 +2169,7 @@ __acquires(&gcwq->lock)
worker_clr_flags(worker, WORKER_CPU_INTENSIVE);
/* we're done with it, release */
- hlist_del_init(&worker->hentry);
+ hash_del(&worker->hentry);
worker->current_work = NULL;
worker->current_cwq = NULL;
cwq_dec_nr_in_flight(cwq, work_color, false);
@@ -3855,7 +3801,6 @@ out_unlock:
static int __init init_workqueues(void)
{
unsigned int cpu;
- int i;
/* make sure we have enough bits for OFFQ CPU number */
BUILD_BUG_ON((1LU << (BITS_PER_LONG - WORK_OFFQ_CPU_SHIFT)) <
@@ -3873,8 +3818,7 @@ static int __init init_workqueues(void)
gcwq->cpu = cpu;
gcwq->flags |= GCWQ_DISASSOCIATED;
- for (i = 0; i < BUSY_WORKER_HASH_SIZE; i++)
- INIT_HLIST_HEAD(&gcwq->busy_hash[i]);
+ hash_init(gcwq->busy_hash);
for_each_worker_pool(pool, gcwq) {
pool->gcwq = gcwq;
--
1.7.8.6
^ permalink raw reply related
* [PATCH v3 03/17] mm, ksm: use new hashtable implementation
From: Sasha Levin @ 2012-08-22 2:26 UTC (permalink / raw)
To: torvalds-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b
Cc: snitzer-H+wXaHxf7aLQT0dZR+AlfA, neilb-l3A5Bk7waGM,
fweisbec-Re5JQEeQqe8AvxtiuMwx3w,
Trond.Myklebust-HgOvQuBEEgTQT0dZR+AlfA,
bfields-uC3wQj2KruNg9hUCZPvPmw,
paul.gortmaker-CWA4WttNNZF54TAoqtyWWQ,
dm-devel-H+wXaHxf7aLQT0dZR+AlfA, agk-H+wXaHxf7aLQT0dZR+AlfA,
aarcange-H+wXaHxf7aLQT0dZR+AlfA, rds-devel-N0ozoZBvEnrZJqsBc5GL+g,
eric.dumazet-Re5JQEeQqe8AvxtiuMwx3w,
venkat.x.venkatsubra-QHcLZuEGTsvQT0dZR+AlfA,
ccaulfie-H+wXaHxf7aLQT0dZR+AlfA, mingo-X9Un+BFzKDI,
dev-yBygre7rU0TnMu66kgdUjQ, ericvh-Re5JQEeQqe8AvxtiuMwx3w,
josh-iaAMLnmF4UmaiuxdJuQwMA, rostedt-nx8X9YLhiw1AfugRpC6u6w,
lw-BthXqXjhjHXQFUHtdCDX3A,
mathieu.desnoyers-vg+e7yoeK/dWk0Htik3J/w, Sasha Levin,
axboe-tSWWG44O7X1aa/9Udqfwiw, linux-nfs-u79uwXL29TY76Z2rM5mHXA,
edumazet-hpIqsD4AKlfQT0dZR+AlfA, linux-mm-Bw31MaZKKs3YtjvyW6yDsg,
netdev-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, ejt-H+wXaHxf7aLQT0dZR+AlfA,
ebiederm-aS9lmoZGLiVWk0Htik3J/w, tj-DgEjT+Ai2ygdnm+yROfE0A,
teigland-H+wXaHxf7aLQT0dZR+AlfA,
akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
davem-fT/PcQaiUtIeIZ0/mPfg9Q
In-Reply-To: <1345602432-27673-1-git-send-email-levinsasha928-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Switch ksm to use the new hashtable implementation. This reduces the amount of
generic unrelated code in the ksm module.
Signed-off-by: Sasha Levin <levinsasha928-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
mm/ksm.c | 33 +++++++++++++++------------------
1 files changed, 15 insertions(+), 18 deletions(-)
diff --git a/mm/ksm.c b/mm/ksm.c
index 9638620..dd4d6af 100644
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -33,7 +33,7 @@
#include <linux/mmu_notifier.h>
#include <linux/swap.h>
#include <linux/ksm.h>
-#include <linux/hash.h>
+#include <linux/hashtable.h>
#include <linux/freezer.h>
#include <linux/oom.h>
@@ -156,9 +156,8 @@ struct rmap_item {
static struct rb_root root_stable_tree = RB_ROOT;
static struct rb_root root_unstable_tree = RB_ROOT;
-#define MM_SLOTS_HASH_SHIFT 10
-#define MM_SLOTS_HASH_HEADS (1 << MM_SLOTS_HASH_SHIFT)
-static struct hlist_head mm_slots_hash[MM_SLOTS_HASH_HEADS];
+#define MM_SLOTS_HASH_BITS 10
+static DEFINE_HASHTABLE(mm_slots_hash, MM_SLOTS_HASH_BITS);
static struct mm_slot ksm_mm_head = {
.mm_list = LIST_HEAD_INIT(ksm_mm_head.mm_list),
@@ -275,26 +274,21 @@ static inline void free_mm_slot(struct mm_slot *mm_slot)
static struct mm_slot *get_mm_slot(struct mm_struct *mm)
{
- struct mm_slot *mm_slot;
- struct hlist_head *bucket;
struct hlist_node *node;
+ struct mm_slot *slot;
+
+ hash_for_each_possible(mm_slots_hash, slot, node, link, (unsigned long)mm)
+ if (slot->mm == mm)
+ return slot;
- bucket = &mm_slots_hash[hash_ptr(mm, MM_SLOTS_HASH_SHIFT)];
- hlist_for_each_entry(mm_slot, node, bucket, link) {
- if (mm == mm_slot->mm)
- return mm_slot;
- }
return NULL;
}
static void insert_to_mm_slots_hash(struct mm_struct *mm,
struct mm_slot *mm_slot)
{
- struct hlist_head *bucket;
-
- bucket = &mm_slots_hash[hash_ptr(mm, MM_SLOTS_HASH_SHIFT)];
mm_slot->mm = mm;
- hlist_add_head(&mm_slot->link, bucket);
+ hash_add(mm_slots_hash, &mm_slot->link, (unsigned long)mm);
}
static inline int in_stable_tree(struct rmap_item *rmap_item)
@@ -647,7 +641,7 @@ static int unmerge_and_remove_all_rmap_items(void)
ksm_scan.mm_slot = list_entry(mm_slot->mm_list.next,
struct mm_slot, mm_list);
if (ksm_test_exit(mm)) {
- hlist_del(&mm_slot->link);
+ hash_del(&mm_slot->link);
list_del(&mm_slot->mm_list);
spin_unlock(&ksm_mmlist_lock);
@@ -1385,7 +1379,7 @@ next_mm:
* or when all VM_MERGEABLE areas have been unmapped (and
* mmap_sem then protects against race with MADV_MERGEABLE).
*/
- hlist_del(&slot->link);
+ hash_del(&slot->link);
list_del(&slot->mm_list);
spin_unlock(&ksm_mmlist_lock);
@@ -1552,7 +1546,7 @@ void __ksm_exit(struct mm_struct *mm)
mm_slot = get_mm_slot(mm);
if (mm_slot && ksm_scan.mm_slot != mm_slot) {
if (!mm_slot->rmap_list) {
- hlist_del(&mm_slot->link);
+ hash_del(&mm_slot->link);
list_del(&mm_slot->mm_list);
easy_to_free = 1;
} else {
@@ -2028,6 +2022,9 @@ static int __init ksm_init(void)
*/
hotplug_memory_notifier(ksm_memory_callback, 100);
#endif
+
+ hash_init(mm_slots_hash);
+
return 0;
out_free:
--
1.7.8.6
^ permalink raw reply related
* [PATCH v3 02/17] userns: use new hashtable implementation
From: Sasha Levin @ 2012-08-22 2:26 UTC (permalink / raw)
To: torvalds
Cc: tj, akpm, linux-kernel, linux-mm, paul.gortmaker, davem, rostedt,
mingo, ebiederm, aarcange, ericvh, netdev, josh, eric.dumazet,
mathieu.desnoyers, axboe, agk, dm-devel, neilb, ccaulfie,
teigland, Trond.Myklebust, bfields, fweisbec, jesse,
venkat.x.venkatsubra, ejt, snitzer, edumazet, linux-nfs, dev,
rds-devel, lw, Sasha Levin
In-Reply-To: <1345602432-27673-1-git-send-email-levinsasha928@gmail.com>
Switch to using the new hashtable implementation to store user structs.
This reduces the amount of generic unrelated code in kernel/user.c.
Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
---
kernel/user.c | 33 +++++++++++++--------------------
1 files changed, 13 insertions(+), 20 deletions(-)
diff --git a/kernel/user.c b/kernel/user.c
index b815fef..d10c484 100644
--- a/kernel/user.c
+++ b/kernel/user.c
@@ -16,6 +16,7 @@
#include <linux/interrupt.h>
#include <linux/export.h>
#include <linux/user_namespace.h>
+#include <linux/hashtable.h>
/*
* userns count is 1 for root user, 1 for init_uts_ns,
@@ -52,13 +53,9 @@ EXPORT_SYMBOL_GPL(init_user_ns);
*/
#define UIDHASH_BITS (CONFIG_BASE_SMALL ? 3 : 7)
-#define UIDHASH_SZ (1 << UIDHASH_BITS)
-#define UIDHASH_MASK (UIDHASH_SZ - 1)
-#define __uidhashfn(uid) (((uid >> UIDHASH_BITS) + uid) & UIDHASH_MASK)
-#define uidhashentry(uid) (uidhash_table + __uidhashfn((__kuid_val(uid))))
static struct kmem_cache *uid_cachep;
-struct hlist_head uidhash_table[UIDHASH_SZ];
+static DEFINE_HASHTABLE(uidhash_table, UIDHASH_BITS)
/*
* The uidhash_lock is mostly taken from process context, but it is
@@ -84,22 +81,22 @@ struct user_struct root_user = {
/*
* These routines must be called with the uidhash spinlock held!
*/
-static void uid_hash_insert(struct user_struct *up, struct hlist_head *hashent)
+static void uid_hash_insert(struct user_struct *up)
{
- hlist_add_head(&up->uidhash_node, hashent);
+ hash_add(uidhash_table, &up->uidhash_node, __kuid_val(up->uid));
}
static void uid_hash_remove(struct user_struct *up)
{
- hlist_del_init(&up->uidhash_node);
+ hash_del(&up->uidhash_node);
}
-static struct user_struct *uid_hash_find(kuid_t uid, struct hlist_head *hashent)
+static struct user_struct *uid_hash_find(kuid_t uid)
{
struct user_struct *user;
struct hlist_node *h;
- hlist_for_each_entry(user, h, hashent, uidhash_node) {
+ hash_for_each_possible(uidhash_table, user, h, uidhash_node, __kuid_val(uid)) {
if (uid_eq(user->uid, uid)) {
atomic_inc(&user->__count);
return user;
@@ -135,7 +132,7 @@ struct user_struct *find_user(kuid_t uid)
unsigned long flags;
spin_lock_irqsave(&uidhash_lock, flags);
- ret = uid_hash_find(uid, uidhashentry(uid));
+ ret = uid_hash_find(uid);
spin_unlock_irqrestore(&uidhash_lock, flags);
return ret;
}
@@ -156,11 +153,10 @@ void free_uid(struct user_struct *up)
struct user_struct *alloc_uid(kuid_t uid)
{
- struct hlist_head *hashent = uidhashentry(uid);
struct user_struct *up, *new;
spin_lock_irq(&uidhash_lock);
- up = uid_hash_find(uid, hashent);
+ up = uid_hash_find(uid);
spin_unlock_irq(&uidhash_lock);
if (!up) {
@@ -176,13 +172,13 @@ struct user_struct *alloc_uid(kuid_t uid)
* on adding the same user already..
*/
spin_lock_irq(&uidhash_lock);
- up = uid_hash_find(uid, hashent);
+ up = uid_hash_find(uid);
if (up) {
key_put(new->uid_keyring);
key_put(new->session_keyring);
kmem_cache_free(uid_cachep, new);
} else {
- uid_hash_insert(new, hashent);
+ uid_hash_insert(new);
up = new;
}
spin_unlock_irq(&uidhash_lock);
@@ -196,17 +192,14 @@ out_unlock:
static int __init uid_cache_init(void)
{
- int n;
-
uid_cachep = kmem_cache_create("uid_cache", sizeof(struct user_struct),
0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
- for(n = 0; n < UIDHASH_SZ; ++n)
- INIT_HLIST_HEAD(uidhash_table + n);
+ hash_init(uidhash_table);
/* Insert the root user immediately (init already runs as root) */
spin_lock_irq(&uidhash_lock);
- uid_hash_insert(&root_user, uidhashentry(GLOBAL_ROOT_UID));
+ uid_hash_insert(&root_user);
spin_unlock_irq(&uidhash_lock);
return 0;
--
1.7.8.6
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply related
* [PATCH v3 01/17] hashtable: introduce a small and naive hashtable
From: Sasha Levin @ 2012-08-22 2:26 UTC (permalink / raw)
To: torvalds-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b
Cc: snitzer-H+wXaHxf7aLQT0dZR+AlfA, neilb-l3A5Bk7waGM,
fweisbec-Re5JQEeQqe8AvxtiuMwx3w,
Trond.Myklebust-HgOvQuBEEgTQT0dZR+AlfA,
bfields-uC3wQj2KruNg9hUCZPvPmw,
paul.gortmaker-CWA4WttNNZF54TAoqtyWWQ,
dm-devel-H+wXaHxf7aLQT0dZR+AlfA, agk-H+wXaHxf7aLQT0dZR+AlfA,
aarcange-H+wXaHxf7aLQT0dZR+AlfA, rds-devel-N0ozoZBvEnrZJqsBc5GL+g,
eric.dumazet-Re5JQEeQqe8AvxtiuMwx3w,
venkat.x.venkatsubra-QHcLZuEGTsvQT0dZR+AlfA,
ccaulfie-H+wXaHxf7aLQT0dZR+AlfA, mingo-X9Un+BFzKDI,
dev-yBygre7rU0TnMu66kgdUjQ, ericvh-Re5JQEeQqe8AvxtiuMwx3w,
josh-iaAMLnmF4UmaiuxdJuQwMA, rostedt-nx8X9YLhiw1AfugRpC6u6w,
lw-BthXqXjhjHXQFUHtdCDX3A,
mathieu.desnoyers-vg+e7yoeK/dWk0Htik3J/w, Sasha Levin,
axboe-tSWWG44O7X1aa/9Udqfwiw, linux-nfs-u79uwXL29TY76Z2rM5mHXA,
edumazet-hpIqsD4AKlfQT0dZR+AlfA, linux-mm-Bw31MaZKKs3YtjvyW6yDsg,
netdev-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, ejt-H+wXaHxf7aLQT0dZR+AlfA,
ebiederm-aS9lmoZGLiVWk0Htik3J/w, tj-DgEjT+Ai2ygdnm+yROfE0A,
teigland-H+wXaHxf7aLQT0dZR+AlfA,
akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
davem-fT/PcQaiUtIeIZ0/mPfg9Q
In-Reply-To: <1345602432-27673-1-git-send-email-levinsasha928-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
This hashtable implementation is using hlist buckets to provide a simple
hashtable to prevent it from getting reimplemented all over the kernel.
Signed-off-by: Sasha Levin <levinsasha928-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
include/linux/hashtable.h | 291 +++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 291 insertions(+), 0 deletions(-)
create mode 100644 include/linux/hashtable.h
diff --git a/include/linux/hashtable.h b/include/linux/hashtable.h
new file mode 100644
index 0000000..d2d6ed0
--- /dev/null
+++ b/include/linux/hashtable.h
@@ -0,0 +1,291 @@
+/*
+ * Hash table implementation
+ * (C) 2012 Sasha Levin <levinsasha928-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
+ */
+
+#ifndef _LINUX_HASHTABLE_H
+#define _LINUX_HASHTABLE_H
+
+#include <linux/list.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/hash.h>
+#include <linux/rculist.h>
+
+#define DEFINE_HASHTABLE(name, bits) \
+ struct hlist_head name[HASH_SIZE(bits)];
+
+#define HASH_SIZE(bits) (1 << (bits))
+#define HASH_BITS(name) (ilog2(ARRAY_SIZE(name)))
+#define HASH_REQUIRED_SIZE(bits) (sizeof(struct hlist_head) * HASH_SIZE(bits))
+
+/* Use hash_32 when possible to allow for fast 32bit hashing in 64bit kernels. */
+#define hash_min(val, bits) ((sizeof(val)==4) ? hash_32((val), (bits)) : hash_long((val), (bits)))
+
+/**
+ * hash_init_size - initialize a hash table
+ * @hashtable: hashtable to be initialized
+ * @bits: bit count of hashing function
+ *
+ * Initializes a hash table with 2**bits buckets.
+ */
+static inline void hash_init_size(struct hlist_head *hashtable, int bits)
+{
+ int i;
+
+ for (i = 0; i < HASH_SIZE(bits); i++)
+ INIT_HLIST_HEAD(hashtable + i);
+}
+
+/**
+ * hash_init - initialize a hash table
+ * @hashtable: hashtable to be initialized
+ *
+ * Calculates the size of the hashtable from the given parameter, otherwise
+ * same as hash_init_size.
+ */
+#define hash_init(name) hash_init_size(name, HASH_BITS(name))
+
+/**
+ * hash_add_size - add an object to a hashtable
+ * @hashtable: hashtable to add to
+ * @bits: bit count used for hashing
+ * @node: the &struct hlist_node of the object to be added
+ * @key: the key of the object to be added
+ */
+#define hash_add_size(hashtable, bits, node, key) \
+ hlist_add_head(node, &hashtable[hash_min(key, bits)]);
+
+/**
+ * hash_add - add an object to a hashtable
+ * @hashtable: hashtable to add to
+ * @node: the &struct hlist_node of the object to be added
+ * @key: the key of the object to be added
+ */
+#define hash_add(hashtable, node, key) \
+ hash_add_size(hashtable, HASH_BITS(hashtable), node, key)
+
+/**
+ * hash_add_rcu_size - add an object to a rcu enabled hashtable
+ * @hashtable: hashtable to add to
+ * @bits: bit count used for hashing
+ * @node: the &struct hlist_node of the object to be added
+ * @key: the key of the object to be added
+ */
+#define hash_add_rcu_size(hashtable, bits, node, key) \
+ hlist_add_head_rcu(node, &hashtable[hash_min(key, bits)]);
+
+/**
+ * hash_add_rcu - add an object to a rcu enabled hashtable
+ * @hashtable: hashtable to add to
+ * @node: the &struct hlist_node of the object to be added
+ * @key: the key of the object to be added
+ */
+#define hash_add_rcu(hashtable, node, key) \
+ hash_add_rcu_size(hashtable, HASH_BITS(hashtable), node, key)
+
+/**
+ * hash_hashed - check whether an object is in any hashtable
+ * @node: the &struct hlist_node of the object to be checked
+ */
+#define hash_hashed(node) (!hlist_unhashed(node))
+
+/**
+ * hash_empty_size - check whether a hashtable is empty
+ * @hashtable: hashtable to check
+ * @bits: bit count used for hashing
+ */
+static inline bool hash_empty_size(struct hlist_head *hashtable, int bits)
+{
+ int i;
+
+ for (i = 0; i < HASH_SIZE(bits); i++)
+ if (!hlist_empty(&hashtable[i]))
+ return false;
+
+ return true;
+}
+
+/**
+ * hash_empty - check whether a hashtable is empty
+ * @hashtable: hashtable to check
+ */
+#define hash_empty(name) hash_empty_size(name, HASH_BITS(name))
+
+/**
+ * hash_del - remove an object from a hashtable
+ * @node: &struct hlist_node of the object to remove
+ */
+static inline void hash_del(struct hlist_node *node)
+{
+ hlist_del_init(node);
+}
+
+/**
+ * hash_del_rcu - remove an object from a rcu enabled hashtable
+ * @node: &struct hlist_node of the object to remove
+ */
+static inline void hash_del_rcu(struct hlist_node *node)
+{
+ hlist_del_init_rcu(node);
+}
+
+/**
+ * hash_for_each_size - iterate over a hashtable
+ * @name: hashtable to iterate
+ * @bits: bit count of hashing function of the hashtable
+ * @bkt: integer to use as bucket loop cursor
+ * @node: the &struct list_head to use as a loop cursor for each entry
+ * @obj: the type * to use as a loop cursor for each entry
+ * @member: the name of the hlist_node within the struct
+ */
+#define hash_for_each_size(name, bits, bkt, node, obj, member) \
+ for (bkt = 0; bkt < HASH_SIZE(bits); bkt++) \
+ hlist_for_each_entry(obj, node, &name[bkt], member)
+
+/**
+ * hash_for_each - iterate over a hashtable
+ * @name: hashtable to iterate
+ * @bkt: integer to use as bucket loop cursor
+ * @node: the &struct list_head to use as a loop cursor for each entry
+ * @obj: the type * to use as a loop cursor for each entry
+ * @member: the name of the hlist_node within the struct
+ */
+#define hash_for_each(name, bkt, node, obj, member) \
+ hash_for_each_size(name, HASH_BITS(name), bkt, node, obj, member)
+
+/**
+ * hash_for_each_rcu_size - iterate over a rcu enabled hashtable
+ * @name: hashtable to iterate
+ * @bits: bit count of hashing function of the hashtable
+ * @bkt: integer to use as bucket loop cursor
+ * @node: the &struct list_head to use as a loop cursor for each entry
+ * @obj: the type * to use as a loop cursor for each entry
+ * @member: the name of the hlist_node within the struct
+ */
+#define hash_for_each_rcu_size(name, bits, bkt, node, obj, member) \
+ for (bkt = 0; bkt < HASH_SIZE(bits); bkt++) \
+ hlist_for_each_entry_rcu(obj, node, &name[bkt], member)
+
+/**
+ * hash_for_each_rcu - iterate over a rcu enabled hashtable
+ * @name: hashtable to iterate
+ * @bkt: integer to use as bucket loop cursor
+ * @node: the &struct list_head to use as a loop cursor for each entry
+ * @obj: the type * to use as a loop cursor for each entry
+ * @member: the name of the hlist_node within the struct
+ */
+#define hash_for_each_rcu(name, bkt, node, obj, member) \
+ hash_for_each_rcu_size(name, HASH_BITS(name), bkt, node, obj, member)
+
+/**
+ * hash_for_each_safe_size - iterate over a hashtable safe against removal of
+ * hash entry
+ * @name: hashtable to iterate
+ * @bkt: integer to use as bucket loop cursor
+ * @node: the &struct list_head to use as a loop cursor for each entry
+ * @tmp: another &struct hlist_node to use as temporary storage
+ * @obj: the type * to use as a loop cursor for each entry
+ * @member: the name of the hlist_node within the struct
+ */
+#define hash_for_each_safe_size(name, bits, bkt, node, tmp, obj, member) \
+ for (bkt = 0; bkt < HASH_SIZE(bits); bkt++) \
+ hlist_for_each_entry_safe(obj, node, tmp, &name[bkt], member)
+
+/**
+ * hash_for_each_safe_size - iterate over a hashtable safe against removal of
+ * hash entry
+ * @name: hashtable to iterate
+ * @bkt: integer to use as bucket loop cursor
+ * @node: the &struct list_head to use as a loop cursor for each entry
+ * @obj: the type * to use as a loop cursor for each entry
+ * @member: the name of the hlist_node within the struct
+ */
+#define hash_for_each_safe(name, bkt, node, tmp, obj, member) \
+ hash_for_each_safe_size(name, HASH_BITS(name), bkt, node, \
+ tmp, obj, member)
+
+/**
+ * hash_for_each_possible - iterate over all possible objects hasing to the
+ * same bucket
+ * @name: hashtable to iterate
+ * @obj: the type * to use as a loop cursor for each entry
+ * @bits: bit count of hashing function of the hashtable
+ * @node: the &struct list_head to use as a loop cursor for each entry
+ * @member: the name of the hlist_node within the struct
+ * @key: the key of the objects to iterate over
+ */
+#define hash_for_each_possible_size(name, obj, bits, node, member, key) \
+ hlist_for_each_entry(obj, node, &name[hash_min(key, bits)], member)
+
+/**
+ * hash_for_each_possible - iterate over all possible objects hashing to the
+ * same bucket
+ * @name: hashtable to iterate
+ * @obj: the type * to use as a loop cursor for each entry
+ * @bits: bit count of hashing function of the hashtable
+ * @node: the &struct list_head to use as a loop cursor for each entry
+ * @member: the name of the hlist_node within the struct
+ * @key: the key of the objects to iterate over
+ */
+#define hash_for_each_possible(name, obj, node, member, key) \
+ hash_for_each_possible_size(name, obj, HASH_BITS(name), node, member, key)
+
+/**
+ * hash_for_each_possible - iterate over all possible objects hashing to the
+ * same bucket
+ * in a rcu enabled hashtable
+ * @name: hashtable to iterate
+ * @obj: the type * to use as a loop cursor for each entry
+ * @bits: bit count of hashing function of the hashtable
+ * @node: the &struct list_head to use as a loop cursor for each entry
+ * @member: the name of the hlist_node within the struct
+ * @key: the key of the objects to iterate over
+ */
+#define hash_for_each_possible_rcu_size(name, obj, bits, node, member, key) \
+ hlist_for_each_entry_rcu(obj, node, &name[hash_min(key, bits)], member)
+
+/**
+ * hash_for_each_possible - iterate over all possible objects hashing to the
+ * same bucket
+ * in a rcu enabled hashtable
+ * @name: hashtable to iterate
+ * @obj: the type * to use as a loop cursor for each entry
+ * @node: the &struct list_head to use as a loop cursor for each entry
+ * @member: the name of the hlist_node within the struct
+ * @key: the key of the objects to iterate over
+ */
+#define hash_for_each_possible_rcu(name, obj, node, member, key) \
+ hash_for_each_possible_rcu_size(name, obj, HASH_BITS(name), \
+ node, member, key)
+
+/**
+ * hash_for_each_possible - iterate over all possible objects hashing to the
+ * same bucket
+ * safe against removal of hash entry
+ * @name: hashtable to iterate
+ * @obj: the type * to use as a loop cursor for each entry
+ * @bits: bit count of hashing function of the hashtable
+ * @node: the &struct list_head to use as a loop cursor for each entry
+ * @member: the name of the hlist_node within the struct
+ * @key: the key of the objects to iterate over
+ */
+#define hash_for_each_possible_safe_size(name, obj, bits, node, tmp, member, key)\
+ hlist_for_each_entry_safe(obj, node, tmp, \
+ &name[hash_min(key, bits)], member)
+
+/**
+ * hash_for_each_possible - iterate over all possible objects hashing to the
+ * same bucket
+ * safe against removal of hash entry
+ * @name: hashtable to iterate
+ * @obj: the type * to use as a loop cursor for each entry
+ * @node: the &struct list_head to use as a loop cursor for each entry
+ * @member: the name of the hlist_node within the struct
+ * @key: the key of the objects to iterate over
+ */
+#define hash_for_each_possible_safe(name, obj, node, tmp, member, key) \
+ hash_for_each_possible_safe_size(name, obj, HASH_BITS(name), \
+ node, tmp, member, key)
+
+#endif
--
1.7.8.6
^ permalink raw reply related
* [PATCH v3 00/17] generic hashtable implementation
From: Sasha Levin @ 2012-08-22 2:26 UTC (permalink / raw)
To: torvalds
Cc: tj, akpm, linux-kernel, linux-mm, paul.gortmaker, davem, rostedt,
mingo, ebiederm, aarcange, ericvh, netdev, josh, eric.dumazet,
mathieu.desnoyers, axboe, agk, dm-devel, neilb, ccaulfie,
teigland, Trond.Myklebust, bfields, fweisbec, jesse,
venkat.x.venkatsubra, ejt, snitzer, edumazet, linux-nfs, dev,
rds-devel, lw, Sasha Levin
There are quite a few places in the kernel which implement a hashtable
in a very similar way. Instead of having implementations of a hashtable
all over the kernel, we can re-use the code.
Since it looks like all the major issues we're addressed in the RFC phase
and no major issues were raised with this patch set, I'd be happy to see
this getting merged so that work could continue on different aspects of
the hashtable. Some interesting directions include:
- Introducing a dynamic RCU hashtable such as the one Mathieu Desnoyers
wrote about out in the userspace RCU.
- Replacing the rest of the the kernel structures which use the same basec
hashtable construct to use this new interface.
- Same as above, but for non-obvious places (for example, I'm looking into
using the hashtable to store KVM vcpus instead of the linked list being used
there now - this should help performance with a large amount of vcpus).
Changes since v2:
- Documentation improvements from Mathieu Desnoyers.
- Converted the SUNRPC audit code to use hashtables as well. Since that code
requires a dynamic hashtable this shows off the _size() API usage.
Changes since v1:
- Added missing hash_init in rds and lockd.
- Addressed the userns comments by Eric Biederman.
- Ran a small test to confirm hash_32 does a good job for low key
values (1-10000), which showed it did - this resulted in no changes to the
code.
Sasha Levin (17):
hashtable: introduce a small and naive hashtable
userns: use new hashtable implementation
mm,ksm: use new hashtable implementation
workqueue: use new hashtable implementation
mm/huge_memory: use new hashtable implementation
tracepoint: use new hashtable implementation
net,9p: use new hashtable implementation
block,elevator: use new hashtable implementation
SUNRPC/cache: use new hashtable implementation
dlm: use new hashtable implementation
net,l2tp: use new hashtable implementation
dm: use new hashtable implementation
lockd: use new hashtable implementation
net,rds: use new hashtable implementation
openvswitch: use new hashtable implementation
tracing output: use new hashtable implementation
SUNRPC: use new hashtable implementation in auth
block/blk.h | 2 +-
block/elevator.c | 23 +--
drivers/md/dm-snap.c | 24 +--
drivers/md/persistent-data/dm-block-manager.c | 1 -
.../persistent-data/dm-persistent-data-internal.h | 19 --
.../md/persistent-data/dm-transaction-manager.c | 30 +--
fs/dlm/lowcomms.c | 47 +---
fs/lockd/svcsubs.c | 66 +++--
include/linux/elevator.h | 5 +-
include/linux/hashtable.h | 291 ++++++++++++++++++++
kernel/trace/trace_output.c | 20 +-
kernel/tracepoint.c | 27 +-
kernel/user.c | 33 +--
kernel/workqueue.c | 86 +-----
mm/huge_memory.c | 57 +---
mm/ksm.c | 33 +--
net/9p/error.c | 21 +-
net/l2tp/l2tp_core.c | 134 ++++------
net/l2tp/l2tp_core.h | 8 +-
net/l2tp/l2tp_debugfs.c | 19 +-
net/openvswitch/vport.c | 30 +--
net/rds/bind.c | 28 ++-
net/rds/connection.c | 102 +++----
net/sunrpc/auth.c | 45 ++--
net/sunrpc/cache.c | 20 +-
25 files changed, 617 insertions(+), 554 deletions(-)
delete mode 100644 drivers/md/persistent-data/dm-persistent-data-internal.h
create mode 100644 include/linux/hashtable.h
--
1.7.8.6
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply
* Re: [PATCH 0/3] x86_64, sfc: 128-bit memory-mapped I/O
From: Ben Hutchings @ 2012-08-22 2:10 UTC (permalink / raw)
To: H. Peter Anvin
Cc: Thomas Gleixner, Ingo Molnar, netdev, linux-net-drivers, x86
In-Reply-To: <50343D16.4040901@zytor.com>
On Tue, 2012-08-21 at 18:59 -0700, H. Peter Anvin wrote:
> On 08/21/2012 06:43 PM, Ben Hutchings wrote:
> > On Tue, 2012-08-21 at 18:38 -0700, H. Peter Anvin wrote:
> >> On 08/21/2012 06:17 PM, Ben Hutchings wrote:
> >>> Current Solarflare network controllers have 128-bit memory-mapped
> >>> registers which are normally accessed through a series of I/O
> >>> operations. However, it is also possible to access them with a single
> >>> MOVAPS instruction on x86_64, and this is measurably faster as it
> >>> requires only one PCIe transaction.
> >>
> >> Also, have you considered doing this with write combining instead?
> >
> > We tried it, and it goes horribly wrong. On some systems, the writes
> > are not combined, but they are reordered in a way the hardware doesn't
> > support. See the comment at the top of drivers/net/ethernet/sfc/io.h.
> >
>
> Yes, you have to make sure you properly enforce the necessary ordering
> requirements manually (I think you can do that with sfence).
We did put an sfence after the writes to each register. But some
systems only want to combine writes that cover an entire cache line, and
the writes covering a 128-bit register get broken back up into multiple
writes at the PCIe level. And on some systems these are sent in
decreasing address order, which breaks the rules for writing to
TX_DESC_UPD.
To avoid this we'd have to put an sfence in between the writes to a
register, leaving us back where we started.
Ben.
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply
* Re: [PATCH 2/3] x86_64: Define 128-bit memory-mapped I/O operations
From: Ben Hutchings @ 2012-08-22 2:04 UTC (permalink / raw)
To: H. Peter Anvin
Cc: Thomas Gleixner, Ingo Molnar, netdev, linux-net-drivers, x86
In-Reply-To: <503437D4.8090706@zytor.com>
On Tue, 2012-08-21 at 18:37 -0700, H. Peter Anvin wrote:
> On 08/21/2012 06:23 PM, Ben Hutchings wrote:
> > Define reado(), writeo() and their raw counterparts using SSE.
> >
> > Based on work by Stuart Hodgson <smhodgson@solarflare.com>.
>
> It would be vastly better if we explicitly controlled this with
> kernel_fpu_begin()/kernel_fpu_end() rather than hiding it in primitives
> than might tempt the user to do very much the wrong thing.
>
> Also, it needs to be extremely clear to the user that these operations
> use the FPU, and all the requirements there need to be met, including
> not using them at interrupt time.
Well we can sometimes use the FPU state at IRQ time, can't we
(irq_fpu_usable())? So we might need, say, try_reado() and
try_writeo() with callers expected to fall back to alternatives. (Which
they must have anyway for any architecture that doesn't support this.)
Ben.
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply
* Re: [PATCH 0/3] x86_64, sfc: 128-bit memory-mapped I/O
From: H. Peter Anvin @ 2012-08-22 1:59 UTC (permalink / raw)
To: Ben Hutchings
Cc: Thomas Gleixner, Ingo Molnar, netdev, linux-net-drivers, x86
In-Reply-To: <1345599783.2659.82.camel@bwh-desktop.uk.solarflarecom.com>
On 08/21/2012 06:43 PM, Ben Hutchings wrote:
> On Tue, 2012-08-21 at 18:38 -0700, H. Peter Anvin wrote:
>> On 08/21/2012 06:17 PM, Ben Hutchings wrote:
>>> Current Solarflare network controllers have 128-bit memory-mapped
>>> registers which are normally accessed through a series of I/O
>>> operations. However, it is also possible to access them with a single
>>> MOVAPS instruction on x86_64, and this is measurably faster as it
>>> requires only one PCIe transaction.
>>
>> Also, have you considered doing this with write combining instead?
>
> We tried it, and it goes horribly wrong. On some systems, the writes
> are not combined, but they are reordered in a way the hardware doesn't
> support. See the comment at the top of drivers/net/ethernet/sfc/io.h.
>
Yes, you have to make sure you properly enforce the necessary ordering
requirements manually (I think you can do that with sfence).
-hpa
^ permalink raw reply
* Re: [PATCH 0/3] x86_64, sfc: 128-bit memory-mapped I/O
From: Ben Hutchings @ 2012-08-22 1:43 UTC (permalink / raw)
To: H. Peter Anvin
Cc: Thomas Gleixner, Ingo Molnar, netdev, linux-net-drivers, x86
In-Reply-To: <50343810.2000809@zytor.com>
On Tue, 2012-08-21 at 18:38 -0700, H. Peter Anvin wrote:
> On 08/21/2012 06:17 PM, Ben Hutchings wrote:
> > Current Solarflare network controllers have 128-bit memory-mapped
> > registers which are normally accessed through a series of I/O
> > operations. However, it is also possible to access them with a single
> > MOVAPS instruction on x86_64, and this is measurably faster as it
> > requires only one PCIe transaction.
>
> Also, have you considered doing this with write combining instead?
We tried it, and it goes horribly wrong. On some systems, the writes
are not combined, but they are reordered in a way the hardware doesn't
support. See the comment at the top of drivers/net/ethernet/sfc/io.h.
Ben.
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply
* Re: [PATCH 0/3] x86_64, sfc: 128-bit memory-mapped I/O
From: H. Peter Anvin @ 2012-08-22 1:38 UTC (permalink / raw)
To: Ben Hutchings
Cc: Thomas Gleixner, Ingo Molnar, netdev, linux-net-drivers, x86
In-Reply-To: <1345598275.2659.71.camel@bwh-desktop.uk.solarflarecom.com>
On 08/21/2012 06:17 PM, Ben Hutchings wrote:
> Current Solarflare network controllers have 128-bit memory-mapped
> registers which are normally accessed through a series of I/O
> operations. However, it is also possible to access them with a single
> MOVAPS instruction on x86_64, and this is measurably faster as it
> requires only one PCIe transaction.
Also, have you considered doing this with write combining instead?
-hpa
^ permalink raw reply
* Re: [PATCH 2/3] x86_64: Define 128-bit memory-mapped I/O operations
From: H. Peter Anvin @ 2012-08-22 1:37 UTC (permalink / raw)
To: Ben Hutchings
Cc: Thomas Gleixner, Ingo Molnar, netdev, linux-net-drivers, x86
In-Reply-To: <1345598601.2659.76.camel@bwh-desktop.uk.solarflarecom.com>
On 08/21/2012 06:23 PM, Ben Hutchings wrote:
> Define reado(), writeo() and their raw counterparts using SSE.
>
> Based on work by Stuart Hodgson <smhodgson@solarflare.com>.
It would be vastly better if we explicitly controlled this with
kernel_fpu_begin()/kernel_fpu_end() rather than hiding it in primitives
than might tempt the user to do very much the wrong thing.
Also, it needs to be extremely clear to the user that these operations
use the FPU, and all the requirements there need to be met, including
not using them at interrupt time.
-hpa
^ permalink raw reply
* [PATCH 3/3] sfc: Use __raw_writeo() to perform TX descriptor push where possible
From: Ben Hutchings @ 2012-08-22 1:26 UTC (permalink / raw)
To: David Miller, Thomas Gleixner, Ingo Molnar, H. Peter Anvin
Cc: netdev, linux-net-drivers, x86
In-Reply-To: <1345598275.2659.71.camel@bwh-desktop.uk.solarflarecom.com>
Use the new __raw_writeo() function for TX descriptor push where
available. This means we now use only a single PCIe transaction
on x86_64 (vs 2 before), reducing TX latency slightly.
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
David,
Assuming the previous 2 patches are accepted for x86, I expect you'll
still want to take this into the net-next tree. So perhaps they should
go onto a separate branch that you can pull?
Ben.
drivers/net/ethernet/sfc/bitfield.h | 3 +++
drivers/net/ethernet/sfc/io.h | 18 ++++++++++++++++--
2 files changed, 19 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/sfc/bitfield.h b/drivers/net/ethernet/sfc/bitfield.h
index b26a954..5feeba2 100644
--- a/drivers/net/ethernet/sfc/bitfield.h
+++ b/drivers/net/ethernet/sfc/bitfield.h
@@ -83,6 +83,9 @@ typedef union efx_qword {
/* An octword (eight-word, i.e. 16 byte) datatype - little-endian in HW */
typedef union efx_oword {
+#ifdef HAVE_INT128
+ __le128 u128;
+#endif
__le64 u64[2];
efx_qword_t qword[2];
__le32 u32[4];
diff --git a/drivers/net/ethernet/sfc/io.h b/drivers/net/ethernet/sfc/io.h
index 751d1ec..fbcdc6d 100644
--- a/drivers/net/ethernet/sfc/io.h
+++ b/drivers/net/ethernet/sfc/io.h
@@ -57,10 +57,22 @@
* current state.
*/
-#if BITS_PER_LONG == 64
+#if defined(writeo)
+#define EFX_USE_OWORD_IO 1
+#endif
+
+#if defined(readq) && defined(writeq)
#define EFX_USE_QWORD_IO 1
#endif
+#ifdef EFX_USE_OWORD_IO
+static inline void _efx_writeo(struct efx_nic *efx, __le128 value,
+ unsigned int reg)
+{
+ __raw_writeo((__force u128)value, efx->membase + reg);
+}
+#endif
+
#ifdef EFX_USE_QWORD_IO
static inline void _efx_writeq(struct efx_nic *efx, __le64 value,
unsigned int reg)
@@ -235,7 +247,9 @@ static inline void _efx_writeo_page(struct efx_nic *efx, efx_oword_t *value,
"writing register %x with " EFX_OWORD_FMT "\n", reg,
EFX_OWORD_VAL(*value));
-#ifdef EFX_USE_QWORD_IO
+#if defined(EFX_USE_OWORD_IO)
+ _efx_writeo(efx, value->u128, reg);
+#elif defined(EFX_USE_QWORD_IO)
_efx_writeq(efx, value->u64[0], reg + 0);
_efx_writeq(efx, value->u64[1], reg + 8);
#else
--
1.7.7.6
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply related
* [PATCH 2/3] x86_64: Define 128-bit memory-mapped I/O operations
From: Ben Hutchings @ 2012-08-22 1:23 UTC (permalink / raw)
To: Thomas Gleixner, Ingo Molnar, H. Peter Anvin
Cc: netdev, linux-net-drivers, x86
In-Reply-To: <1345598275.2659.71.camel@bwh-desktop.uk.solarflarecom.com>
Define reado(), writeo() and their raw counterparts using SSE.
Based on work by Stuart Hodgson <smhodgson@solarflare.com>.
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
arch/x86/Kconfig.cpu | 4 +++
arch/x86/include/asm/io.h | 14 +++++++++
arch/x86/lib/Makefile | 1 +
arch/x86/lib/oword_io.c | 65 +++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 84 insertions(+), 0 deletions(-)
create mode 100644 arch/x86/lib/oword_io.c
diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu
index 706e12e..802508e 100644
--- a/arch/x86/Kconfig.cpu
+++ b/arch/x86/Kconfig.cpu
@@ -372,6 +372,10 @@ config X86_USE_3DNOW
def_bool y
depends on (MCYRIXIII || MK7 || MGEODE_LX) && !UML
+config X86_USE_SSE
+ def_bool y
+ depends on X86_64
+
config X86_OOSTORE
def_bool y
depends on (MWINCHIP3D || MWINCHIPC6) && MTRR
diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h
index d8e8eef..06b3e23 100644
--- a/arch/x86/include/asm/io.h
+++ b/arch/x86/include/asm/io.h
@@ -95,6 +95,20 @@ build_mmio_write(writeq, "q", unsigned long, "r", :"memory")
#endif
+#ifdef CONFIG_X86_USE_SSE
+
+u128 reado(const volatile void __iomem *addr);
+void writeo(u128 val, volatile void __iomem *addr);
+
+#define __raw_reado(addr) reado(addr)
+#define __raw_writeo(val, addr) writeo(val, addr)
+
+/* Let people know that we have them */
+#define reado reado
+#define writeo writeo
+
+#endif
+
/**
* virt_to_phys - map virtual addresses to physical
* @address: address to remap
diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile
index b00f678..1791198 100644
--- a/arch/x86/lib/Makefile
+++ b/arch/x86/lib/Makefile
@@ -25,6 +25,7 @@ lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
lib-$(CONFIG_INSTRUCTION_DECODER) += insn.o inat.o
obj-y += msr.o msr-reg.o msr-reg-export.o
+obj-$(CONFIG_X86_USE_SSE) += oword_io.o
ifeq ($(CONFIG_X86_32),y)
obj-y += atomic64_32.o
diff --git a/arch/x86/lib/oword_io.c b/arch/x86/lib/oword_io.c
new file mode 100644
index 0000000..8189bf3
--- /dev/null
+++ b/arch/x86/lib/oword_io.c
@@ -0,0 +1,65 @@
+/****************************************************************************
+ * 128-bit MMIO for x86
+ * Copyright 2012 Solarflare Communications Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation, incorporated herein by reference.
+ */
+
+#include <linux/export.h>
+#include <linux/preempt.h>
+#include <linux/types.h>
+#include <asm/io.h>
+
+/*
+ * We copy the data between a memory buffer and the MMIO address via
+ * register xmm0. We have to save and restore the SSE state, and
+ * disable preemption. Only the MMIO address is required to be
+ * 128-bit aligned, since the stack generally is not.
+ */
+
+u128 reado(const volatile void __iomem *addr)
+{
+ u128 ret;
+ u64 cr0;
+ u128 xmm0;
+
+ preempt_disable();
+ asm volatile (
+ "movq %%cr0,%0\n\t"
+ "clts\n\t"
+ "movups %%xmm0,%1\n\t"
+ "movaps %3,%%xmm0\n\t"
+ "movups %%xmm0,%2\n\t"
+ "sfence\n\t"
+ "movups %1,%%xmm0\n\t"
+ "movq %0,%%cr0\n\t"
+ : "=r"(cr0), "=m"(xmm0), "=m"(ret)
+ : "m"(*(const volatile u128 __iomem *)addr));
+ preempt_enable();
+
+ return ret;
+}
+EXPORT_SYMBOL(reado);
+
+void writeo(u128 val, volatile void __iomem *addr)
+{
+ u64 cr0;
+ u128 xmm0;
+
+ preempt_disable();
+ asm volatile (
+ "movq %%cr0,%0\n\t"
+ "clts\n\t"
+ "movups %%xmm0,%1\n\t"
+ "movups %3,%%xmm0\n\t"
+ "movaps %%xmm0,%2\n\t"
+ "sfence\n\t"
+ "movups %1,%%xmm0\n\t"
+ "movq %0,%%cr0\n\t"
+ : "=r"(cr0), "=m"(xmm0), "=m"(*(volatile u128 __iomem *)addr)
+ : "m"(val));
+ preempt_enable();
+}
+EXPORT_SYMBOL(writeo);
--
1.7.7.6
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply related
* [PATCH 1/3] x86_64: Define 128-bit types for kernel code only
From: Ben Hutchings @ 2012-08-22 1:20 UTC (permalink / raw)
To: Thomas Gleixner, Ingo Molnar, H. Peter Anvin
Cc: netdev, linux-net-drivers, x86
In-Reply-To: <1345598275.2659.71.camel@bwh-desktop.uk.solarflarecom.com>
These types will initially be used for 128-bit I/O operations.
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
I'm not sure whether there is any point in all the _t type aliases, but
they're defined for all the other explicit-width types.
Ben.
arch/x86/include/asm/types.h | 8 ++++++++
include/linux/types.h | 12 ++++++++++++
2 files changed, 20 insertions(+), 0 deletions(-)
diff --git a/arch/x86/include/asm/types.h b/arch/x86/include/asm/types.h
index 8e8c23f..0829082 100644
--- a/arch/x86/include/asm/types.h
+++ b/arch/x86/include/asm/types.h
@@ -3,4 +3,12 @@
#include <asm-generic/types.h>
+#ifdef __KERNEL__
+#if defined(CONFIG_X86_64) && !defined(__ASSEMBLY__) && !defined(_SETUP)
+#define HAVE_INT128
+typedef __int128 s128;
+typedef unsigned __int128 u128;
+#endif
+#endif
+
#endif /* _ASM_X86_TYPES_H */
diff --git a/include/linux/types.h b/include/linux/types.h
index 9c1bd53..46e67ad 100644
--- a/include/linux/types.h
+++ b/include/linux/types.h
@@ -127,6 +127,12 @@ typedef __s64 int64_t;
#define aligned_be64 __be64 __attribute__((aligned(8)))
#define aligned_le64 __le64 __attribute__((aligned(8)))
+#ifdef HAVE_INT128
+typedef u128 u_int128_t;
+typedef u128 uint128_t;
+typedef s128 int128_t;
+#endif
+
/**
* The type used for indexing onto a disc or disc partition.
*
@@ -199,6 +205,12 @@ typedef __u32 __bitwise __wsum;
#define __aligned_le64 __le64 __attribute__((aligned(8)))
#ifdef __KERNEL__
+
+#ifdef HAVE_INT128
+typedef u128 __bitwise __le128;
+typedef u128 __bitwise __be128;
+#endif
+
typedef unsigned __bitwise__ gfp_t;
typedef unsigned __bitwise__ fmode_t;
--
1.7.7.6
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply related
* [PATCH 0/3] x86_64, sfc: 128-bit memory-mapped I/O
From: Ben Hutchings @ 2012-08-22 1:17 UTC (permalink / raw)
To: Thomas Gleixner, Ingo Molnar, H. Peter Anvin
Cc: netdev, linux-net-drivers, x86
Current Solarflare network controllers have 128-bit memory-mapped
registers which are normally accessed through a series of I/O
operations. However, it is also possible to access them with a single
MOVAPS instruction on x86_64, and this is measurably faster as it
requires only one PCIe transaction.
This series introduces reado(), writeo() and the corresponding raw
operations on x86_64. These could also be implemented on i386 with an
appropriate CPU selection, but it would require u128 etc. to be defined
as structure types.
The sfc driver can potentially take advantage of both 128-bit reads and
writes, but as a first step this changes only one particular write that
may be done on the data path.
Ben.
Ben Hutchings (3):
x86_64: Define 128-bit types for kernel code only
x86_64: Define 128-bit memory-mapped I/O operations
sfc: Use __raw_writeo() to perform TX descriptor push where possible
arch/x86/Kconfig.cpu | 4 ++
arch/x86/include/asm/io.h | 14 +++++++
arch/x86/include/asm/types.h | 8 ++++
arch/x86/lib/Makefile | 1 +
arch/x86/lib/oword_io.c | 65 +++++++++++++++++++++++++++++++++++
drivers/net/ethernet/sfc/bitfield.h | 3 ++
drivers/net/ethernet/sfc/io.h | 18 ++++++++-
include/linux/types.h | 12 ++++++
8 files changed, 123 insertions(+), 2 deletions(-)
create mode 100644 arch/x86/lib/oword_io.c
--
1.7.7.6
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply
* Re: [GIT] Networking
From: Al Viro @ 2012-08-22 0:08 UTC (permalink / raw)
To: David Miller; +Cc: torvalds, akpm, netdev, linux-kernel
In-Reply-To: <20120821.163823.1448570709635488157.davem@davemloft.net>
On Tue, Aug 21, 2012 at 04:38:23PM -0700, David Miller wrote:
> 8) Fix all the netprio file handling bugs found by Al Viro, from John
> Fastabend.
Great, I was just about to start figuring out how to deal with inter-tree
dependencies; now I'll just rebase my internal queue ;-) (I've added
iterate_fd(files, from, callback) that goes through the descriptor
table starting at given fd, calling the non-blocking callback for files in
there until the callback returns 0; that kills open-coded loops of that
kind in tty_io and netprio, as well as most of the crap in selinux
flush_unauthorized_files(); for now I just have a copy of John's patch
in my tree, but if it's about to go into the mainline - great, less
potential PITA for me).
^ permalink raw reply
* [GIT] Networking
From: David Miller @ 2012-08-21 23:38 UTC (permalink / raw)
To: torvalds; +Cc: akpm, netdev, linux-kernel
A couple weeks of bug fixing in there. The largest chunk is all the
broken crap Amerigo Wang found in the netpoll layer.
1) netpoll and it's users has several serious bugs:
a) uses GFP_KERNEL with locks held
b) interfaces requiring interrupts disabled are called with them
enabled
c) and vice versa
d) VLAN tag demuxing, as per all other RX packet input paths, is
not applied
All from Amerigo Wang.
2) Hopefully cure the ipv4 mapped ipv6 address TCP early demux bugs
for good, from Neal Cardwell.
3) Unlike AF_UNIX, AF_PACKET sockets don't set a default credentials
when the user doesn't specify one explicitly during sendmsg().
Instead we attach an empty (zero) SCM credential block which
is definitely not what we want. Fix from Eric Dumazet.
4) IPv6 illegally invokes netdevice notifiers with RCU lock held, fix
from Ben Hutchings.
5) inet_csk_route_child_sock() checks wrong inet options pointer, fix
from Christoph Paasch.
6) When AF_PACKET is used for transmit, packet loopback doesn't behave
properly when a socket fanout is enabled, from Eric Leblond.
7) On bluetooth l2cap channel create failure, we leak the socket, from
Jaganath Kanakkassery.
8) Fix all the netprio file handling bugs found by Al Viro, from John
Fastabend.
9) Several error return and NULL deref bug fixes in networking drivers
from Julia Lawall.
10) A large smattering of struct padding et al. kernel memory leaks
to userspace found of Mathias Krause.
11) Conntrack expections in netfilter can access an uninitialized timer,
fix from Pablo Neira Ayuso.
12) Several netfilter SIP tracker bug fixes from Patrick McHardy.
13) IPSEC ipv6 routes are not initialized correctly all the time,
resulting in an OOPS in inet_putpeer(). Also from Patrick
McHardy.
14) Bridging does rcu_dereference() outside of RCU protected area,
from Stephen Hemminger.
15) Fix routing cache removal performance regression when looking up
output routes that have a local destination. From Zheng Yan.
Please pull, thanks a lot!
The following changes since commit ddf343f635fe4440cad528e12f96f28bd50aa099:
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux (2012-08-14 07:58:59 +0300)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/davem/net.git master
for you to fetch changes up to e0e3cea46d31d23dc40df0a49a7a2c04fe8edfea:
af_netlink: force credentials passing [CVE-2012-3520] (2012-08-21 14:53:01 -0700)
----------------------------------------------------------------
Alexey Khoroshilov (1):
rndis_wlan: Fix potential memory leak in update_pmkid()
Amerigo Wang (15):
netpoll: use GFP_ATOMIC in slave_enable_netpoll() and __netpoll_setup()
netpoll: make __netpoll_cleanup non-block
netconsole: do not release spin_lock when calling __netpoll_cleanup
netpoll: take rcu_read_lock_bh() in netpoll_rx()
netpoll: use netpoll_rx_on() in netpoll_rx()
netpoll: take rcu_read_lock_bh() in netpoll_send_skb_on_dev()
bridge: add some comments for NETDEV_RELEASE
bridge: use list_for_each_entry() in netpoll functions
netpoll: check netpoll tx status on the right device
netpoll: convert several functions to bool
vlan: clean up some variable names
vlan: clean up vlan_dev_hard_start_xmit()
netpoll: handle vlan tags in netpoll tx and rx path
netpoll: re-enable irq in poll_napi()
netconsole: remove a redundant netconsole_target_put()
Andrei Emeltchenko (1):
Bluetooth: smp: Fix possible NULL dereference
Ben Hutchings (4):
llc2: Fix silent failure of llc_station_init()
llc2: Call llc_station_exit() on llc2_init() failure path
llc: Fix races between llc2 handler use and (un)registration
ipv6: addrconf: Avoid calling netdevice notifiers with RCU read-side lock
Bjørn Mork (5):
net: qmi_wwan: use fixed interface number matching
net: qmi_wwan: add Sierra Wireless devices
net: qmi_wwan: compress device_id list using macros
net: sierra_net: replace whitelist with ifnumber match
net: qmi_wwan: new devices: UML290 and K5006-Z
Bob Copeland (1):
ath5k: fix spin_lock_irqsave/spin_lock_bh nesting in mesh
Christoph Paasch (1):
ipv4: Use newinet->inet_opt in inet_csk_route_child_sock()
Dan Carpenter (1):
wireless: at76c50x: signedness bug in at76_dfu_get_state()
David S. Miller (2):
Merge branch 'for-davem' of git://git.kernel.org/.../linville/wireless
Merge git://1984.lsi.us.es/nf
Dirk Gouders (1):
netconsole.txt: revision of examples for the receiver of kernel messages
Eric Dumazet (3):
tcp: fix possible socket refcount problem
ipv4: fix ip header ident selection in __ip_make_skb()
af_netlink: force credentials passing [CVE-2012-3520]
Eric Leblond (1):
af_packet: don't emit packet on orig fanout group
Felix Fietkau (1):
ath9k: fix interrupt storms on queued hardware reset
Gustavo Padovan (1):
Bluetooth: Fix possible deadlock in SCO code
Igor Maravic (1):
net: ipv6: proc: Fix error handling
Jaganath Kanakkassery (1):
Bluetooth: Fix socket not getting freed if l2cap channel create fails
Jason Wang (1):
act_mirred: do not drop packets when fails to mirror it
Jesper Juhl (1):
caif: Do not dereference NULL in chnl_recv_cb()
John Fastabend (3):
net: netprio: fix files lock and remove useless d_path bits
net: netprio: fd passed in SCM_RIGHTS datagram not set correctly
net: netprio: fix cgrp create and write priomap race
John W. Linville (2):
Merge branch 'master' of git://git.kernel.org/.../bluetooth/bluetooth
Merge branch 'master' of git://git.kernel.org/.../linville/wireless into for-davem
Julia Lawall (6):
drivers/net/ethernet/ti/davinci_cpdma.c: Remove potential NULL dereference
drivers/net/ethernet/freescale/fs_enet: fix error return code
drivers/net/ethernet/mellanox/mlx4/mcg.c: fix error return code
drivers/net/wimax/i2400m/fw.c: fix error return code
drivers/net/wan/dscc4.c: fix error return code
drivers/net/irda: fix error return code
Kelvin Cheung (1):
net/stmmac: fix issue of clk_get for Loongson1B.
Lorenzo Bianconi (1):
ath9k: fix decrypt_error initialization in ath_rx_tasklet()
Manoj Iyer (1):
Bluetooth: btusb: Add vendor specific ID (0a5c:21f4) BCM20702A0
Mathias Krause (14):
atm: fix info leak in getsockopt(SO_ATMPVC)
atm: fix info leak via getsockname()
Bluetooth: HCI - Fix info leak in getsockopt(HCI_FILTER)
Bluetooth: HCI - Fix info leak via getsockname()
Bluetooth: RFCOMM - Fix info leak in getsockopt(BT_SECURITY)
Bluetooth: RFCOMM - Fix info leak in ioctl(RFCOMMGETDEVLIST)
Bluetooth: RFCOMM - Fix info leak via getsockname()
Bluetooth: L2CAP - Fix info leak via getsockname()
l2tp: fix info leak via getsockname()
llc: fix info leak via getsockname()
dccp: check ccid before dereferencing
dccp: fix info leak via getsockopt(DCCP_SOCKOPT_CCID_TX_INFO)
ipvs: fix info leak in getsockopt(IP_VS_SO_GET_TIMEOUT)
net: fix info leak in compat dev_ifconf()
Neal Cardwell (1):
net: tcp: move sk_rx_dst_set call after tcp_create_openreq_child()
Pablo Neira Ayuso (2):
netfilter: ctnetlink: fix missing locking while changing conntrack from nfqueue
netfilter: nf_ct_expect: fix possible access to uninitialized timer
Patrick McHardy (4):
netfilter: nf_ct_sip: fix helper name
netfilter: nf_ct_sip: fix IPv6 address parsing
netfilter: nf_nat_sip: fix via header translation with multiple parameters
net: ipv6: fix oops in inet_putpeer()
Peng Chen (1):
Bluetooth: add support for atheros 0489:e057
Phil Edworthy (1):
net: sh_eth: Add eth support for R8A7779 device
Rajkumar Manoharan (1):
ath9k: stop btcoex on device suspend
Ram Malovany (3):
Bluetooth: Fix using NULL inquiry entry
Bluetooth: Fix using a NULL inquiry cache entry
Bluetooth: Set name_state to unknown when entry name is empty
Randy Dunlap (1):
net/core/dev.c: fix kernel-doc warning
Stephen Hemminger (1):
bridge: fix rcu dereference outside of rcu_read_lock
Steve Glendinning (1):
smsc75xx: add missing entry to MAINTAINERS
Steve Hodgson (1):
vmxnet3: Fix race between dev_open() and register_netdev()
Szymon Janc (1):
Bluetooth: Fix legacy pairing with some devices
Timur Tabi (2):
dt: introduce for_each_available_child_of_node, of_get_next_available_child
netdev/phy: skip disabled mdio-mux nodes
Yan, Zheng (1):
ipv4: Cache local output routes
Documentation/networking/netconsole.txt | 19 +++-
MAINTAINERS | 6 ++
drivers/bluetooth/ath3k.c | 2 +
drivers/bluetooth/btusb.c | 2 +
drivers/net/bonding/bond_main.c | 12 ++-
drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c | 4 +-
drivers/net/ethernet/freescale/fs_enet/mii-fec.c | 8 +-
drivers/net/ethernet/mellanox/mlx4/mcg.c | 4 +-
drivers/net/ethernet/renesas/Kconfig | 4 +-
drivers/net/ethernet/renesas/sh_eth.c | 11 ++-
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 2 +-
drivers/net/ethernet/ti/davinci_cpdma.c | 3 +-
drivers/net/irda/ks959-sir.c | 1 +
drivers/net/irda/ksdazzle-sir.c | 1 +
drivers/net/netconsole.c | 6 --
drivers/net/phy/mdio-mux.c | 2 +-
drivers/net/team/team.c | 16 ++--
drivers/net/usb/qmi_wwan.c | 251 +++++++++-------------------------------------------
drivers/net/usb/sierra_net.c | 52 +++--------
drivers/net/vmxnet3/vmxnet3_drv.c | 2 +-
drivers/net/wan/dscc4.c | 5 +-
drivers/net/wimax/i2400m/fw.c | 4 +-
drivers/net/wireless/at76c50x-usb.c | 2 +-
drivers/net/wireless/ath/ath5k/base.c | 6 +-
drivers/net/wireless/ath/ath5k/mac80211-ops.c | 5 +-
drivers/net/wireless/ath/ath9k/mac.c | 18 ++--
drivers/net/wireless/ath/ath9k/mac.h | 1 +
drivers/net/wireless/ath/ath9k/main.c | 4 +-
drivers/net/wireless/ath/ath9k/pci.c | 1 +
drivers/net/wireless/ath/ath9k/recv.c | 2 +-
drivers/net/wireless/rndis_wlan.c | 6 +-
drivers/of/base.c | 27 ++++++
include/linux/if_team.h | 30 +++----
include/linux/netdevice.h | 5 +-
include/linux/netfilter/nf_conntrack_sip.h | 2 +-
include/linux/netpoll.h | 42 +++++----
include/linux/of.h | 7 ++
include/net/llc.h | 2 +-
include/net/scm.h | 4 +-
include/net/xfrm.h | 2 +
net/8021q/vlan_dev.c | 52 ++++++-----
net/atm/common.c | 1 +
net/atm/pvc.c | 1 +
net/bluetooth/hci_event.c | 28 ++++--
net/bluetooth/hci_sock.c | 2 +
net/bluetooth/l2cap_core.c | 1 +
net/bluetooth/l2cap_sock.c | 3 +-
net/bluetooth/rfcomm/sock.c | 2 +
net/bluetooth/rfcomm/tty.c | 2 +-
net/bluetooth/sco.c | 19 ++--
net/bluetooth/smp.c | 5 +-
net/bridge/br_device.c | 30 +++----
net/bridge/br_forward.c | 2 +-
net/bridge/br_if.c | 6 +-
net/bridge/br_private.h | 4 +-
net/caif/chnl_net.c | 4 +
net/core/dev.c | 17 +++-
net/core/netpoll.c | 109 ++++++++++++++++-------
net/core/netprio_cgroup.c | 30 ++-----
net/core/scm.c | 4 +
net/dccp/ccid.h | 4 +-
net/dccp/ccids/ccid3.c | 1 +
net/ipv4/inet_connection_sock.c | 7 +-
net/ipv4/ip_output.c | 2 +-
net/ipv4/netfilter/nf_nat_sip.c | 9 +-
net/ipv4/route.c | 1 -
net/ipv4/tcp_ipv4.c | 9 +-
net/ipv4/tcp_minisocks.c | 2 -
net/ipv4/tcp_output.c | 14 +--
net/ipv4/tcp_timer.c | 6 +-
net/ipv6/addrconf.c | 4 +-
net/ipv6/proc.c | 4 +-
net/ipv6/tcp_ipv6.c | 25 +++---
net/ipv6/xfrm6_policy.c | 8 ++
net/l2tp/l2tp_ip6.c | 1 +
net/llc/af_llc.c | 8 +-
net/llc/llc_input.c | 21 ++++-
net/llc/llc_station.c | 23 +----
net/netfilter/ipvs/ip_vs_ctl.c | 1 +
net/netfilter/nf_conntrack_expect.c | 29 ++----
net/netfilter/nf_conntrack_netlink.c | 7 +-
net/netfilter/nf_conntrack_sip.c | 92 ++++++++++++++-----
net/netlink/af_netlink.c | 2 +-
net/packet/af_packet.c | 9 ++
net/sched/act_mirred.c | 11 ++-
net/socket.c | 1 +
net/unix/af_unix.c | 4 +-
net/xfrm/xfrm_policy.c | 2 +
88 files changed, 637 insertions(+), 575 deletions(-)
^ permalink raw reply
* [PATCH 1/1] tcp: Wrong timeout for SYN segments
From: Alex Bergmann @ 2012-08-21 23:29 UTC (permalink / raw)
To: davem; +Cc: netdev, linux-kernel
Hi David,
I'm not 100% sure, but it looks like I found an RFC mismatch with the
current default values of the TCP implementation.
Alex
>From 8b854a525eb45f64ad29dfab16f9d9f681e84495 Mon Sep 17 00:00:00 2001
From: Alexander Bergmann <alex@linlab.net>
Date: Wed, 22 Aug 2012 00:29:08 +0200
Subject: [PATCH 1/1] tcp: Wrong timeout for SYN segments
Commit 9ad7c049 changed the initRTO from 3secs to 1sec in accordance to
RFC6298 (former RFC2988bis). This introduced a gap with RFC1122 that
defines a minimum retransmission window for SYN segments of at least
180secs.
Prior to 9ad7c049 the timeout was defined with 189secs. Now we have only
a timeout of 63secs.
((2 << 5) - 1) * 3 secs = 189 secs
((2 << 5) - 1) * 1 secs = 63 secs
To fulfill the MUST constraint in RFC1122 section 4.2.3.5 about R2 for
SYN segments, the values of TCP_SYN_RETRIES and TCP_SYNACK_RETRIES must
be changed to 7 reties.
((2 << 7) - 1) * 1 secs = 255 secs
This would result in an ETIMEDOUT of 4 minutes 15 seconds.
Signed-off-by: Alexander Bergmann <alex@linlab.net>
---
include/net/tcp.h | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 1f000ff..7eaae19 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -98,10 +98,10 @@ extern void tcp_time_wait(struct sock *sk, int state, int timeo);
* 15 is ~13-30min depending on RTO.
*/
-#define TCP_SYN_RETRIES 5 /* number of times to retry active opening a
+#define TCP_SYN_RETRIES 7 /* number of times to retry active opening a
* connection: ~180sec is RFC minimum */
-#define TCP_SYNACK_RETRIES 5 /* number of times to retry passive opening a
+#define TCP_SYNACK_RETRIES 7 /* number of times to retry passive opening a
* connection: ~180sec is RFC minimum */
#define TCP_TIMEWAIT_LEN (60*HZ) /* how long to wait to destroy TIME-WAIT
--
1.7.8.6
^ permalink raw reply related
* Re: [PATCH v6] bonding support for IPv6 transmit hashing
From: John Eaglesham @ 2012-08-21 22:21 UTC (permalink / raw)
To: Jay Vosburgh; +Cc: Jeremy Brookman, netdev
In-Reply-To: <11100.1345576795@death.nxdomain>
On 8/21/2012 12:19 PM, Jay Vosburgh wrote:
> Jeremy Brookman <jeremy.brookman@gmail.com> wrote:
>
>>> You should use a mix of tabs, as necessary, to get things to line up
>>> how I told you they need to line up.
>>
>> Unless I'm missing something, this change doesn't seem to have made it
>> through to the kernel tip, but we could really use this bugfix. Is it
>> in a repository I didn't notice, or not yet through the review? If
>> it's not through the review, is any help needed to get it there?
>
> The submitter (John Eaglesham) never posted an updated version
> that addressed the various comments, nor did his original patch
> submission include a Signed-off-by.
>
> I went ahead and updated the patch to address the comments; I've
> only compile tested this. Are you (Jeremy or John) able to test this to
> confirm that it will hash ipv6 traffic as expected (I can test it, but
> it won't be today)?
>
> John, can you post a Signed-off-by for your patch (really, this
> updated version of your patch)?
>
> If John signs off and somebody tests this, I'll post a formal
> submssion with the full commit message.
>
> -J
>
Since my last submission I ended up making some changes on my end to
streamline the logic. I can fold together my patch with yours and test
them later tonight. If everything looks good I'll post the changes back
to the list.
Thanks!
John
^ permalink raw reply
* Re: [PATCH 05/19] netfilter: nf_conntrack_ipv6: improve fragmentation handling
From: Jesper Dangaard Brouer @ 2012-08-21 22:21 UTC (permalink / raw)
To: Patrick McHardy
Cc: netfilter-devel, netdev, Julian Anastasov, Hans Schillstrom,
Hans Schillstrom
In-Reply-To: <Pine.GSO.4.63.1208192141570.3016@stinky-local.trash.net>
On Sun, 2012-08-19 at 21:44 +0200, Patrick McHardy wrote:
> On Sun, 19 Aug 2012, Jesper Dangaard Brouer wrote:
> > On Sat, 2012-08-18 at 14:26 +0200, Patrick McHardy wrote:
[...]
> > Don't I need to load some of the helper modules, or just the
> > nf_conntrack_ipv6 module, or perhaps only nf_defrag_ipv6 ?
>
> Not with the entire patchset, just IPv6 conntrack is enough. Aith IPv6 NAT
> the first packet of a connection must always be defragemented, independant
> of an assigned helper.
When loading "nf_conntrack_ipv6" I run into issues.
When sending a fragmented UDP packet. With these patches, the IPVS
stack will no longer see the fragmented packets, but instead see one
large SKB. This will trigger a MTU path check in e.g.
ip_vs_dr_xmit_v6() and an ICMPv6 too big packet is send back.
IPVS: ip_vs_dr_xmit_v6(): frag needed
Perhaps we could change/fix the MTU check in IPVS?
(This would also solve issues I've seen with TSO/GSO frames, hitting
this code path).
--
Best regards,
Jesper Dangaard Brouer
MSc.CS, Sr. Network Kernel Developer at Red Hat
Author of http://www.iptv-analyzer.org
LinkedIn: http://www.linkedin.com/in/brouer
^ permalink raw reply
* Re: [PATCH] af_netlink: force credentials passing [CVE-2012-3520]
From: David Miller @ 2012-08-21 21:53 UTC (permalink / raw)
To: eric.dumazet; +Cc: netdev, pmatouse, fweimer, pablo
In-Reply-To: <1345566077.5158.530.camel@edumazet-glaptop>
From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Tue, 21 Aug 2012 18:21:17 +0200
> From: Eric Dumazet <edumazet@google.com>
>
> Pablo Neira Ayuso discovered that avahi and
> potentially NetworkManager accept spoofed Netlink messages because of a
> kernel bug. The kernel passes all-zero SCM_CREDENTIALS ancillary data
> to the receiver if the sender did not provide such data, instead of not
> including any such data at all or including the correct data from the
> peer (as it is the case with AF_UNIX).
>
> This bug was introduced in commit 16e572626961
> (af_unix: dont send SCM_CREDENTIALS by default)
>
> This patch forces passing credentials for netlink, as
> before the regression.
>
> Another fix would be to not add SCM_CREDENTIALS in
> netlink messages if not provided by the sender, but it
> might break some programs.
>
> With help from Florian Weimer & Petr Matousek
>
> This issue is designated as CVE-2012-3520
>
> Signed-off-by: Eric Dumazet <edumazet@google.com>
Applied and queued up for -stable, thanks Eric.
^ permalink raw reply
* Re: Bug with IPv6-UDP address binding
From: Jesper Dangaard Brouer @ 2012-08-21 21:51 UTC (permalink / raw)
To: Eric Dumazet; +Cc: netdev, Thomas Graf
In-Reply-To: <1344512634.28967.732.camel@edumazet-glaptop>
On Thu, 2012-08-09 at 13:43 +0200, Eric Dumazet wrote:
> Here is an IPv4 sample UDP application, able to echo packets with the IP
> source set to original DST address of the ping packet.
>
> Doing the same on IPv6 is probably trivial as well
I have implemented a combined IPv6 + IPv4 version of the udp echo code,
and placed it on github here:
https://github.com/netoptimizer/network-testing/blob/master/src/udp_echo.c
Comments and patches are welcome ;-)
> #include <sys/types.h>
> #include <sys/socket.h>
> #include <netinet/in.h>
> #include <linux/udp.h>
> #include <string.h>
> #include <stdio.h>
> #include <unistd.h>
> #include <arpa/inet.h>
>
> #define PORT 4040
>
> int pktinfo_get(struct msghdr *my_hdr, struct in_pktinfo *pktinfo)
> {
> int res = -1;
>
> if (my_hdr->msg_controllen > 0) {
> struct cmsghdr *get_cmsg;
> for (get_cmsg = CMSG_FIRSTHDR(my_hdr); get_cmsg;
> get_cmsg = CMSG_NXTHDR(my_hdr, get_cmsg)) {
> if (get_cmsg->cmsg_type == IP_PKTINFO) {
> struct in_pktinfo *get_pktinfo = (struct in_pktinfo *)CMSG_DATA(get_cmsg);
> memcpy(pktinfo, get_pktinfo, sizeof(*pktinfo));
> res = 0;
> }
> }
> }
> return res;
> }
>
> int main(int argc, char *argv[])
> {
> int fd = socket(AF_INET, SOCK_DGRAM, 0);
> struct sockaddr_in addr, rem_addr;
> int res, on = 1;
> struct msghdr msghdr;
> struct iovec vec[1];
> char cbuf[512];
> char frame[4096];
> struct in_pktinfo pktinfo;
> int c, count = 1000000;
>
> while ((c = getopt(argc, argv, "c:")) != -1) {
> if (c == 'c') count = atoi(optarg);
> }
> memset(&addr, 0, sizeof(addr));
> addr.sin_family = AF_INET;
> addr.sin_port = htons(PORT);
> if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
> perror("bind");
> return 1;
> }
> setsockopt(fd, SOL_IP, IP_PKTINFO, &on, sizeof(on));
>
> while (1) {
> memset(&msghdr, 0, sizeof(msghdr));
> msghdr.msg_control = cbuf;
> msghdr.msg_controllen = sizeof(cbuf);
> msghdr.msg_iov = vec;
> msghdr.msg_iovlen = 1;
> vec[0].iov_base = frame;
> vec[0].iov_len = sizeof(frame);
> msghdr.msg_name = &rem_addr;
> msghdr.msg_namelen = sizeof(rem_addr);
> res = recvmsg(fd, &msghdr, 0);
> if (res == -1)
> break;
> if (pktinfo_get(&msghdr, &pktinfo) == 0)
> printf("Got IP_PKTINFO dst addr=%s\n", inet_ntoa(pktinfo.ipi_spec_dst));
>
> /* ok, just echo reply this frame.
> * Using sendmsg() will provide IP_PKTINFO back to kernel
> * to let it use the 'right' source address
> * (destination address of the incoming packet)
> */
> vec[0].iov_len = res;
> sendmsg(fd, &msghdr, 0);
> if (--count == 0)
> break;
> }
> return 0;
> }
>
>
^ permalink raw reply
* Re: [PATCH] ipv4: fix ip header ident selection in __ip_make_skb()
From: David Miller @ 2012-08-21 21:51 UTC (permalink / raw)
To: eric.dumazet; +Cc: netdev, shemminger, casteyde.christian
In-Reply-To: <1345483605.5158.345.camel@edumazet-glaptop>
From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Mon, 20 Aug 2012 19:26:45 +0200
> From: Eric Dumazet <edumazet@google.com>
>
> Christian Casteyde reported a kmemcheck 32-bit read from uninitialized
> memory in __ip_select_ident().
>
> It turns out that __ip_make_skb() called ip_select_ident() before
> properly initializing iph->daddr.
>
> This is a bug uncovered by commit 1d861aa4b3fb (inet: Minimize use of
> cached route inetpeer.)
>
> Addresses https://bugzilla.kernel.org/show_bug.cgi?id=46131
>
> Reported-by: Christian Casteyde <casteyde.christian@free.fr>
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> Cc: Stephen Hemminger <shemminger@vyatta.com>
Applied, thanks Eric.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox