From feb143679eb89ebd2cf973257a58420da60d3249 Mon Sep 17 00:00:00 2001 From: Hans Beckerus Date: Tue, 18 Feb 2014 13:22:00 +0100 Subject: [PATCH] * Released 1.19.8 * Disabled automatic switch to direct I/O mode. * Tweaked some of the more fine grained "hacks" to improve support for compressed archives. * Now supports 'flag_nullpath_ok' and 'flag_nopath' (FUSE >= 2.9) in fuse ops. * The race condition in the I/O buffer has been identified and the lock utilization has been redesigned accordingly to minimize lock contention. * Added check for __sync_synchronize() * Changed use of the FUSE 'keep_cache' flag --- ChangeLog | 31 +++++++ compat.h | 2 +- configure.ac | 18 ++++ debug.h | 2 +- dirlist.c | 8 +- dirlist.h | 2 +- dllext.cpp | 2 +- dllext.hpp | 2 +- dllwrapper.h | 2 +- filecache.c | 2 +- filecache.h | 2 +- fileext.hpp | 2 +- hash.h | 2 +- index.h | 2 +- iobuffer.c | 15 ++-- iobuffer.h | 2 +- mkr2i.c | 2 +- optdb.c | 2 +- optdb.h | 2 +- platform.h | 6 +- rar2fs.1 | 2 +- rar2fs.c | 239 +++++++++++++++++++++++++++++++-------------------- sighandler.c | 2 +- sighandler.h | 2 +- version.h | 4 +- 25 files changed, 233 insertions(+), 124 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8e061d7..1cabe49 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,36 @@ rar2fs ChangeLog file. +2014-02-14 Hans Beckerus + + * Released 1.19.8 + +2014-02-07 Hans Beckerus + + * Disabled automatic switch to direct I/O mode. + + * Tweaked some of the more fine grained "hacks" to improve + support for compressed archives. + + * Now supports 'flag_nullpath_ok' and 'flag_nopath' + (FUSE >= 2.9) in fuse ops. + +2014-02-04 Hans Beckerus + + * The race condition in the I/O buffer has been identified and + the lock utilization has been redesigned accordingly to + minimize lock contention. + + * Added check for __sync_synchronize() + +2014-02-03 Hans Beckerus + + * Changed use of the FUSE 'keep_cache' flag + + * Removed the attempt to optimize the lock contention level + in the I/O buffer. Seems to have opened up for additional + race conditions. When CPU is really needed lock contention + should be close to none anyway. + 2014-02-02 Hans Beckerus * Released 1.19.5 diff --git a/compat.h b/compat.h index 8fc242a..fc36549 100644 --- a/compat.h +++ b/compat.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2009-2013 Hans Beckerus (hans.beckerus#AT#gmail.com) + Copyright (C) 2009-2014 Hans Beckerus (hans.beckerus#AT#gmail.com) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/configure.ac b/configure.ac index 5ac84b8..38817a6 100644 --- a/configure.ac +++ b/configure.ac @@ -591,6 +591,24 @@ AC_TRY_LINK([],[return 0;], ac_c_werror_flag= AC_LANG_POP +AC_LANG_PUSH(C) +ac_c_werror_flag=yes +AC_MSG_CHECKING([for __sync_synchronize]) +AC_TRY_COMPILE([],[int main (int argc, char** argv) {__sync_synchronize();}], + [AC_MSG_RESULT([yes]) + has_synchronize=yes + ], + [AC_MSG_RESULT([no]) + has_synchronize=no + ] +) +ac_c_werror_flag= +AC_LANG_POP + +if test x"$has_synchronize" = x"yes"; then + AC_DEFINE(HAVE_SYNC_SYNCHRONIZE, 1, [Define if __sync_synchronize() is available]) +fi + AC_PROG_LN_S AC_PROG_MKDIR_P diff --git a/debug.h b/debug.h index 3495bae..86ab224 100644 --- a/debug.h +++ b/debug.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2009-2013 Hans Beckerus (hans.beckerus#AT#gmail.com) + Copyright (C) 2009-2014 Hans Beckerus (hans.beckerus#AT#gmail.com) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/dirlist.c b/dirlist.c index 7aa9367..3e6607e 100644 --- a/dirlist.c +++ b/dirlist.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2009-2013 Hans Beckerus (hans.beckerus#AT#gmail.com) + Copyright (C) 2009-2014 Hans Beckerus (hans.beckerus#AT#gmail.com) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -36,14 +36,14 @@ ***************************************************************************** * ****************************************************************************/ -static inline int swap(struct dir_entry_list *A, struct dir_entry_list *B) { +static inline int swap(struct dir_entry_list *A, struct dir_entry_list *B) +{ int swap = strcmp(A->entry.name, B->entry.name); swap = !swap ? A->entry.type > B->entry.type : swap; if (swap > 0) { const struct dir_entry TMP = B->entry; B->entry = A->entry; A->entry = TMP; - return 1; } return 0; @@ -163,5 +163,3 @@ struct dir_entry_list *dir_entry_add(struct dir_entry_list *l, const char *key, return l; } - - diff --git a/dirlist.h b/dirlist.h index 0e57797..5f5b561 100644 --- a/dirlist.h +++ b/dirlist.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2009-2013 Hans Beckerus (hans.beckerus#AT#gmail.com) + Copyright (C) 2009-2014 Hans Beckerus (hans.beckerus#AT#gmail.com) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/dllext.cpp b/dllext.cpp index ea0f069..25b561b 100644 --- a/dllext.cpp +++ b/dllext.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2009-2013 Hans Beckerus (hans.beckerus#AT#gmail.com) + Copyright (C) 2009-2014 Hans Beckerus (hans.beckerus#AT#gmail.com) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/dllext.hpp b/dllext.hpp index 03c108b..2ca80b2 100644 --- a/dllext.hpp +++ b/dllext.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2009-2013 Hans Beckerus (hans.beckerus#AT#gmail.com) + Copyright (C) 2009-2014 Hans Beckerus (hans.beckerus#AT#gmail.com) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/dllwrapper.h b/dllwrapper.h index 80257a0..618ab02 100644 --- a/dllwrapper.h +++ b/dllwrapper.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2009-2013 Hans Beckerus (hans.beckerus#AT#gmail.com) + Copyright (C) 2009-2014 Hans Beckerus (hans.beckerus#AT#gmail.com) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/filecache.c b/filecache.c index 6e367f9..22aa971 100644 --- a/filecache.c +++ b/filecache.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2009-2013 Hans Beckerus (hans.beckerus@gmail.com) + Copyright (C) 2009-2014 Hans Beckerus (hans.beckerus@gmail.com) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/filecache.h b/filecache.h index bf1335a..ec15d81 100644 --- a/filecache.h +++ b/filecache.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2009-2013 Hans Beckerus (hans.beckerus@gmail.com) + Copyright (C) 2009-2014 Hans Beckerus (hans.beckerus@gmail.com) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/fileext.hpp b/fileext.hpp index d4693ea..b904877 100644 --- a/fileext.hpp +++ b/fileext.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2009-2013 Hans Beckerus (hans.beckerus#AT#gmail.com) + Copyright (C) 2009-2014 Hans Beckerus (hans.beckerus#AT#gmail.com) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/hash.h b/hash.h index 4625dc6..f029dcc 100644 --- a/hash.h +++ b/hash.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2009-2013 Hans Beckerus (hans.beckerus#AT#gmail.com) + Copyright (C) 2009-2014 Hans Beckerus (hans.beckerus#AT#gmail.com) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/index.h b/index.h index 12cd76d..3cf0143 100644 --- a/index.h +++ b/index.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2009-2013 Hans Beckerus (hans.beckerus#AT#gmail.com) + Copyright (C) 2009-2014 Hans Beckerus (hans.beckerus#AT#gmail.com) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/iobuffer.c b/iobuffer.c index 5ee23b2..2e0e65a 100644 --- a/iobuffer.c +++ b/iobuffer.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2009-2013 Hans Beckerus (hans.beckerus#AT#gmail.com) + Copyright (C) 2009-2014 Hans Beckerus (hans.beckerus#AT#gmail.com) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -49,13 +49,13 @@ size_t readTo(struct io_buf *dest, FILE *fp, int hist) { unsigned tot = 0; pthread_mutex_lock(&io_mutex); - unsigned int lri = dest->ri; /* read once */ unsigned int lwi = dest->wi; /* read once */ + unsigned int lri = dest->ri; + pthread_mutex_unlock(&io_mutex); size_t left = SPACE_LEFT(lri, lwi) - 1; /* -1 to avoid wi = ri */ if (IOB_HIST_SZ && hist == IOB_SAVE_HIST) { left = left > IOB_HIST_SZ ? left - IOB_HIST_SZ : 0; if (!left) { - pthread_mutex_unlock(&io_mutex); return 0; /* quick exit */ } } @@ -77,10 +77,12 @@ size_t readTo(struct io_buf *dest, FILE *fp, int hist) chunk -= n; chunk = !chunk ? left : chunk; } - dest->offset += tot; + pthread_mutex_lock(&io_mutex); dest->wi = lwi; - dest->used = SPACE_USED(lri, lwi); + dest->used = SPACE_USED(dest->ri, lwi); /* dest->ri might have changed */ pthread_mutex_unlock(&io_mutex); + MB(); + dest->offset += tot; return tot; } @@ -107,7 +109,6 @@ size_t readFrom(char *dest, struct io_buf *src, size_t size, size_t off) chunk = chunk < size ? chunk : size; /* reconsider assumption */ while (size) { memcpy(dest, src->data_p + lri, chunk); - used -= chunk; lri = (lri + chunk) & (IOB_SZ - 1); tot += chunk; size -= chunk; @@ -116,7 +117,7 @@ size_t readFrom(char *dest, struct io_buf *src, size_t size, size_t off) } pthread_mutex_lock(&io_mutex); src->ri = lri; - src->used = used; + src->used -= tot; /* src->used might have changed */ pthread_mutex_unlock(&io_mutex); return tot; diff --git a/iobuffer.h b/iobuffer.h index 202991e..5530b52 100644 --- a/iobuffer.h +++ b/iobuffer.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2009-2013 Hans Beckerus (hans.beckerus#AT#gmail.com) + Copyright (C) 2009-2014 Hans Beckerus (hans.beckerus#AT#gmail.com) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/mkr2i.c b/mkr2i.c index bd3bdab..f9b8b94 100644 --- a/mkr2i.c +++ b/mkr2i.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2009-2013 Hans Beckerus (hans.beckerus#AT#gmail.com) + Copyright (C) 2009-2014 Hans Beckerus (hans.beckerus#AT#gmail.com) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/optdb.c b/optdb.c index 4be9b21..1261804 100644 --- a/optdb.c +++ b/optdb.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2009-2013 Hans Beckerus (hans.beckerus#AT#gmail.com) + Copyright (C) 2009-2014 Hans Beckerus (hans.beckerus#AT#gmail.com) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/optdb.h b/optdb.h index be457d9..92b5e58 100644 --- a/optdb.h +++ b/optdb.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2009-2013 Hans Beckerus (hans.beckerus#AT#gmail.com) + Copyright (C) 2009-2014 Hans Beckerus (hans.beckerus#AT#gmail.com) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/platform.h b/platform.h index ab3fd73..fa5b9aa 100644 --- a/platform.h +++ b/platform.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2009-2013 Hans Beckerus (hans.beckerus#AT#gmail.com) + Copyright (C) 2009-2014 Hans Beckerus (hans.beckerus#AT#gmail.com) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -95,7 +95,11 @@ #endif #ifdef __GNUC__ +#ifdef HAVE_SYNC_SYNCHRONIZE +#define MB() __sync_synchronize() +#else #define MB() do{ __asm__ __volatile__ ("" ::: "memory"); } while(0) +#endif #else #warning Check code for MB() on current platform #define MB() diff --git a/rar2fs.1 b/rar2fs.1 index adf33bf..51d2c78 100644 --- a/rar2fs.1 +++ b/rar2fs.1 @@ -1,4 +1,4 @@ -.TH RAR2FS 1 "v\ " "Wed, May 22, 2013" "User Commands" +.TH RAR2FS 1 "v\ " "Wed, May 22, 2014" "User Commands" .SH NAME .B rar2fs \- FUSE file system for reading RAR archives diff --git a/rar2fs.c b/rar2fs.c index 1028509..1576253 100644 --- a/rar2fs.c +++ b/rar2fs.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2009-2013 Hans Beckerus (hans.beckerus#AT#gmail.com) + Copyright (C) 2009-2014 Hans Beckerus (hans.beckerus#AT#gmail.com) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -112,27 +112,34 @@ struct io_handle { #define IO_TYPE_RAW 2 #define IO_TYPE_ISO 3 #define IO_TYPE_INFO 4 +#define IO_TYPE_DIR 5 union { struct io_context *context; /* type = IO_TYPE_RAR/IO_TYPE_RAW */ int fd; /* type = IO_TYPE_NRM/IO_TYPE_ISO */ + DIR *dp; /* type = IO_TYPE_DIR */ void *buf_p; /* type = IO_TYPE_INFO */ uintptr_t bits; } u; dir_elem_t *entry_p; /* type = IO_TYPE_ISO */ + char *path; /* type = IO_TYPE_DIR */ }; #define FH_ZERO(fh) ((fh) = 0) #define FH_ISSET(fh) (fh) #define FH_SETCONTEXT(fh, v) (FH_TOIO(fh)->u.context = (v)) #define FH_SETFD(fh, v) (FH_TOIO(fh)->u.fd = (v)) +#define FH_SETDP(fh, v) (FH_TOIO(fh)->u.dp = (v)) #define FH_SETBUF(fh, v) (FH_TOIO(fh)->u.buf_p = (v)) #define FH_SETIO(fh, v) ((fh) = (uintptr_t)(v)) #define FH_SETENTRY(fh, v) (FH_TOIO(fh)->entry_p = (v)) +#define FH_SETPATH(fh, v) (FH_TOIO(fh)->path = (v)) #define FH_SETTYPE(fh, v) (FH_TOIO(fh)->type = (v)) #define FH_TOCONTEXT(fh) (FH_TOIO(fh)->u.context) #define FH_TOFD(fh) (FH_TOIO(fh)->u.fd) +#define FH_TODP(fh) (FH_TOIO(fh)->u.dp) #define FH_TOBUF(fh) (FH_TOIO(fh)->u.buf_p) #define FH_TOENTRY(fh) (FH_TOIO(fh)->entry_p) +#define FH_TOPATH(fh) (FH_TOIO(fh)->path) #define FH_TOIO(fh) ((struct io_handle*)(uintptr_t)(fh)) #define WAIT_THREAD(pfd) \ @@ -882,7 +889,7 @@ static int lread_info(char *buf, size_t size, off_t offset, if (c > 0) return c; } - /* Nothing to output */ + /* Nothing to output (EOF) */ return 0; } @@ -1094,7 +1101,6 @@ static int lread_rar(char *buf, size_t size, off_t offset, } } } - fi->direct_io = 1; pthread_mutex_lock(&file_access_mutex); e_p = filecache_get(op->entry_p->name_p); if (e_p) @@ -1134,7 +1140,7 @@ static int lread_rar(char *buf, size_t size, off_t offset, * fake data to propagate in sub-sequent reads. * This case is very likely for multi-part AVI 2.0. */ - if (op->seq < 15 && ((offset + size) - op->buf->offset) + if (op->seq < 25 && ((offset + size) - op->buf->offset) > (IOB_SZ - IOB_HIST_SZ)) { dir_elem_t *e_p; /* "real" cache entry */ printd(3, "seq=%d long jump hack2 offset=%" PRIu64 "," @@ -1142,7 +1148,6 @@ static int lread_rar(char *buf, size_t size, off_t offset, op->seq, offset, size, op->buf->offset); op->seq--; /* pretend it never happened */ - fi->direct_io = 1; pthread_mutex_lock(&file_access_mutex); e_p = filecache_get(op->entry_p->name_p); if (e_p) @@ -1209,11 +1214,12 @@ static int lread_rar(char *buf, size_t size, off_t offset, ***************************************************************************** * ****************************************************************************/ -static int lflush(const char *path, struct fuse_file_info *fi) +static int lflush(struct fuse_file_info *fi) { - ENTER_("%s", path); - (void)path; /* touch */ + ENTER_(); + (void)fi; /* touch */ + return 0; } @@ -1221,11 +1227,10 @@ static int lflush(const char *path, struct fuse_file_info *fi) ***************************************************************************** * ****************************************************************************/ -static int lrelease(const char *path, struct fuse_file_info *fi) +static int lrelease(struct fuse_file_info *fi) { - ENTER_("%s", path); + ENTER_(); - (void)path; /* touch */ if (FH_TOIO(fi->fh)->type == IO_TYPE_INFO) { if (FH_TOBUF(fi->fh)) free(FH_TOBUF(fi->fh)); @@ -1236,6 +1241,7 @@ static int lrelease(const char *path, struct fuse_file_info *fi) if (FH_TOENTRY(fi->fh)) filecache_freeclone(FH_TOENTRY(fi->fh)); } + printd(3, "(%05d) %s [%-16p]\n", getpid(), "FREE", fi->fh); free(FH_TOIO(fi->fh)); FH_ZERO(fi->fh); return 0; @@ -1245,14 +1251,13 @@ static int lrelease(const char *path, struct fuse_file_info *fi) ***************************************************************************** * ****************************************************************************/ -static int lread(const char *path, char *buffer, size_t size, off_t offset, +static int lread(char *buffer, size_t size, off_t offset, struct fuse_file_info *fi) { int res; - ENTER_("%s size = %zu, offset = %" PRIu64, path, size, offset); - - (void)path; /* touch */ + ENTER_("%d size = %zu, offset = %" PRIu64, FH_TOFD(fi->fh), + size, offset); res = pread(FH_TOFD(fi->fh), buffer, size, offset); if (res == -1) @@ -2703,7 +2708,7 @@ static int rar2_getattr2(const char *path, struct stat *stbuf) static void dump_dir_list(const char *path, void *buffer, fuse_fill_dir_t filler, struct dir_entry_list *next) { - ENTER_(); + ENTER_("%s", path); int do_inval_cache = 1; @@ -2733,6 +2738,42 @@ static void dump_dir_list(const char *path, void *buffer, fuse_fill_dir_t filler } } +/*! + ***************************************************************************** + * + ****************************************************************************/ +static int rar2_opendir(const char *path, struct fuse_file_info *fi) +{ + ENTER_("%s", path); + + DIR *dp = NULL; + char *root; + ABS_ROOT(root, path); + + dp = opendir(root); + if (dp == NULL && errno == ENOENT) { + if (filecache_get(path)) + goto opendir_ok; + return -ENOENT; + } + if (dp == NULL) + return -errno; + +opendir_ok: + + FH_SETIO(fi->fh, malloc(sizeof(struct io_handle))); + if (!FH_ISSET(fi->fh)) { + closedir(dp); + return -ENOMEM; + } + FH_SETTYPE(fi->fh, IO_TYPE_DIR); + FH_SETENTRY(fi->fh, NULL); + FH_SETDP(fi->fh, dp); + FH_SETPATH(fi->fh, strdup(path)); + + return 0; +} + /*! ***************************************************************************** * @@ -2740,30 +2781,33 @@ static void dump_dir_list(const char *path, void *buffer, fuse_fill_dir_t filler static int rar2_readdir(const char *path, void *buffer, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi) { - ENTER_("%s", path); + ENTER_("%s", (path ? path : "")); + (void)path; /* touch */ (void)offset; /* touch */ - (void)fi; /* touch */ + + assert(FH_ISSET(fi->fh) && "bad I/O handle"); + + struct io_handle *io = FH_TOIO(fi->fh); + if (io == NULL) + return -EIO; struct dir_entry_list dir_list; /* internal list root */ struct dir_entry_list *next = &dir_list; dir_list_open(next); - DIR *dp; - char *root; - ABS_ROOT(root, path); - - dp = opendir(root); + DIR *dp = FH_TODP(fi->fh); if (dp != NULL) { - readdir_scan(path, root, &next); - (void)closedir(dp); + char *root; + ABS_ROOT(root, FH_TOPATH(fi->fh)); + readdir_scan(FH_TOPATH(fi->fh), root, &next); goto dump_buff; } int vol = 1; pthread_mutex_lock(&file_access_mutex); - dir_elem_t *entry_p = filecache_get(path); + dir_elem_t *entry_p = filecache_get(FH_TOPATH(fi->fh)); if (entry_p) { char *tmp = strdup(entry_p->rar_p); int multipart = entry_p->flags.multipart; @@ -2772,7 +2816,7 @@ static int rar2_readdir(const char *path, void *buffer, fuse_fill_dir_t filler, if (multipart) { int vol_end = OPT_INT(OPT_KEY_SEEK_LENGTH, 0); printd(3, "Search for local directory in %s\n", tmp); - while (!listrar(path, &next, tmp)) { + while (!listrar(entry_p->name_p, &next, tmp)) { ++vol; if (vol_end && vol_end < vol) goto fill_buff; @@ -2782,7 +2826,7 @@ static int rar2_readdir(const char *path, void *buffer, fuse_fill_dir_t filler, } else { if (tmp) { printd(3, "Search for local directory in %s\n", tmp); - if (!listrar(path, &next, tmp)) { + if (!listrar(entry_p->name_p, &next, tmp)) { free(tmp); goto fill_buff; } @@ -2795,12 +2839,7 @@ static int rar2_readdir(const char *path, void *buffer, fuse_fill_dir_t filler, if (vol == 1) { dir_list_free(&dir_list); - /* - * Fuse bug!? Returning -ENOENT here seems to be - * silently ignored. Typically errno is here set to - * ESPIPE (aka "Illegal seek"). - */ - return -errno; + return -ENOENT; } fill_buff: @@ -2811,7 +2850,7 @@ static int rar2_readdir(const char *path, void *buffer, fuse_fill_dir_t filler, dump_buff: dir_list_close(&dir_list); - dump_dir_list(path, buffer, filler, &dir_list); + dump_dir_list(FH_TOPATH(fi->fh), buffer, filler, &dir_list); dir_list_free(&dir_list); return 0; @@ -2825,10 +2864,10 @@ static int rar2_readdir2(const char *path, void *buffer, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi) { - ENTER_("%s", path); + ENTER_("%s", (path ? path : "")); + (void)path; /* touch */ (void)offset; /* touch */ - (void)fi; /* touch */ struct dir_entry_list dir_list; /* internal list root */ struct dir_entry_list *next = &dir_list; @@ -2838,7 +2877,7 @@ static int rar2_readdir2(const char *path, void *buffer, int c_end = OPT_INT(OPT_KEY_SEEK_LENGTH, 0); struct dir_entry_list *arch_next = arch_list_root.next; while (arch_next) { - (void)listrar(path, &next, arch_next->entry.name); + (void)listrar(FH_TOPATH(fi->fh), &next, arch_next->entry.name); if (c_end && ++c == c_end) break; arch_next = arch_next->next; @@ -2848,12 +2887,32 @@ static int rar2_readdir2(const char *path, void *buffer, filler(buffer, "..", NULL, 0); dir_list_close(&dir_list); - dump_dir_list(path, buffer, filler, &dir_list); + dump_dir_list(FH_TOPATH(fi->fh), buffer, filler, &dir_list); dir_list_free(&dir_list); return 0; } +/*! + ***************************************************************************** + * + ****************************************************************************/ +static int rar2_releasedir(const char *path, struct fuse_file_info *fi) +{ + ENTER_("%s", (path ? path : "")); + + (void)path; + struct io_handle *io = FH_TOIO(fi->fh); + if (io == NULL) + return -EIO; + + closedir(FH_TODP(fi->fh)); + free(FH_TOPATH(fi->fh)); + free(FH_TOIO(fi->fh)); + FH_ZERO(fi->fh); + return 0; +} + /*! ***************************************************************************** * @@ -3210,7 +3269,7 @@ static int rar2_open(const char *path, struct fuse_file_info *fi) FH_SETIO(fi->fh, io); FH_SETTYPE(fi->fh, IO_TYPE_INFO); FH_SETBUF(fi->fh, wcb); - fi->direct_io = 1; + fi->direct_io = 1; /* skip cache */ extract_rar_file_info(e_p, wcb); filecache_freeclone(e_p); return 0; @@ -3325,6 +3384,16 @@ static int rar2_open(const char *path, struct fuse_file_info *fi) op->volHdl = NULL; } + /* + * Disable flushing the kernel cache of the file contents on + * every open(). This should only be enabled on files, where + * the file data is never changed externally (not through the + * mounted FUSE filesystem). + * Since the file contents will never change this should save + * us from some user space calls! + */ + fi->keep_cache = 1; + /* * Make sure cache entry is filled in completely * before cloning it @@ -3391,17 +3460,6 @@ static int rar2_open(const char *path, struct fuse_file_info *fi) pthread_mutex_init(&op->mutex, NULL); - /* - * Disable flushing the cache of the file contents on every open(). - * This is important to make sure FUSE does not force read from an - * old offset. That could break the logic for compressed/encrypted - * archives since the I/O context will become out-of-sync. - * This should only be enabled on files, where the file data is never - * changed externally (not through the mounted FUSE filesystem). - * But first see 'direct_io' below. - */ - fi->keep_cache = 1; - /* * The below will take precedence over keep_cache. * This flag will allow the filesystem to bypass the page cache using @@ -3412,8 +3470,10 @@ static int rar2_open(const char *path, struct fuse_file_info *fi) * information to be propagated to sub-sequent reads. Setting this * flag will force _all_ reads to enter the filesystem. */ +#if 0 /* disable for now */ if (entry_p->flags.direct_io) fi->direct_io = 1; +#endif /* Create reader thread */ op->terminate = 1; @@ -3571,11 +3631,14 @@ static void rar2_destroy(void *data) * ****************************************************************************/ static int rar2_flush(const char *path, struct fuse_file_info *fi) -{ - ENTER_("%s", path); - printd(3, "(%05d) %-8s%s [%-16p][called from %05d]\n", getpid(), - "FLUSH", path, FH_TOCONTEXT(fi->fh), fuse_get_context()->pid); - return lflush(path, fi); +{ + ENTER_("%s", (path ? path : "")); + + (void)path; /* touch */ + + printd(3, "(%05d) %s [%-16p][called from %05d]\n", getpid(), + "FLUSH", FH_TOCONTEXT(fi->fh), fuse_get_context()->pid); + return lflush(fi); } /*! @@ -3645,15 +3708,14 @@ static int rar2_statfs(const char *path, struct statvfs *vfs) ****************************************************************************/ static int rar2_release(const char *path, struct fuse_file_info *fi) { - ENTER_("%s", path); - printd(3, "(%05d) %-8s%s [%-16p]\n", getpid(), "RELEASE", path, - FH_TOCONTEXT(fi->fh)); - if (!FH_ISSET(fi->fh)) { - pthread_mutex_lock(&file_access_mutex); - filecache_invalidate(path); - pthread_mutex_unlock(&file_access_mutex); + ENTER_("%s", (path ? path : "")); + + (void)path; /* touch */ + + if (!FH_ISSET(fi->fh)) return 0; - } + + printd(3, "(%05d) %s [%-16p]\n", getpid(), "RELEASE", fi->fh); if (FH_TOIO(fi->fh)->type == IO_TYPE_RAR || FH_TOIO(fi->fh)->type == IO_TYPE_RAW) { @@ -3705,7 +3767,7 @@ static int rar2_release(const char *path, struct fuse_file_info *fi) pthread_mutex_destroy(&op->mutex); } } - printd(3, "(%05d) %-8s%s [%-16p]\n", getpid(), "FREE", path, op); + printd(3, "(%05d) %s [%-16p]\n", getpid(), "FREE", fi->fh); if (op->buf) { /* XXX clean up */ #ifdef HAVE_MMAP @@ -3726,9 +3788,7 @@ static int rar2_release(const char *path, struct fuse_file_info *fi) free(FH_TOIO(fi->fh)); FH_ZERO(fi->fh); } else { - char *root; - ABS_ROOT(root, path); - return lrelease(root, fi); + return lrelease(fi); } return 0; @@ -3745,37 +3805,26 @@ static int rar2_read(const char *path, char *buffer, size_t size, off_t offset, struct io_handle *io; assert(FH_ISSET(fi->fh) && "bad I/O handle"); + (void)path; /* touch */ + io = FH_TOIO(fi->fh); if (!io) return -EIO; -#if 0 - int direct_io = fi->direct_io; -#endif - ENTER_("%s size=%zu, offset=%" PRIu64 ", fh=%" PRIu64, path, size, offset, fi->fh); + ENTER_("size=%zu, offset=%" PRIu64 ", fh=%" PRIu64, size, offset, fi->fh); if (io->type == IO_TYPE_NRM) { - char *root; - ABS_ROOT(root, path); - res = lread(root, buffer, size, offset, fi); + res = lread(buffer, size, offset, fi); } else if (io->type == IO_TYPE_ISO) { - char *root; - ABS_ROOT(root, io->entry_p->file_p); - res = lread(root, buffer, size, offset, fi); + res = lread(buffer, size, offset, fi); } else if (io->type == IO_TYPE_RAW) { res = lread_raw(buffer, size, offset, fi); } else if (io->type == IO_TYPE_INFO) { res = lread_info(buffer, size, offset, fi); - } else { + } else if (io->type == IO_TYPE_RAR) { res = lread_rar(buffer, size, offset, fi); - } - -#if 0 - if (res < 0 && direct_io) { - errno = -res; /* convert to proper errno? */ - return -1; - } -#endif + } else + return -EIO; return res; } @@ -3803,12 +3852,12 @@ static int rar2_truncate(const char *path, off_t offset) static int rar2_write(const char *path, const char *buffer, size_t size, off_t offset, struct fuse_file_info *fi) { - char *root; ssize_t n; - ENTER_("%s", path); + ENTER_("%s", (path ? path : "")); + + (void)path; /* touch */ - ABS_ROOT(root, path); n = pwrite(FH_TOFD(fi->fh), buffer, size, offset); return n >= 0 ? n : -errno; } @@ -4333,6 +4382,8 @@ static struct fuse_operations rar2_operations = { .destroy = rar2_destroy, .open = rar2_open, .release = rar2_release, + .opendir = rar2_opendir, + .releasedir = rar2_releasedir, .read = rar2_read, .flush = rar2_flush, .readlink = rar2_readlink, @@ -4342,6 +4393,12 @@ static struct fuse_operations rar2_operations = { .listxattr = rar2_listxattr, .removexattr = rar2_removexattr, #endif +#if FUSE_MAJOR_VERSION == 2 && FUSE_MINOR_VERSION > 7 + .flag_nullpath_ok = 1, +#endif +#if FUSE_MAJOR_VERSION > 2 || (FUSE_MAJOR_VERSION == 2 && FUSE_MINOR_VERSION == 9) + .flag_nopath = 1, +#endif }; struct work_task_data { @@ -4587,7 +4644,7 @@ static void print_version() src_rev[0] = '\0'; #endif #endif - printf("rar2fs v%u.%u.%u%s (DLL version %d) Copyright (C) 2009-2013 Hans Beckerus\n", + printf("rar2fs v%u.%u.%u%s (DLL version %d) Copyright (C) 2009-2014 Hans Beckerus\n", RAR2FS_MAJOR_VER, RAR2FS_MINOR_VER, RAR2FS_PATCH_LVL, src_rev, diff --git a/sighandler.c b/sighandler.c index ce35457..36ba4c6 100644 --- a/sighandler.c +++ b/sighandler.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2009-2013 Hans Beckerus (hans.beckerus#AT#gmail.com) + Copyright (C) 2009-2014 Hans Beckerus (hans.beckerus#AT#gmail.com) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sighandler.h b/sighandler.h index 2f8ae10..d1284dc 100644 --- a/sighandler.h +++ b/sighandler.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2009-2013 Hans Beckerus (hans.beckerus#AT#gmail.com) + Copyright (C) 2009-2014 Hans Beckerus (hans.beckerus#AT#gmail.com) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/version.h b/version.h index 7295fd1..c7cf1b0 100644 --- a/version.h +++ b/version.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2009-2013 Hans Beckerus (hans.beckerus#AT#gmail.com) + Copyright (C) 2009-2014 Hans Beckerus (hans.beckerus#AT#gmail.com) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -31,6 +31,6 @@ #define RAR2FS_MAJOR_VER 1 #define RAR2FS_MINOR_VER 19 -#define RAR2FS_PATCH_LVL 5 +#define RAR2FS_PATCH_LVL 8 #endif