From 31e7f22cdc7c77ac7b48ba6a258ca9611063320a Mon Sep 17 00:00:00 2001 From: Patrick Farrell Date: Mon, 8 Dec 2014 22:26:28 -0600 Subject: [PATCH] LU-6081 user: use random() instead of /dev/urandom /dev/urandom gives good random numbers, but using it is very prone to error, and opening/closing the device every time a number is needed takes time. Instead, initializes the library with our seed by calling srandom(), and then use random(). Export a boolean variable liblustreapi_initialized to let applications check that the library was properly initialized by the loader. Signed-off-by: frank zago Signed-off-by: Henri Doreau Change-Id: Ie6ced0d39df29d7054919e239add58a23115ec35 Reviewed-on: http://review.whamcloud.com/13277 Tested-by: Jenkins Tested-by: Maloo Reviewed-by: Andreas Dilger Reviewed-by: James Simmons Reviewed-by: Oleg Drokin --- lustre/include/lustre/lustreapi.h | 3 ++ lustre/utils/Makefile.am | 2 +- lustre/utils/lfs.c | 51 ++++--------------------- lustre/utils/liblustreapi.c | 32 ++++++---------- lustre/utils/liblustreapi_util.c | 78 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 100 insertions(+), 66 deletions(-) create mode 100644 lustre/utils/liblustreapi_util.c diff --git a/lustre/include/lustre/lustreapi.h b/lustre/include/lustre/lustreapi.h index bfea291..6d2d512 100644 --- a/lustre/include/lustre/lustreapi.h +++ b/lustre/include/lustre/lustreapi.h @@ -46,6 +46,9 @@ #include #include +extern bool liblustreapi_initialized; + + typedef void (*llapi_cb_t)(char *obd_type_name, char *obd_name, char *obd_uuid, void *args); diff --git a/lustre/utils/Makefile.am b/lustre/utils/Makefile.am index 2a1482e..bbb6b6e 100644 --- a/lustre/utils/Makefile.am +++ b/lustre/utils/Makefile.am @@ -87,7 +87,7 @@ L_KERNELCOMM := $(top_builddir)/libcfs/libcfs/kernel_user_comm.c liblustreapitmp_a_SOURCES = liblustreapi.c liblustreapi_hsm.c \ liblustreapi_nodemap.c lustreapi_internal.h \ liblustreapi_json.c liblustreapi_layout.c \ - liblustreapi_lease.c \ + liblustreapi_lease.c liblustreapi_util.c \ $(L_IOCTL) $(L_KERNELCOMM) $(L_STRING) if UTILS diff --git a/lustre/utils/lfs.c b/lustre/utils/lfs.c index 3923ea0..3c41251 100644 --- a/lustre/utils/lfs.c +++ b/lustre/utils/lfs.c @@ -353,41 +353,6 @@ command_t cmdlist[] = { { 0, 0, 0, NULL } }; -/* Generate a random id for the grouplock */ -static int random_group_id(int *gid) -{ - int fd; - int rc; - size_t sz = sizeof(*gid); - - fd = open("/dev/urandom", O_RDONLY); - if (fd < 0) { - rc = -errno; - fprintf(stderr, "cannot open /dev/urandom: %s\n", - strerror(-rc)); - goto out; - } - -retry: - rc = read(fd, gid, sz); - if (rc < sz) { - rc = -errno; - fprintf(stderr, "cannot read %zu bytes from /dev/urandom: %s\n", - sz, strerror(-rc)); - goto out; - } - - /* gids must be non-zero */ - if (*gid == 0) - goto retry; - -out: - if (fd >= 0) - close(fd); - - return rc; -} - #define MIGRATION_BLOCKS 1 static int lfs_migrate(char *name, __u64 migration_flags, @@ -433,15 +398,6 @@ static int lfs_migrate(char *name, __u64 migration_flags, goto free; } - if (migration_flags & MIGRATION_BLOCKS) { - rc = random_group_id(&gid); - if (rc < 0) { - fprintf(stderr, "%s: cannot get random group ID: %s\n", - name, strerror(-rc)); - goto free; - } - } - /* search for file directory pathname */ if (strlen(name) > sizeof(parent)-1) { rc = -E2BIG; @@ -526,6 +482,9 @@ static int lfs_migrate(char *name, __u64 migration_flags, goto error; } + do + gid = random(); + while (gid == 0); if (migration_flags & MIGRATION_BLOCKS) { /* take group lock to limit concurent access * this will be no more needed when exclusive access will @@ -4070,6 +4029,10 @@ int main(int argc, char **argv) { int rc; + /* Ensure that liblustreapi constructor has run */ + if (!liblustreapi_initialized) + fprintf(stderr, "liblustreapi was not properly initialized\n"); + setlinebuf(stdout); Parser_init("lfs > ", cmdlist); diff --git a/lustre/utils/liblustreapi.c b/lustre/utils/liblustreapi.c index 3cd39ec..e74cf70 100644 --- a/lustre/utils/liblustreapi.c +++ b/lustre/utils/liblustreapi.c @@ -4683,29 +4683,16 @@ int llapi_create_volatile_idx(char *directory, int idx, int open_flags) char file_path[PATH_MAX]; char filename[PATH_MAX]; int fd; - int random; + int rnumber; int rc; - fd = open("/dev/urandom", O_RDONLY); - if (fd < 0) { - llapi_error(LLAPI_MSG_ERROR, errno, - "Cannot open /dev/urandom"); - return -errno; - } - rc = read(fd, &random, sizeof(random)); - close(fd); - if (rc < sizeof(random)) { - llapi_error(LLAPI_MSG_ERROR, errno, - "cannot read %zu bytes from /dev/urandom", - sizeof(random)); - return -errno; - } + rnumber = random(); if (idx == -1) snprintf(filename, sizeof(filename), - LUSTRE_VOLATILE_HDR"::%.4X", random); + LUSTRE_VOLATILE_HDR"::%.4X", rnumber); else snprintf(filename, sizeof(filename), - LUSTRE_VOLATILE_HDR":%.4X:%.4X", idx, random); + LUSTRE_VOLATILE_HDR":%.4X:%.4X", idx, rnumber); rc = snprintf(file_path, sizeof(file_path), "%s/%s", directory, filename); @@ -4736,13 +4723,16 @@ int llapi_create_volatile_idx(char *directory, int idx, int open_flags) */ int llapi_fswap_layouts(int fd1, int fd2, __u64 dv1, __u64 dv2, __u64 flags) { - struct lustre_swap_layouts lsl; - int rc; + struct lustre_swap_layouts lsl; + int rc; - srandom(time(NULL)); lsl.sl_fd = fd2; lsl.sl_flags = flags; - lsl.sl_gid = random(); + + do + lsl.sl_gid = random(); + while (lsl.sl_gid == 0); + lsl.sl_dv1 = dv1; lsl.sl_dv2 = dv2; rc = ioctl(fd1, LL_IOC_LOV_SWAP_LAYOUTS, &lsl); diff --git a/lustre/utils/liblustreapi_util.c b/lustre/utils/liblustreapi_util.c new file mode 100644 index 0000000..329f0e4 --- /dev/null +++ b/lustre/utils/liblustreapi_util.c @@ -0,0 +1,78 @@ +/* + * LGPL HEADER START + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * (C) Copyright (c) 2015, Cray Inc, all rights reserved. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser General Public License + * LGPL version 2.1 or (at your discretion) any later version. + * LGPL version 2.1 accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl-2.1.html + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * LGPL HEADER END + */ +/* + * lustre/utils/liblustreapi_util.c + * + * Misc LGPL-licenced utility functions for liblustreapi. + * + * Author: Frank Zago + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Indicate whether the liblustreapi_init() constructor below has run or not. + * + * This can be used by external programs to ensure if the initialization + * mechanism has actually worked. + */ +bool liblustreapi_initialized; + + +/* + * Initializes the library + */ +static __attribute__ ((constructor)) void liblustreapi_init(void) +{ + unsigned int seed; + struct timeval tv; + int fd; + + /* Initializes the random number generator (random()). Get + * data from different places in case one of them fails. This + * is enough to get reasonably random numbers, but is not + * strong enough to be used for cryptography. */ + seed = syscall(SYS_gettid); + + if (gettimeofday(&tv, NULL) == 0) { + seed ^= tv.tv_sec; + seed ^= tv.tv_usec; + } + + fd = open("/dev/urandom", O_RDONLY | O_NOFOLLOW); + if (fd >= 0) { + unsigned int rnumber; + + (void)read(fd, &rnumber, sizeof(rnumber)); + seed ^= rnumber; + close(fd); + } + + srandom(seed); + liblustreapi_initialized = true; +} -- 1.8.3.1