From patchwork Wed May 25 04:14:04 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 9134695 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 352F86075C for ; Wed, 25 May 2016 04:14:28 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 29ACC28214 for ; Wed, 25 May 2016 04:14:28 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1B9D62825C; Wed, 25 May 2016 04:14:28 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B9F8728214 for ; Wed, 25 May 2016 04:14:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1750920AbcEYEOY (ORCPT ); Wed, 25 May 2016 00:14:24 -0400 Received: from cn.fujitsu.com ([222.73.24.84]:16327 "EHLO song.cn.fujitsu.com" rhost-flags-OK-FAIL-OK-OK) by vger.kernel.org with ESMTP id S1750856AbcEYEOX (ORCPT ); Wed, 25 May 2016 00:14:23 -0400 X-IronPort-AV: E=Sophos;i="5.20,367,1444665600"; d="scan'208";a="500362" Received: from unknown (HELO cn.fujitsu.com) ([10.167.250.3]) by song.cn.fujitsu.com with ESMTP; 25 May 2016 12:14:11 +0800 Received: from adam-work.localdomain (unknown [10.167.226.34]) by cn.fujitsu.com (Postfix) with ESMTP id 1C2384056403; Wed, 25 May 2016 12:14:06 +0800 (CST) From: Qu Wenruo To: linux-btrfs@vger.kernel.org Cc: dsterba@suse.cz Subject: [PATCH 1/2] btrfs-progs: utils: Introduce new pseudo random API Date: Wed, 25 May 2016 12:14:04 +0800 Message-Id: <1464149645-4308-1-git-send-email-quwenruo@cn.fujitsu.com> X-Mailer: git-send-email 2.8.2 MIME-Version: 1.0 X-yoursite-MailScanner-ID: 1C2384056403.A8FE9 X-yoursite-MailScanner: Found to be clean X-yoursite-MailScanner-From: quwenruo@cn.fujitsu.com Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP David has reported some quite chaos usage of pseudo random numbers. Like using static srand seed, or even calling rand() without setting seed correctly. The new pseudo random API will initialize the random seed on its first calling and use uniformly distributed pseudo random number generator as backend. Signed-off-by: Qu Wenruo --- utils.c | 36 ++++++++++++++++++++++++++++++++++++ utils.h | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/utils.c b/utils.c index 7761165..c0e860a 100644 --- a/utils.c +++ b/utils.c @@ -54,9 +54,11 @@ #define BLKDISCARD _IO(0x12,119) #endif +static int seed_initlized = 0; static int btrfs_scan_done = 0; static char argv0_buf[ARGV0_BUF_SIZE] = "btrfs"; +static unsigned short seeds[3]; const char *get_argv0_buf(void) { @@ -4051,3 +4053,37 @@ out: return ret; } + +void rand_seed(u64 seed) +{ + int i; + /* only use the last 48 bits */ + for (i = 0; i < 3; i++) { + seeds[i] = (unsigned short)(seed ^ (unsigned short)(-1)); + seed >>= 16; + } + seed_initlized = 1; +} + +u32 rand_u32(void) +{ + struct timeval tv; + + if (seed_initlized) + return nrand48(seeds); + + /* + * It's possible to use /dev/random, but we don't need that true + * random number nor want to wait for entropy, + * since we're only using random API to do corruption to test. + * Time and pid/ppid based seed would be good enough, and won't + * cause sleep for entropy pool. + */ + gettimeofday(&tv, 0); + seeds[0] = getpid() ^ (tv.tv_sec & 0xFFFF); + seeds[1] = getppid() ^ (tv.tv_usec & 0xFFFF); + seeds[2] = (tv.tv_sec ^ tv.tv_usec) >> 16; + seed_initlized = 1; + + return (u32)nrand48(seeds); +} diff --git a/utils.h b/utils.h index ebe6d61..0977262 100644 --- a/utils.h +++ b/utils.h @@ -362,4 +362,40 @@ static inline int error_on(int condition, const char *fmt, ...) return 1; } +/* pseudo random number generator wrappers */ +u32 rand_u32(void); + +static inline int rand_int(void) +{ + return (int)(rand_u32()); +} + +static inline u64 rand_u64(void) +{ + u64 ret = 0; + + ret += rand_u32(); + ret <<= 32; + ret += rand_u32(); + return ret; +} + +static inline u16 rand_u16(void) +{ + return (u16)(rand_u32()); +} + +static inline u8 rand_u8(void) +{ + return (u8)(rand_u32()); +} + +/* Return random number in range [0, limit) */ +static inline unsigned int rand_range(unsigned int up) +{ + return (unsigned int)(rand_u32() % up); +} + +/* Also allow setting seeds manually */ +void rand_seed(u64 seed); #endif