From d141ea44c1d901c27f61865808e8c5f9801b2606 Mon Sep 17 00:00:00 2001 From: Nikolaus Rath Date: Sun, 6 Aug 2017 11:06:42 +0200 Subject: Re-enabled writeback cache. Fixes: #72. --- ChangeLog.rst | 3 +-- README.rst | 10 ++++++++++ sshfs.c | 30 +++++++++++++++++++++++------- test/test_sshfs.py | 3 ++- 4 files changed, 36 insertions(+), 10 deletions(-) diff --git a/ChangeLog.rst b/ChangeLog.rst index 5285523..973d86b 100644 --- a/ChangeLog.rst +++ b/ChangeLog.rst @@ -1,8 +1,7 @@ Unreleased Changes ------------------ -* Truly disable the writeback cache, instead of just adjusting the - default and printing a warning when explicitly enabled. +* Re-enabled writeback cache. * SSHFS now supports O_APPEND. Release 3.1.0 (2017-08-04) diff --git a/README.rst b/README.rst index 91c3ef5..1ec2d72 100644 --- a/README.rst +++ b/README.rst @@ -116,6 +116,16 @@ individual files when seen through an SSHFS mount, i.e. they will appear to have different inodes and an *st_nlink* value of 1. +O_APPEND +~~~~~~~~ + +When writeback caching is enabled, SSHFS cannot reliably support the +``O_APPEND`` open flag and thus signals an error on open. To enable +support for unreliable ``O_APPEND`` (which may overwrite data if the +file changes on the server at a bad time), mount the file system with +``-o unreliable_append``. + + Getting Help ------------ diff --git a/sshfs.c b/sshfs.c index cc35577..a76ae8a 100644 --- a/sshfs.c +++ b/sshfs.c @@ -216,6 +216,7 @@ struct sshfs { int rename_workaround; int truncate_workaround; int buflimit_workaround; + int unrel_append; int fstat_workaround; int transform_symlinks; int follow_symlinks; @@ -409,6 +410,7 @@ static struct fuse_opt sshfs_opts[] = { SSHFS_OPT("dir_cache=no", dir_cache, 0), SSHFS_OPT("writeback_cache=yes", writeback_cache, 1), SSHFS_OPT("writeback_cache=no", writeback_cache, 0), + SSHFS_OPT("unreliable_append", unrel_append, 1), SSHFS_OPT("-h", show_help, 1), SSHFS_OPT("--help", show_help, 1), @@ -2500,6 +2502,24 @@ static int sshfs_open_common(const char *path, mode_t mode, if (sshfs.dir_cache) wrctr = cache_get_write_ctr(); + /* With writeback cache, kernel may send read requests even + when userspace opened write-only */ + if (sshfs.writeback_cache && + (fi->flags & O_ACCMODE) == O_WRONLY) { + fi->flags &= ~O_ACCMODE; + fi->flags |= O_RDWR; + } + + /* Having the kernel handle O_APPEND doesn't work reliably, if + the file changes on the server at the wrong time, we will + overwrite data instead of appending. */ + if ((fi->flags & O_APPEND) && sshfs.writeback_cache) { + if(sshfs.unrel_append) + fi->flags &= ~O_APPEND; + else + return -EINVAL; + } + if ((fi->flags & O_ACCMODE) == O_RDONLY) pflags = SSH_FXF_READ; else if((fi->flags & O_ACCMODE) == O_WRONLY) @@ -3344,6 +3364,7 @@ static void usage(const char *progname) " -o sshfs_sync synchronous writes\n" " -o no_readahead synchronous reads (no speculative readahead)\n" " -o sync_readdir synchronous readdir\n" +" -o unreliable_append Enable (unreliable) O_APPEND support\n" " -d, --debug print some debugging information (implies -f)\n" " -o writeback_cache=BOOL enable writeback cache {yes,no} (default: yes)\n" " -o dir_cache=BOOL enable caching of directory contents (names,\n" @@ -3855,7 +3876,8 @@ int main(int argc, char *argv[]) sshfs.wfd = -1; sshfs.ptyfd = -1; sshfs.dir_cache = 1; - sshfs.writeback_cache = 0; + sshfs.writeback_cache = 1; + sshfs.unrel_append = 0; sshfs.show_help = 0; sshfs.show_version = 0; sshfs.singlethread = 0; @@ -3904,12 +3926,6 @@ int main(int argc, char *argv[]) exit(1); } - if(sshfs.writeback_cache) { - printf("NOTICE: writeback cache is disabled in this release due to potential\n" - "dataloss. It will be re-enabled in a future SSHFS release.\n"); - sshfs.writeback_cache = 0; - } - if (sshfs.idmap == IDMAP_USER) sshfs.detect_uid = 1; else if (sshfs.idmap == IDMAP_FILE) { diff --git a/test/test_sshfs.py b/test/test_sshfs.py index 446a617..224179f 100755 --- a/test/test_sshfs.py +++ b/test/test_sshfs.py @@ -66,7 +66,8 @@ def test_sshfs(tmpdir, debug, cache_timeout, sync_rd, cmdline += [ '-o', 'sync_readdir' ] if writeback: - cmdline += [ '-o', 'writeback_cache=yes' ] + cmdline += [ '-o', 'writeback_cache=yes', + '-o', 'unreliable_append' ] else: cmdline += [ '-o', 'writeback_cache=no' ] -- cgit v1.2.3