summaryrefslogtreecommitdiff
path: root/ioreplay/src/mounts.c
diff options
context:
space:
mode:
authorPaul Buetow <pbuetow@mimecast.com>2018-03-06 17:38:59 +0000
committerPaul Buetow <pbuetow@mimecast.com>2018-03-06 17:38:59 +0000
commit26b3b3e368a79ce29df732ea04e72a4c002ae2ce (patch)
treee3fc8d7461ab371279f7bf9c692096cd39cc92f6 /ioreplay/src/mounts.c
parentae2221660f9b411fa78cdf8034f0803e9a870cde (diff)
rename into ioriot
Diffstat (limited to 'ioreplay/src/mounts.c')
-rw-r--r--ioreplay/src/mounts.c400
1 files changed, 0 insertions, 400 deletions
diff --git a/ioreplay/src/mounts.c b/ioreplay/src/mounts.c
deleted file mode 100644
index afa8376..0000000
--- a/ioreplay/src/mounts.c
+++ /dev/null
@@ -1,400 +0,0 @@
-// Copyright 2018 Mimecast Ltd.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "mounts.h"
-
-#include "utils/futils.h"
-
-#define _PATH_INSERT "/.ioreplay/"
-#define _PATH_INSERT_LEN 11 // strlen of _PATH_INSERT
-
-void mounts_read(mounts_s *m)
-{
- char *mounts = "/proc/mounts";
- size_t len = 0;
- char *line = NULL;
- char *saveptr = NULL;
-
- Put("Reading '%s'", mounts);
-
- FILE *fp = Fopen(mounts, "r");
- Out("Adding supported file systems to replay paths:");
-
- while (getline(&line, &len, fp) != -1) {
- bool ignore = true;
-
- char *dev = strtok_r(line, " ", &saveptr);
- if (dev == NULL) {
- Error("Could not parse device from %s", mounts);
- }
-
- char *mp = strtok_r(NULL, " ", &saveptr);
- if (mp == NULL) {
- Error("Could not parse mountpoint from %s", mounts);
- }
-
- char *fs = strtok_r(NULL, " ", &saveptr);
- if (fs == NULL) {
- Error("Could not parse file system from %s", mounts);
- }
-#ifdef MP_DEBUG
- Debug("fs:%s", fs);
-#endif
- // TODO: Make file system types configurable
- if (Eq(fs, "ext2")) {
- ignore = false;
- } else if (Eq(fs, "ext5")) {
- ignore = false;
- } else if (Eq(fs, "ext4")) {
- ignore = false;
- } else if (Eq(fs, "xfs")) {
- ignore = false;
- } else if (Eq(fs, "zfs")) {
- ignore = false;
- } else if (Eq(fs, "btrfs")) {
- ignore = false;
- }
-
- if (ignore) {
- if (strcmp(mp, "/") != 0) {
- m->ignore_mps[m->ignore_count] = Clone(mp);
- m->ignore_count++;
- }
-
- } else if (m->count >= MAX_MOUNTPOINTS) {
- Error("Exceeded max mount points: %d\n", m->count);
-
- } else {
- Out(" %s (%s)", mp, fs);
- m->mps[m->count] = Clone(mp);
- m->lengths[m->count] = strlen(mp);
- m->count++;
- }
- }
-
- fclose(fp);
- Out("\n");
-}
-
-mounts_s *mounts_new(options_s *opts)
-{
- mounts_s *m = Malloc(mounts_s);
-
- m->opts = opts;
- m->count = 0;
- m->ignore_count = 0;
- mounts_read(m);
-
- return m;
-}
-
-void mounts_destroy(mounts_s *m)
-{
- if (!m)
- return;
- for (int i = 0; i < m->count; i++)
- free(m->mps[i]);
- free(m);
-}
-
-void mounts_trash(mounts_s *m)
-{
- options_s *opts = m->opts;
- set_limits_drop_root(opts->user);
- Put("Moving all old files to trash (of previous tests)...");
-
- struct timeval tv;
- gettimeofday(&tv, NULL);
-
- char *wd_path = NULL;
- asprintf(&wd_path, "%s/%s", opts->wd_base, opts->name);
-
- char *trash_path = NULL;
- asprintf(&trash_path, "%s/.trash/%ld", opts->wd_base, tv.tv_sec);
-
- if (is_dir(wd_path)) {
- ensure_dir_exists(trash_path);
- chown_path(opts->user, trash_path);
- if (rename(wd_path, trash_path)) {
- Errno("Could not move '%s' to '%s'", wd_path, trash_path);
- }
- }
- free(wd_path);
- free(trash_path);
-
- for (int i = 0; i < m->count; i++) {
- char *mp = m->mps[i];
- char *path = NULL;
- asprintf(&path, "%s/%s/%s", mp, _PATH_INSERT, opts->name);
- asprintf(&trash_path, "%s/%s/.trash/%ld",
- mp, _PATH_INSERT, tv.tv_sec);
-
- if (is_dir(path)) {
- ensure_dir_exists(trash_path);
- chown_path(opts->user, trash_path);
- if (rename(path, trash_path)) {
- Errno("Could not move '%s' to '%s'", path, trash_path);
- }
- }
-
- free(path);
- free(trash_path);
- }
-
- Put("Done trashing!");
- Put("Once the drives fill up you may want to purge old data (-P)");
-}
-
-void mounts_purge(mounts_s *m)
-{
- options_s *opts = m->opts;
- set_limits_drop_root(opts->user);
-
- Out("Purging all data from the following directories:");
-
- int active_purgers = 0, max_purgers = 16;
- if (opts->num_workers > max_purgers)
- max_purgers = opts->num_workers;
-
- char *purge_path = NULL;
- asprintf(&purge_path, "%s", opts->wd_base);
- if (is_dir(purge_path)) {
- Out(" %s", purge_path);
- pid_t pid = fork();
-
- if (pid == 0) {
- ensure_dir_empty(purge_path);
- free(purge_path);
- exit(0);
-
- } else if (pid < 0) {
- Errno("\nUnable to create cleaner process! :'-(");
- }
- active_purgers++;
- }
- free(purge_path);
-
- int cleaner_status = SUCCESS;
-
- for (int i = 0; i < m->count; i++) {
- char *mp = m->mps[i];
- char *purge_path = NULL;
- asprintf(&purge_path, "%s/%s", mp, _PATH_INSERT);
-
- if (is_dir(purge_path)) {
- if (active_purgers+1 >= max_purgers) {
- wait(&cleaner_status);
- active_purgers--;
- }
-
- // TODO: Use threading model same way as in init/init.c
- pid_t pid = fork();
- if (pid == 0) {
- Out(" %s", purge_path);
- ensure_dir_empty(purge_path);
- free(purge_path);
- exit(0);
- } else if (pid < 0) {
- Errno("Unable to create cleaner process! :'-(");
- }
- active_purgers++;
- }
- free(purge_path);
- }
-
- while (wait(&cleaner_status) > 0)
- active_purgers--;
- Put("\nCleaning done!");
-}
-
-void mounts_init(mounts_s *m)
-{
- options_s *opts = m->opts;
- char *wd_path = NULL;
- asprintf(&wd_path, "%s/%s", opts->wd_base, opts->name);
- ensure_dir_exists(wd_path);
- chown_path(opts->user, opts->wd_base);
- chown_path(opts->user, wd_path);
-
- if (chdir(wd_path)) {
- Errno("Could not chdir into '%s'!", wd_path);
-
- } else {
- Put("Chdir into '%s'", wd_path);
- }
-
- free(wd_path);
-
- for (int i = 0; i < m->count; i++) {
- char *mp = m->mps[i];
- char *path = NULL;
-
- // Create .ioreplay/ directory on MP
- asprintf(&path, "%s/%s", mp, _PATH_INSERT);
- ensure_dir_exists(path);
- chown_path(m->opts->user, path);
- free(path);
- path = NULL;
-
- // Create .ioreplay/NAME directory on MP
- asprintf(&path, "%s/%s/%s", mp, _PATH_INSERT, opts->name);
- ensure_dir_exists(path);
- chown_path(m->opts->user, path);
- free(path);
- }
-}
-
-bool mounts_ignore_path(mounts_s *m, const char *path)
-{
- // CentOS 7 specific, ignore temp namespace mounts!
- char *pos = strstr(path, "/tmp/namespace-");
- if (pos == path)
- return true;
-
- // iterate backwards through all mount points.
- for (int i = m->ignore_count-1; i >= 0; --i) {
- char *mountpoint = m->ignore_mps[i];
- pos = strstr(path, mountpoint);
- // Ignore this path as it is in the ignore mp list
- if (pos == path)
- return true;
- }
-
- return false;
-}
-
-bool mounts_transform_path(mounts_s *m, const char *name,
- char *path, char **path_r)
-{
- char *tmp = NULL;
-#ifdef DEBUG_TRANSFORM_PATH
- char *original_path = path;
-#endif
- bool line_ok = true;
-
- // First figure out whether there are '..' in any paths. If so we have to
- // tokenize the path and remove '..'. Example:
- // transform '/foo/bar/../' into '/foo/'.
- // Also remove double '/' from paths.
-
- if (strstr(path, "..") || strstr(path, "//")) {
- // tmp will be freed under label 'cleanup' at end of function.
- tmp = Calloc(strlen(path)+1, char);
-
- // stack to put the tokens on
- stack_s *s = stack_new();
-
- // we need a copy of the path, so we can tokenize it into the stack
- char* clone = Clone(path);
-
- char *saveptr = NULL;
- char *tok = strtok_r(clone, "/", &saveptr);
-
- // Add each part of the path to the stack.
- while (tok) {
- if (strcmp(tok, "..") == 0) {
- stack_pop(s);
- } else {
- stack_push(s, tok);
- }
- tok = strtok_r(NULL, "/", &saveptr);
- }
-
- if (stack_is_empty(s)) {
- strcpy(tmp, ".");
-
- } else {
- s = stack_new_reverse_from(s);
- strcpy(tmp, "/");
- strcat(tmp, (char*)stack_pop(s));
-
- while(!stack_is_empty(s)) {
- strcat(tmp, "/");
- strcat(tmp, (char*)stack_pop(s));
- }
- }
-
- stack_destroy(s);
- free(clone);
-
- // This is the path without '..' and '//' (and '///' ... etc')
- path = tmp;
- }
-
- // Now heck whether the path is on a supported file system. If not, ignore!
- if (mounts_ignore_path(m, path)) {
- line_ok = false;
- goto cleanup;
- }
-
- // So the path is on a valid mount point! Now we need to insert
- // .ioreplay/NAME to each mount point, e.g. /usr/local/.ioreplay/NAME/...
-
- // Iterate backwards through all mount points.
- for (int i = m->count-1; i >= 0; --i) {
- char *mountpoint = m->mps[i];
- int mp_len = m->lengths[i];
-
- if (strncmp(path, mountpoint, mp_len) == 0) {
- // Found a path to replace
- // Now insert .ioreplay/NAME/ into the file path.
- *path_r = Calloc(strlen(path) + strlen(name)+1
- + _PATH_INSERT_LEN+1, char);
-
- if (strcmp(mountpoint, "/") == 0) {
- // Root path
- strcpy(*path_r, _PATH_INSERT);
- strcat(*path_r, name);
- strcat(*path_r, path);
-
- } else {
- strcpy(*path_r, mountpoint);
- strcat(*path_r, _PATH_INSERT);
- strcat(*path_r, name);
- char *pos = path;
- pos += mp_len * (int) sizeof(char);
- strcat(*path_r, pos);
- }
-
- goto cleanup;
- }
- }
-
- if (tmp)
- free(tmp);
-
- return line_ok;
-
-cleanup:
-#ifdef DEBUG_TRANSFORM_PATH
- Debug("Transform path '%s' -> '%s' -> '%s'", original_path, path, *path_r);
-#endif
- if (tmp)
- free(tmp);
-
- return line_ok;
-}
-
-int mounts_get_mountnumber(mounts_s *m, const char *path)
-{
- for (int i = m->count-1; i >= 0; --i) {
- char *mountpoint = m->mps[i];
- int mp_len = m->lengths[i];
-
- if (strncmp(path, mountpoint, mp_len) == 0)
- return i;
- }
-
- return 0;
-}