Whamcloud - gitweb
LU-6081 user: use random() instead of /dev/urandom 77/13277/12
authorPatrick Farrell <paf@cray.com>
Tue, 9 Dec 2014 04:26:28 +0000 (22:26 -0600)
committerOleg Drokin <oleg.drokin@intel.com>
Tue, 3 Feb 2015 18:00:01 +0000 (18:00 +0000)
/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 <fzago@cray.com>
Signed-off-by: Henri Doreau <henri.doreau@cea.fr>
Change-Id: Ie6ced0d39df29d7054919e239add58a23115ec35
Reviewed-on: http://review.whamcloud.com/13277
Tested-by: Jenkins
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Andreas Dilger <andreas.dilger@intel.com>
Reviewed-by: James Simmons <uja.ornl@gmail.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
lustre/include/lustre/lustreapi.h
lustre/utils/Makefile.am
lustre/utils/lfs.c
lustre/utils/liblustreapi.c
lustre/utils/liblustreapi_util.c [new file with mode: 0644]

index bfea291..6d2d512 100644 (file)
@@ -46,6 +46,9 @@
 #include <stdint.h>
 #include <lustre/lustre_user.h>
 
+extern bool liblustreapi_initialized;
+
+
 typedef void (*llapi_cb_t)(char *obd_type_name, char *obd_name, char *obd_uuid,
                           void *args);
 
index 2a1482e..bbb6b6e 100644 (file)
@@ -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
index 3923ea0..3c41251 100644 (file)
@@ -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);
index 3cd39ec..e74cf70 100644 (file)
@@ -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 (file)
index 0000000..329f0e4
--- /dev/null
@@ -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 <fzago@cray.com>
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdbool.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/syscall.h>
+
+/*
+ * 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;
+}