summaryrefslogtreecommitdiff
path: root/ioshark
diff options
context:
space:
mode:
authorMohan Srinivasan <srmohan@google.com>2017-02-24 16:34:28 -0800
committerMohan Srinivasan <srmohan@google.com>2017-02-27 20:01:11 -0800
commit02f8626d766424406bcfea1e20ef352d3b9a72cf (patch)
tree768ececfd4d106049585ab238302e9f71f395797 /ioshark
parent2aa6e6fbda3ac6781efd022f01f8006cedda878d (diff)
downloadextras-02f8626d766424406bcfea1e20ef352d3b9a72cf.tar.gz
IOshark support to not pre-create files in /system, /vendor, ...
1) Add support to IOshark to not pre-create files that the workload read from /system, /vendor and other read-only partitions. Instead we just read the underlying files directly. 2) This support is implemented under a new -q (quick) mode. 3) Other misc fixes to do a setrlimit(NO_FD) so we don't run out of fds during test. 4) Also commiting raw strace files from several monkey runs so we can compile those if we make on disk IOshark format changes in the future. Test: Run IOshark with different workloads to make sure that this skipping of pre-creation works fine. Change-Id: Ic025cb0162eca479d9f529846e619dd4b71aa490 Signed-off-by: Mohan Srinivasan <srmohan@google.com>
Diffstat (limited to 'ioshark')
-rw-r--r--ioshark/Android.mk8
-rwxr-xr-xioshark/collect-straces.sh4
-rw-r--r--ioshark/compile_ioshark.c2
-rw-r--r--ioshark/compile_ioshark.h3
-rw-r--r--ioshark/compile_ioshark_subr.c117
-rw-r--r--ioshark/dump_ioshark_filenames.c80
-rw-r--r--ioshark/ioshark.h11
-rw-r--r--ioshark/ioshark_bench.c136
-rw-r--r--ioshark/ioshark_bench.h23
-rw-r--r--ioshark/ioshark_bench_subr.c117
-rw-r--r--ioshark/monkeytrace1.tar.gzbin0 -> 16710898 bytes
-rw-r--r--ioshark/monkeytrace2.tar.gzbin0 -> 104344148 bytes
-rw-r--r--ioshark/monkeytracebig.tar.gzbin0 -> 19851673 bytes
-rw-r--r--ioshark/wl.tarbin1566720 -> 11939840 bytes
14 files changed, 455 insertions, 46 deletions
diff --git a/ioshark/Android.mk b/ioshark/Android.mk
index 04ddeb10..f760d7b6 100644
--- a/ioshark/Android.mk
+++ b/ioshark/Android.mk
@@ -33,5 +33,13 @@ LOCAL_MODULE := compile_ioshark
LOCAL_MODULE_TAGS := debug
include $(BUILD_HOST_EXECUTABLE)
+include $(CLEAR_VARS)
+#LOCAL_32_BIT_ONLY = true
+LOCAL_MODULE_HOST_OS := linux
+LOCAL_SRC_FILES := dump_ioshark_filenames.c
+LOCAL_CFLAGS := -g -O2 -Wall -Werror -D_GNU_SOURCE
+LOCAL_MODULE := dump_ioshark_filenames
+LOCAL_MODULE_TAGS := debug
+include $(BUILD_HOST_EXECUTABLE)
diff --git a/ioshark/collect-straces.sh b/ioshark/collect-straces.sh
index 1071a33e..d8a73055 100755
--- a/ioshark/collect-straces.sh
+++ b/ioshark/collect-straces.sh
@@ -88,6 +88,4 @@ tar xf trace.tar
compile_tracefiles
# tar up the .wl files just created
-tar zcf wl.tgz *.wl
-
-
+tar cf wl.tar ioshark_filenames *.wl
diff --git a/ioshark/compile_ioshark.c b/ioshark/compile_ioshark.c
index 683b5975..97c77c90 100644
--- a/ioshark/compile_ioshark.c
+++ b/ioshark/compile_ioshark.c
@@ -459,6 +459,7 @@ int main(int argc, char **argv)
progname, infile);
exit(EXIT_FAILURE);
}
+ init_filename_cache();
get_start_time(&start_time);
fp = fopen(infile, "r");
if (fp == NULL) {
@@ -574,4 +575,5 @@ int main(int argc, char **argv)
in_mem_file_op_head = in_mem_file_op_head->next;
free(temp);
}
+ store_filename_cache();
}
diff --git a/ioshark/compile_ioshark.h b/ioshark/compile_ioshark.h
index 13095bf6..9e11bd20 100644
--- a/ioshark/compile_ioshark.h
+++ b/ioshark/compile_ioshark.h
@@ -21,6 +21,7 @@ struct files_db_s {
int fileno;
struct files_db_s *next;
size_t size;
+ int global_filename_ix;
};
/* Lifted from Wikipedia Jenkins Hash function page */
@@ -73,6 +74,8 @@ void files_db_write_objects(FILE *fp);
void *files_db_add(char *filename);
void *files_db_lookup(char *filename);
int files_db_get_total_obj(void);
+void init_filename_cache(void);
+void store_filename_cache(void);
diff --git a/ioshark/compile_ioshark_subr.c b/ioshark/compile_ioshark_subr.c
index e2b6b891..5cc07c66 100644
--- a/ioshark/compile_ioshark_subr.c
+++ b/ioshark/compile_ioshark_subr.c
@@ -31,6 +31,8 @@ static struct files_db_s *files_db_buckets[FILE_DB_HASHSIZE];
static int current_fileno = 1;
static int num_objects = 0;
+static int filename_cache_lookup(char *filename);;
+
void
files_db_write_objects(FILE *fp)
{
@@ -44,8 +46,11 @@ files_db_write_objects(FILE *fp)
while (db_node != NULL) {
st.fileno = db_node->fileno;
st.size = db_node->size;
+ st.global_filename_ix =
+ db_node->global_filename_ix;
if (fwrite(&st, sizeof(st), 1, fp) != 1) {
- fprintf(stderr, "%s Write error trace.outfile\n",
+ fprintf(stderr,
+ "%s Write error trace.outfile\n",
progname);
exit(EXIT_FAILURE);
}
@@ -84,6 +89,8 @@ void *files_db_add(char *filename)
hash %= FILE_DB_HASHSIZE;
db_node = malloc(sizeof(struct files_db_s));
db_node->filename = strdup(filename);
+ db_node->global_filename_ix =
+ filename_cache_lookup(filename);
db_node->fileno = current_fileno++;
db_node->next = files_db_buckets[hash];
db_node->size = 0;
@@ -98,5 +105,113 @@ files_db_get_total_obj(void)
return num_objects;
}
+static struct ioshark_filename_struct *filename_cache;
+static int filename_cache_num_entries;
+static int filename_cache_size;
+
+void
+init_filename_cache(void)
+{
+ static FILE *filename_cache_fp;
+ struct stat st;
+ int file_exists = 1;
+
+ if (stat("ioshark_filenames", &st) < 0) {
+ if (errno != ENOENT) {
+ fprintf(stderr, "%s Can't stat ioshark_filenames file\n",
+ progname);
+ exit(EXIT_FAILURE);
+ } else {
+ file_exists = 0;
+ filename_cache_num_entries = 0;
+ }
+ } else {
+ filename_cache_num_entries = st.st_size /
+ sizeof(struct ioshark_filename_struct);
+ }
+ if (file_exists) {
+ filename_cache_fp = fopen("ioshark_filenames", "r");
+ if (filename_cache_fp == NULL) {
+ fprintf(stderr, "%s Cannot open ioshark_filenames file\n",
+ progname);
+ exit(EXIT_FAILURE);
+ }
+ }
+ /* Preallocate a fixed size of entries */
+ filename_cache_size = filename_cache_num_entries + 1024;
+ filename_cache = calloc(filename_cache_size,
+ sizeof(struct ioshark_filename_struct));
+ if (filename_cache == NULL) {
+ fprintf(stderr, "%s Can't allocate memory - this is fatal\n",
+ __func__);
+ exit(EXIT_FAILURE);
+ }
+ if (fread(filename_cache,
+ sizeof(struct ioshark_filename_struct),
+ filename_cache_num_entries,
+ filename_cache_fp) != (size_t)filename_cache_num_entries) {
+ fprintf(stderr, "%s Can't read ioshark_filenames file\n",
+ progname);
+ exit(EXIT_FAILURE);
+ }
+ if (file_exists)
+ fclose(filename_cache_fp);
+}
+
+static int
+filename_cache_lookup(char *filename)
+{
+ int ret;
+ int i;
+
+ for (i = 0 ; i < filename_cache_num_entries ; i++) {
+ if (strcmp(filename_cache[i].path, filename) == 0)
+ return i;
+ }
+ if (filename_cache_num_entries >= filename_cache_size) {
+ int newsize;
+
+ /* reallocate the filename cache up first */
+ filename_cache_size += 1024;
+ newsize = filename_cache_size *
+ sizeof(struct ioshark_filename_struct);
+ filename_cache = realloc(filename_cache, newsize);
+ if (filename_cache == NULL) {
+ fprintf(stderr,
+ "%s Can't allocate memory - this is fatal\n",
+ __func__);
+ exit(EXIT_FAILURE);
+ }
+ }
+ strcpy(filename_cache[filename_cache_num_entries].path,
+ filename);
+ ret = filename_cache_num_entries;
+ filename_cache_num_entries++;
+ return ret;
+}
+
+void
+store_filename_cache(void)
+{
+ static FILE *filename_cache_fp;
+
+ filename_cache_fp = fopen("ioshark_filenames", "w+");
+ if (filename_cache_fp == NULL) {
+ fprintf(stderr, "%s Cannot open ioshark_filenames file\n",
+ progname);
+ exit(EXIT_FAILURE);
+ }
+ if (fwrite(filename_cache,
+ sizeof(struct ioshark_filename_struct),
+ filename_cache_num_entries,
+ filename_cache_fp) != (size_t)filename_cache_num_entries) {
+ fprintf(stderr, "%s Can't read ioshark_filenames file\n",
+ progname);
+ exit(EXIT_FAILURE);
+ }
+ fclose(filename_cache_fp);
+ free(filename_cache);
+}
+
diff --git a/ioshark/dump_ioshark_filenames.c b/ioshark/dump_ioshark_filenames.c
new file mode 100644
index 00000000..c082c274
--- /dev/null
+++ b/ioshark/dump_ioshark_filenames.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * 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 <stdio.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/errno.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include "ioshark.h"
+
+/*
+ * Real simple utility that just extracts and dumps the IOshark filenames
+ * one per line from the ioshark_filenames file. Useful in debugging.
+ */
+int
+main(int argc __attribute__((unused)), char **argv)
+{
+ char *progname;
+ static FILE *filename_cache_fp;
+ struct stat st;
+ struct ioshark_filename_struct *filename_cache;
+ int filename_cache_num_entries;
+ size_t filename_cache_size;
+ int i;
+
+ progname = argv[0];
+ if (stat("ioshark_filenames", &st) < 0) {
+ fprintf(stderr, "%s Can't stat ioshark_filenames file\n",
+ progname);
+ exit(EXIT_FAILURE);
+ }
+ filename_cache_num_entries = st.st_size /
+ sizeof(struct ioshark_filename_struct);
+ filename_cache_fp = fopen("ioshark_filenames", "r");
+ if (filename_cache_fp == NULL) {
+ fprintf(stderr, "%s Cannot open ioshark_filenames file\n",
+ progname);
+ exit(EXIT_FAILURE);
+ }
+ /* Preallocate a fixed size of entries */
+ filename_cache_size = filename_cache_num_entries + 1024;
+ filename_cache = calloc(filename_cache_size,
+ sizeof(struct ioshark_filename_struct));
+ if (filename_cache == NULL) {
+ fprintf(stderr, "%s Can't allocate memory - this is fatal\n",
+ __func__);
+ exit(EXIT_FAILURE);
+ }
+ if (fread(filename_cache,
+ sizeof(struct ioshark_filename_struct),
+ filename_cache_num_entries,
+ filename_cache_fp) != (size_t)filename_cache_num_entries) {
+ fprintf(stderr, "%s Can't read ioshark_filenames file\n",
+ progname);
+ exit(EXIT_FAILURE);
+ }
+ for (i = 0 ; i < filename_cache_num_entries ; i++) {
+ printf("%s\n", filename_cache[i].path);
+ }
+ free(filename_cache);
+ fclose(filename_cache_fp);
+}
diff --git a/ioshark/ioshark.h b/ioshark/ioshark.h
index f0a715f7..fd9caca4 100644
--- a/ioshark/ioshark.h
+++ b/ioshark/ioshark.h
@@ -40,6 +40,7 @@ struct ioshark_header {
struct ioshark_file_state {
int fileno; /* 1..num_files, with files name ioshark.<fileno> */
size_t size;
+ int global_filename_ix;
};
enum file_op {
@@ -106,3 +107,13 @@ struct ioshark_file_operation {
} open_a;
} u;
};
+
+#define MAX_IOSHARK_PATHLEN 512
+
+/*
+ * Global table of all fileames
+ */
+struct ioshark_filename_struct
+{
+ char path[MAX_IOSHARK_PATHLEN];
+};
diff --git a/ioshark/ioshark_bench.c b/ioshark/ioshark_bench.c
index 670ec757..95ba854d 100644
--- a/ioshark/ioshark_bench.c
+++ b/ioshark/ioshark_bench.c
@@ -28,10 +28,21 @@
#include <assert.h>
#include <pthread.h>
#include <sys/statfs.h>
+#include <sys/resource.h>
#include "ioshark.h"
#define IOSHARK_MAIN
#include "ioshark_bench.h"
+/*
+ * Note on "quick" mode where we do reads on existing /system,
+ * /vendor and other files in ro partitions, instead of creating
+ * them. The ioshark compiler builds up a table of all the files
+ * in /system, /vendor and other ro partitions. For files in this
+ * list, the benchmark skips the pre-creation of these files and
+ * reads them directly.
+ * The code relevant to this is in *filename_cache*.
+ */
+
char *progname;
#define MAX_INPUT_FILES 1024
@@ -56,6 +67,7 @@ pthread_t tid[MAX_THREADS];
int do_delay = 0;
int verbose = 0;
int summary_mode = 0;
+int quick_mode = 0;
#if 0
static long gettid()
@@ -66,7 +78,9 @@ static long gettid()
void usage()
{
- fprintf(stderr, "%s [-d preserve_delays] [-n num_iterations] [-t num_threads] <list of parsed input files>\n",
+ fprintf(stderr, "%s [-d preserve_delays] [-n num_iterations] [-t num_threads] -q -v | -s <list of parsed input files>\n",
+ progname);
+ fprintf(stderr, "%s -s, -v are mutually exclusive\n",
progname);
exit(EXIT_FAILURE);
}
@@ -150,9 +164,11 @@ create_files(struct thread_state_s *state)
{
int i;
struct ioshark_file_state file_state;
- char path[512];
+ char path[MAX_IOSHARK_PATHLEN];
void *db_node;
struct rw_bytes_s rw_bytes;
+ char *filename;
+ int readonly;
memset(&rw_bytes, 0, sizeof(struct rw_bytes_s));
for (i = 0 ; i < state->num_files ; i++) {
@@ -162,15 +178,31 @@ create_files(struct thread_state_s *state)
progname);
exit(EXIT_FAILURE);
}
- sprintf(path, "file.%d.%d",
- (int)(state - thread_state),
- file_state.fileno);
- create_file(path, file_state.size,
- &rw_bytes);
+ /*
+ * Check to see if the file is in a readonly partition,
+ * in which case, we don't have to pre-create the file
+ * we can just read the existing file.
+ */
+ filename =
+ get_ro_filename(file_state.global_filename_ix);
+ assert(filename != NULL);
+ if (quick_mode == 0 ||
+ is_readonly_mount(filename, file_state.size) == 0) {
+ sprintf(path, "file.%d.%d",
+ (int)(state - thread_state),
+ file_state.fileno);
+ create_file(path, file_state.size,
+ &rw_bytes);
+ filename = path;
+ readonly = 0;
+ } else {
+ readonly = 1;
+ }
db_node = files_db_add_byfileno(state->db_handle,
- file_state.fileno);
+ file_state.fileno,
+ readonly);
files_db_update_size(db_node, file_state.size);
- files_db_update_filename(db_node, path);
+ files_db_update_filename(db_node, filename);
}
update_byte_counts(&aggr_create_rw_bytes, &rw_bytes);
}
@@ -416,15 +448,24 @@ do_io(struct thread_state_s *state)
}
if (file_op.file_op != IOSHARK_OPEN &&
files_db_get_fd(db_node) == -1) {
+ int openflags;
+
/*
* This is a hack to workaround the fact that we did not
- * see an open() for this file until now. open() the file
- * O_RDWR, so that we can perform the IO.
+ * see an open() for this file until now. open() the
+ * file O_RDWR, so that we can perform the IO.
*/
- fd = open(files_db_get_filename(db_node), O_RDWR);
+ if (files_db_readonly(db_node))
+ openflags = O_RDONLY;
+ else
+ openflags = O_RDWR;
+ fd = open(files_db_get_filename(db_node),
+ openflags);
if (fd < 0) {
- fprintf(stderr, "%s: open(%s O_RDWR) error %d\n",
- progname, files_db_get_filename(db_node),
+ fprintf(stderr, "%s: open(%s %x) error %d\n",
+ progname,
+ files_db_get_filename(db_node),
+ openflags,
errno);
exit(EXIT_FAILURE);
}
@@ -520,11 +561,16 @@ get_start_end(int *start_ix)
progname);
exit(EXIT_FAILURE);
}
- if (file_state.size > free_fs_bytes) {
- fclose(fp);
- goto out;
+ if (quick_mode == 0 ||
+ !is_readonly_mount(
+ get_ro_filename(file_state.global_filename_ix),
+ file_state.size)) {
+ if (file_state.size > free_fs_bytes) {
+ fclose(fp);
+ goto out;
+ }
+ free_fs_bytes -= file_state.size;
}
- free_fs_bytes -= file_state.size;
}
fclose(fp);
}
@@ -568,6 +614,40 @@ wait_for_threads(int num_threads)
}
}
+#define IOSHARK_FD_LIM 8192
+
+static void
+sizeup_fd_limits(void)
+{
+ struct rlimit r;
+
+ getrlimit(RLIMIT_NOFILE, &r);
+ if (r.rlim_cur >= IOSHARK_FD_LIM)
+ /* cur limit already at what we want */
+ return;
+ /*
+ * Size up both the Max and Cur to IOSHARK_FD_LIM.
+ * If we are not running as root, this will fail,
+ * catch that below and exit.
+ */
+ if (r.rlim_max < IOSHARK_FD_LIM)
+ r.rlim_max = IOSHARK_FD_LIM;
+ r.rlim_cur = IOSHARK_FD_LIM;
+ if (setrlimit(RLIMIT_NOFILE, &r) < 0) {
+ fprintf(stderr, "%s: Can't setrlimit (RLIMIT_NOFILE, 8192)\n",
+ progname);
+ exit(EXIT_FAILURE);
+ }
+ getrlimit(RLIMIT_NOFILE, &r);
+ if (r.rlim_cur < IOSHARK_FD_LIM) {
+ fprintf(stderr, "%s: Can't setrlimit up to 8192\n",
+ progname);
+ fprintf(stderr, "%s: Running as root ?\n",
+ progname);
+ exit(EXIT_FAILURE);
+ }
+}
+
int
main(int argc, char **argv)
{
@@ -582,7 +662,7 @@ main(int argc, char **argv)
struct thread_state_s *state;
progname = argv[0];
- while ((c = getopt(argc, argv, "dn:st:v")) != EOF) {
+ while ((c = getopt(argc, argv, "dn:st:qv")) != EOF) {
switch (c) {
case 'd':
do_delay = 1;
@@ -597,6 +677,14 @@ main(int argc, char **argv)
case 't':
num_threads = atoi(optarg);
break;
+ case 'q':
+ /*
+ * If quick mode is enabled, then we won't
+ * pre-create files that we are doing IO on that
+ * live in readonly partitions (/system, /vendor etc)
+ */
+ quick_mode = 1;
+ break;
case 'v':
verbose = 1;
break;
@@ -614,13 +702,14 @@ main(int argc, char **argv)
if (optind == argc)
usage();
+ sizeup_fd_limits();
+
for (i = optind; i < argc; i++) {
infile = argv[i];
if (stat(infile, &st) < 0) {
fprintf(stderr, "%s: Can't stat %s\n",
progname, infile);
exit(EXIT_FAILURE);
- continue;
}
if (st.st_size == 0) {
fprintf(stderr, "%s: Empty file %s\n",
@@ -649,6 +738,9 @@ main(int argc, char **argv)
timerclear(&aggregate_file_remove_time);
timerclear(&aggregate_IO_time);
+ if (quick_mode)
+ init_filename_cache();
+
capture_util_state_before();
/*
@@ -667,6 +759,8 @@ main(int argc, char **argv)
/* Create files once */
if (!summary_mode)
printf("Doing Pre-creation of Files\n");
+ if (quick_mode && !summary_mode)
+ printf("Skipping Pre-creation of read-only Files\n");
if (num_threads == 0 || num_threads > num_files)
num_threads = num_files;
(void)system("echo 3 > /proc/sys/vm/drop_caches");
@@ -765,4 +859,6 @@ main(int argc, char **argv)
report_cpu_disk_util();
printf("\n");
}
+ if (quick_mode)
+ free_filename_cache();
}
diff --git a/ioshark/ioshark_bench.h b/ioshark/ioshark_bench.h
index 95e6a317..d0d09626 100644
--- a/ioshark/ioshark_bench.h
+++ b/ioshark/ioshark_bench.h
@@ -46,6 +46,7 @@ struct files_db_s {
int fileno;
size_t size;
int fd;
+ int readonly;
int debug_open_flags;
struct files_db_s *next;
};
@@ -96,6 +97,12 @@ files_db_get_filename(void *node)
return (((struct files_db_s *)node)->filename);
}
+static inline int
+files_db_readonly(void *node)
+{
+ return (((struct files_db_s *)node)->readonly);
+}
+
static inline u_int64_t
get_msecs(struct timeval *tv)
{
@@ -122,7 +129,7 @@ update_delta_time(struct timeval *start,
void *files_db_create_handle(void);
void *files_db_lookup_byfileno(void *handle, int fileno);
-void *files_db_add_byfileno(void *handle, int fileno);
+void *files_db_add_byfileno(void *handle, int fileno, int readonly);
void files_db_update_fd(void *node, int fd);
void files_db_unlink_files(void *db_handle);
void files_db_close_files(void *handle);
@@ -141,13 +148,7 @@ void ioshark_handle_mmap(void *db_node,
void capture_util_state_before(void);
void report_cpu_disk_util(void);
-
-
-
-
-
-
-
-
-
-
+char *get_ro_filename(int ix);
+void init_filename_cache(void);
+void free_filename_cache(void);
+int is_readonly_mount(char *filename, size_t size);
diff --git a/ioshark/ioshark_bench_subr.c b/ioshark/ioshark_bench_subr.c
index 1b0ecf98..4280a5a4 100644
--- a/ioshark/ioshark_bench_subr.c
+++ b/ioshark/ioshark_bench_subr.c
@@ -26,6 +26,9 @@
#include <fcntl.h>
#include <string.h>
#include <assert.h>
+#include <sys/vfs.h>
+#include <sys/statvfs.h>
+#include <sys/mman.h>
#include "ioshark.h"
#include "ioshark_bench.h"
@@ -60,7 +63,7 @@ void *files_db_lookup_byfileno(void *handle, int fileno)
return db_node;
}
-void *files_db_add_byfileno(void *handle, int fileno)
+void *files_db_add_byfileno(void *handle, int fileno, int readonly)
{
u_int32_t hash = fileno % FILE_DB_HASHSIZE;
struct files_db_handle *h = (struct files_db_handle *)handle;
@@ -72,6 +75,7 @@ void *files_db_add_byfileno(void *handle, int fileno)
db_node = malloc(sizeof(struct files_db_s));
db_node->fileno = fileno;
db_node->filename = NULL;
+ db_node->readonly = readonly;
db_node->size = 0;
db_node->fd = -1;
db_node->next = h->files_db_buckets[hash];
@@ -99,24 +103,30 @@ files_db_fsync_discard_files(void *handle)
if (db_node->fd == -1) {
int fd;
+ int openflags;
- /*
+ /*n
* File was closed, let's open it so we can
* fsync and fadvise(DONTNEED) it.
*/
do_close = 1;
+ if (files_db_readonly(db_node))
+ openflags = O_RDONLY;
+ else
+ openflags = O_RDWR;
fd = open(files_db_get_filename(db_node),
- O_RDWR);
+ openflags);
if (fd < 0) {
fprintf(stderr,
- "%s: open(%s O_RDWR) error %d\n",
+ "%s: open(%s %x) error %d\n",
progname, db_node->filename,
+ openflags,
errno);
exit(EXIT_FAILURE);
}
db_node->fd = fd;
}
- if (fsync(db_node->fd) < 0) {
+ if (!db_node->readonly && fsync(db_node->fd) < 0) {
fprintf(stderr, "%s: Cannot fsync %s\n",
__func__, db_node->filename);
exit(1);
@@ -192,10 +202,13 @@ files_db_unlink_files(void *handle)
exit(1);
}
db_node->fd = -1;
- if (unlink(db_node->filename) < 0) {
- fprintf(stderr, "%s: Cannot unlink %s:%s\n",
- __func__, db_node->filename, strerror(errno));
- exit(1);
+ if (is_readonly_mount(db_node->filename, db_node->size) == 0) {
+ if (unlink(db_node->filename) < 0) {
+ fprintf(stderr, "%s: Cannot unlink %s:%s\n",
+ __func__, db_node->filename,
+ strerror(errno));
+ exit(EXIT_FAILURE);
+ }
}
db_node = db_node->next;
}
@@ -488,8 +501,6 @@ capture_util_state_before(void)
read_cpu_util_state(&before);
}
-extern int verbose;
-
void
report_cpu_disk_util(void)
{
@@ -547,3 +558,87 @@ report_cpu_disk_util(void)
else
printf("%.2f", disk_util);
}
+
+
+static struct ioshark_filename_struct *filename_cache;
+static int filename_cache_num_entries;
+
+char *
+get_ro_filename(int ix)
+{
+ if (ix >= filename_cache_num_entries)
+ return NULL;
+ return filename_cache[ix].path;
+}
+
+void
+init_filename_cache(void)
+{
+ int fd;
+ struct stat st;
+
+ fd = open("ioshark_filenames", O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "%s Can't open ioshark_filenames file\n",
+ progname);
+ exit(EXIT_FAILURE);
+ }
+ if (fstat(fd, &st) < 0) {
+ fprintf(stderr, "%s Can't fstat ioshark_filenames file\n",
+ progname);
+ exit(EXIT_FAILURE);
+ }
+ filename_cache_num_entries = st.st_size /
+ sizeof(struct ioshark_filename_struct);
+ filename_cache = mmap(NULL, st.st_size, PROT_READ,
+ MAP_SHARED | MAP_LOCKED | MAP_POPULATE,
+ fd, 0);
+ if (filename_cache == MAP_FAILED) {
+ fprintf(stderr, "%s Can't fstat ioshark_filenames file: %s\n",
+ progname, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ close(fd);
+}
+
+void
+free_filename_cache(void)
+{
+ size_t mmap_size;
+
+ mmap_size = filename_cache_num_entries *
+ sizeof(struct ioshark_filename_struct);
+ munmap(filename_cache, mmap_size);
+}
+
+/*
+ * Is the passed in filename a regular file ? (eg. not a directory).
+ * Second, is it in a read-only partition ?
+ */
+int
+is_readonly_mount(char *filename, size_t size)
+{
+ struct statfs statfsbuf;
+ struct stat statbuf;
+
+ if (stat(filename, &statbuf) < 0) {
+ /* File possibly deleted */
+ return 0;
+ }
+ if (!S_ISREG(statbuf.st_mode)) {
+ /* Is it a regular file ? */
+ return 0;
+ }
+ if ((size_t)statbuf.st_size < size) {
+ /* Size of existing file is smaller than we expect */
+ return 0;
+ }
+ if (statfs(filename, &statfsbuf) < 0) {
+ /* This shouldn't happen */
+ return 0;
+ }
+ if ((statfsbuf.f_flags & ST_RDONLY) == 0)
+ return 0;
+ else
+ return 1;
+}
diff --git a/ioshark/monkeytrace1.tar.gz b/ioshark/monkeytrace1.tar.gz
new file mode 100644
index 00000000..ae313dd8
--- /dev/null
+++ b/ioshark/monkeytrace1.tar.gz
Binary files differ
diff --git a/ioshark/monkeytrace2.tar.gz b/ioshark/monkeytrace2.tar.gz
new file mode 100644
index 00000000..e5b8268c
--- /dev/null
+++ b/ioshark/monkeytrace2.tar.gz
Binary files differ
diff --git a/ioshark/monkeytracebig.tar.gz b/ioshark/monkeytracebig.tar.gz
new file mode 100644
index 00000000..2ff70475
--- /dev/null
+++ b/ioshark/monkeytracebig.tar.gz
Binary files differ
diff --git a/ioshark/wl.tar b/ioshark/wl.tar
index af7d964e..c945faea 100644
--- a/ioshark/wl.tar
+++ b/ioshark/wl.tar
Binary files differ