From: "Theodore Ts'o" <tytso@mit.edu> Based on reports from Ingo's Latency Tracer that the TCP sequence number rekey code is causing latency problems, I've moved the sequence number rekey to be done out of a workqueue. Signed-off-by: Andrew Morton <akpm@osdl.org> --- 25-akpm/drivers/char/random.c | 27 ++++++++++++++++----------- 1 files changed, 16 insertions(+), 11 deletions(-) diff -puN drivers/char/random.c~dev-random-fix-latency-in-rekeying-sequence-number drivers/char/random.c --- 25/drivers/char/random.c~dev-random-fix-latency-in-rekeying-sequence-number 2004-08-19 23:36:12.632791416 -0700 +++ 25-akpm/drivers/char/random.c 2004-08-19 23:36:12.637790656 -0700 @@ -2240,30 +2240,35 @@ static struct keydata { static spinlock_t ip_lock = SPIN_LOCK_UNLOCKED; static unsigned int ip_cnt; -static struct keydata *__check_and_rekey(time_t time) +static void rekey_seq_generator(void *private_) { struct keydata *keyptr; + struct timeval tv; + + do_gettimeofday(&tv); + spin_lock_bh(&ip_lock); keyptr = &ip_keydata[ip_cnt&1]; - if (!keyptr->rekey_time || (time - keyptr->rekey_time) > REKEY_INTERVAL) { - keyptr = &ip_keydata[1^(ip_cnt&1)]; - keyptr->rekey_time = time; - get_random_bytes(keyptr->secret, sizeof(keyptr->secret)); - keyptr->count = (ip_cnt&COUNT_MASK)<<HASH_BITS; - mb(); - ip_cnt++; - } + + keyptr = &ip_keydata[1^(ip_cnt&1)]; + keyptr->rekey_time = tv.tv_sec; + get_random_bytes(keyptr->secret, sizeof(keyptr->secret)); + keyptr->count = (ip_cnt&COUNT_MASK)<<HASH_BITS; + mb(); + ip_cnt++; + spin_unlock_bh(&ip_lock); - return keyptr; } +static DECLARE_WORK(rekey_work, rekey_seq_generator, NULL); + static inline struct keydata *check_and_rekey(time_t time) { struct keydata *keyptr = &ip_keydata[ip_cnt&1]; rmb(); if (!keyptr->rekey_time || (time - keyptr->rekey_time) > REKEY_INTERVAL) { - keyptr = __check_and_rekey(time); + schedule_work(&rekey_work); } return keyptr; _