/* Linux Projected Filesystem Copyright (C) 2018-2019 GitHub, Inc. See the NOTICE file distributed with this library for additional information regarding copyright ownership. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. 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. You should have received a copy of the GNU Lesser General Public License along with this library, in the file COPYING; if not, see . */ #define _GNU_SOURCE // for nanosleep() in #include #include #include #include #include #include #include "test_common.h" #define MOUNT_SLEEP_TIMESPEC { 0, 1000*1000 } #define MOUNT_WAIT_SEC_DEFAULT 30 #define MOUNT_WAIT_SEC_MAX 3600 static int get_curr_time(time_t *sec) { struct timeval tv; int ret = 0; if (gettimeofday(&tv, NULL) < 0) { warn("unable to get current time"); ret = -1; } else *sec = tv.tv_sec; return ret; } /* modelled on wait_for_mount() in FUSE's test/util.py */ static int wait_for_mount(dev_t prior_dev, const char *mountdir, time_t max_wait) { struct stat mnt; const struct timespec wait_req = MOUNT_SLEEP_TIMESPEC; time_t start, now, wait = 0; time_t warn_sec = 0; int ret = 0; ret = get_curr_time(&start); if (ret < 0) goto out; do { if (stat(mountdir, &mnt) != 0) { // limit warnings to once per second if (warn_sec < wait) { warn("unable to query mount point: %s", mountdir); warn_sec = wait; } } else if (prior_dev != mnt.st_dev) break; nanosleep(&wait_req, NULL); ret = get_curr_time(&now); if (ret < 0) break; wait = now - start; if (wait >= max_wait) { warnx("timeout waiting for filesystem mount at: %s", mountdir); ret = -1; break; } } while (1); out: return ret; } int main(int argc, char *const argv[]) { char *args[3]; long int prior_dev; long int timeout; unsigned int opt_flags; time_t max_wait = MOUNT_WAIT_SEC_DEFAULT; test_parse_opts(argc, argv, TEST_OPT_TIMEOUT, 2, 2, args, NULL, " "); prior_dev = test_parse_long(args[0], 16); if (errno > 0 || prior_dev <= 0) test_exit_error(argv[0], "invalid device ID: %s", args[0]); opt_flags = test_get_opts(TEST_OPT_TIMEOUT, &timeout); if (opt_flags != TEST_OPT_NONE) { if (timeout > MOUNT_WAIT_SEC_MAX) test_exit_error(argv[0], "invalid timeout: %li", timeout); max_wait = timeout; } if (wait_for_mount((dev_t)prior_dev, args[1], max_wait) < 0) exit(EXIT_FAILURE); exit(EXIT_SUCCESS); }