Hello community, here is the log from the commit of package s3backer for openSUSE:Factory checked in at 2013-06-05 13:38:00 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/s3backer (Old) and /work/SRC/openSUSE:Factory/.s3backer.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "s3backer" Changes: -------- --- /work/SRC/openSUSE:Factory/s3backer/s3backer.changes 2013-04-03 13:06:23.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.s3backer.new/s3backer.changes 2013-06-05 14:24:47.000000000 +0200 @@ -1,0 +2,7 @@ +Wed May 29 17:49:29 UTC 2013 - [email protected] + +- Update to version 1.3.5 + + Check for duplicate mount at startup (issue #10) + + Minor spec file cleanups + +------------------------------------------------------------------- Old: ---- s3backer-1.3.4.tar.gz New: ---- s3backer-1.3.5.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ s3backer.spec ++++++ --- /var/tmp/diff_new_pack.mdgd2q/_old 2013-06-05 14:24:47.000000000 +0200 +++ /var/tmp/diff_new_pack.mdgd2q/_new 2013-06-05 14:24:47.000000000 +0200 @@ -18,7 +18,7 @@ Name: s3backer -Version: 1.3.4 +Version: 1.3.5 Release: 0 Summary: FUSE-based single file backing store via Amazon S3 License: GPL-2.0+ @@ -61,22 +61,17 @@ %build export SUSE_ASNEEDED=0 %{configure} -make +make %{?_smp_mflags} %install -rm -rf ${RPM_BUILD_ROOT} -%{makeinstall} -install COPYING %{buildroot}%{_datadir}/doc/packages/%{name}/ -rm -f %{buildroot}%{_datadir}/doc/packages/%{name}/INSTALL +make install DESTDIR='%{buildroot}' +install -m 0644 COPYING %{buildroot}%{_docdir}/%{name}/ +rm -f %{buildroot}%{_docdir}/%{name}/INSTALL %files -%defattr(0644,root,root,0755) -%attr(0755,root,root) %{_bindir}/%{name} -%if 0%{?mandriva_version} -%attr(0644,root,root) %{_mandir}/man1/%{name}.1 -%else -%attr(0644,root,root) %{_mandir}/man1/%{name}.1.gz -%endif -%doc %{_datadir}/doc/packages/%{name} +%defattr(-,root,root,-) +%{_bindir}/* +%{_mandir}/man1/* +%{_docdir}/%{name} %changelog ++++++ s3backer-1.3.4.tar.gz -> s3backer-1.3.5.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/s3backer-1.3.4/CHANGES new/s3backer-1.3.5/CHANGES --- old/s3backer-1.3.4/CHANGES 2013-04-03 03:44:48.000000000 +0200 +++ new/s3backer-1.3.5/CHANGES 2013-05-29 19:43:01.000000000 +0200 @@ -1,3 +1,7 @@ +Version 1.3.5 (r485) released 29 May 2013 + + - Check for duplicate mount at startup (issue #10) + - Remove obsolete backward-compatibility block size check Version 1.3.4 (r476) released 2 Apr 2013 @@ -134,4 +138,4 @@ Version 1.0.0 released 19 June 2008 -$Id: CHANGES 476 2013-04-03 01:44:44Z archie.cobbs $ +$Id: CHANGES 485 2013-05-29 17:42:59Z archie.cobbs $ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/s3backer-1.3.4/Makefile.am new/s3backer-1.3.5/Makefile.am --- old/s3backer-1.3.4/Makefile.am 2011-02-01 18:31:15.000000000 +0100 +++ new/s3backer-1.3.5/Makefile.am 2013-05-11 19:07:54.000000000 +0200 @@ -19,7 +19,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301, USA. # -# $Id: Makefile.am 448 2011-02-01 17:31:15Z archie.cobbs $ +# $Id: Makefile.am 482 2013-05-11 17:07:49Z archie.cobbs $ # bin_PROGRAMS= s3backer @@ -35,6 +35,7 @@ fuse_ops.h \ hash.h \ http_io.h \ + reset.h \ test_io.h \ s3b_config.h @@ -55,6 +56,7 @@ fuse_ops.c \ hash.c \ http_io.c \ + reset.c \ s3b_config.c \ test_io.c \ svnrev.c @@ -67,6 +69,7 @@ erase.c \ hash.c \ http_io.c \ + reset.c \ s3b_config.c \ test_io.c \ svnrev.c @@ -76,5 +79,5 @@ SUBDIRS= debian svnrev.c: - printf 'const int s3backer_svnrev = %u;\n' `svn info | grep -w Rev | sed -r 's/^.*Rev: //g'` > svnrev.c + printf 'const int s3backer_svnrev = %u;\n' `svn info | grep -w Rev | sed 's/^.*Rev: //g'` > svnrev.c diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/s3backer-1.3.4/Makefile.in new/s3backer-1.3.5/Makefile.in --- old/s3backer-1.3.4/Makefile.in 2013-04-03 03:45:21.000000000 +0200 +++ new/s3backer-1.3.5/Makefile.in 2013-05-29 19:43:26.000000000 +0200 @@ -34,7 +34,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301, USA. # -# $Id: Makefile.am 448 2011-02-01 17:31:15Z archie.cobbs $ +# $Id: Makefile.am 482 2013-05-11 17:07:49Z archie.cobbs $ # @@ -99,14 +99,15 @@ am_s3backer_OBJECTS = main.$(OBJEXT) block_cache.$(OBJEXT) \ block_part.$(OBJEXT) dcache.$(OBJEXT) ec_protect.$(OBJEXT) \ erase.$(OBJEXT) fuse_ops.$(OBJEXT) hash.$(OBJEXT) \ - http_io.$(OBJEXT) s3b_config.$(OBJEXT) test_io.$(OBJEXT) \ - svnrev.$(OBJEXT) + http_io.$(OBJEXT) reset.$(OBJEXT) s3b_config.$(OBJEXT) \ + test_io.$(OBJEXT) svnrev.$(OBJEXT) s3backer_OBJECTS = $(am_s3backer_OBJECTS) s3backer_LDADD = $(LDADD) am_tester_OBJECTS = tester.$(OBJEXT) block_cache.$(OBJEXT) \ block_part.$(OBJEXT) dcache.$(OBJEXT) ec_protect.$(OBJEXT) \ erase.$(OBJEXT) hash.$(OBJEXT) http_io.$(OBJEXT) \ - s3b_config.$(OBJEXT) test_io.$(OBJEXT) svnrev.$(OBJEXT) + reset.$(OBJEXT) s3b_config.$(OBJEXT) test_io.$(OBJEXT) \ + svnrev.$(OBJEXT) tester_OBJECTS = $(am_tester_OBJECTS) tester_LDADD = $(LDADD) DEFAULT_INCLUDES = -I.@am__isrc@ @@ -314,6 +315,7 @@ fuse_ops.h \ hash.h \ http_io.h \ + reset.h \ test_io.h \ s3b_config.h @@ -329,6 +331,7 @@ fuse_ops.c \ hash.c \ http_io.c \ + reset.c \ s3b_config.c \ test_io.c \ svnrev.c @@ -341,6 +344,7 @@ erase.c \ hash.c \ http_io.c \ + reset.c \ s3b_config.c \ test_io.c \ svnrev.c @@ -468,6 +472,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hash.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http_io.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/reset.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/s3b_config.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/svnrev.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_io.Po@am__quote@ @@ -1047,7 +1052,7 @@ svnrev.c: - printf 'const int s3backer_svnrev = %u;\n' `svn info | grep -w Rev | sed -r 's/^.*Rev: //g'` > svnrev.c + printf 'const int s3backer_svnrev = %u;\n' `svn info | grep -w Rev | sed 's/^.*Rev: //g'` > svnrev.c # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/s3backer-1.3.4/block_cache.c new/s3backer-1.3.5/block_cache.c --- old/s3backer-1.3.4/block_cache.c 2011-02-01 18:31:15.000000000 +0100 +++ new/s3backer-1.3.5/block_cache.c 2013-05-11 19:07:54.000000000 +0200 @@ -19,7 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. * - * $Id: block_cache.c 448 2011-02-01 17:31:15Z archie.cobbs $ + * $Id: block_cache.c 482 2013-05-11 17:07:49Z archie.cobbs $ */ #include "s3backer.h" @@ -169,6 +169,8 @@ }; /* s3backer_store functions */ +static int block_cache_meta_data(struct s3backer_store *s3b, off_t *file_sizep, u_int *block_sizep); +static int block_cache_set_mounted(struct s3backer_store *s3b, int *old_valuep, int new_value); static int block_cache_read_block(struct s3backer_store *s3b, s3b_block_t block_num, void *dest, u_char *actual_md5, const u_char *expect_md5, int strict); static int block_cache_write_block(struct s3backer_store *s3b, s3b_block_t block_num, const void *src, u_char *md5, @@ -176,6 +178,7 @@ static int block_cache_read_block_part(struct s3backer_store *s3b, s3b_block_t block_num, u_int off, u_int len, void *dest); static int block_cache_write_block_part(struct s3backer_store *s3b, s3b_block_t block_num, u_int off, u_int len, const void *src); static int block_cache_list_blocks(struct s3backer_store *s3b, block_list_func_t *callback, void *arg); +static int block_cache_flush(struct s3backer_store *s3b); static void block_cache_destroy(struct s3backer_store *s3b); /* Other functions */ @@ -228,11 +231,14 @@ (*config->log)(LOG_ERR, "calloc(): %s", strerror(r)); goto fail0; } + s3b->meta_data = block_cache_meta_data; + s3b->set_mounted = block_cache_set_mounted; s3b->read_block = block_cache_read_block; s3b->write_block = block_cache_write_block; s3b->read_block_part = block_cache_read_block_part; s3b->write_block_part = block_cache_write_block_part; s3b->list_blocks = block_cache_list_blocks; + s3b->flush = block_cache_flush; s3b->destroy = block_cache_destroy; /* Initialize block_cache_private structure */ @@ -370,9 +376,43 @@ return 0; } -/* - * Destructor - */ +static int +block_cache_meta_data(struct s3backer_store *s3b, off_t *file_sizep, u_int *block_sizep) +{ + struct block_cache_private *const priv = s3b->data; + + return (*priv->inner->meta_data)(priv->inner, file_sizep, block_sizep); +} + +static int +block_cache_set_mounted(struct s3backer_store *s3b, int *old_valuep, int new_value) +{ + struct block_cache_private *const priv = s3b->data; + + return (*priv->inner->set_mounted)(priv->inner, old_valuep, new_value); +} + +static int +block_cache_flush(struct s3backer_store *const s3b) +{ + struct block_cache_private *const priv = s3b->data; + + /* Grab lock and sanity check */ + pthread_mutex_lock(&priv->mutex); + S3BCACHE_CHECK_INVARIANTS(priv); + + /* Wait for all dirty blocks to be written and all worker threads to exit */ + priv->stopping = 1; + while (TAILQ_FIRST(&priv->dirties) != NULL || priv->num_threads > 0) { + pthread_cond_broadcast(&priv->worker_work); + pthread_cond_wait(&priv->worker_exit, &priv->mutex); + } + + /* Release lock */ + pthread_mutex_unlock(&priv->mutex); + return 0; +} + static void block_cache_destroy(struct s3backer_store *const s3b) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/s3backer-1.3.4/configure new/s3backer-1.3.5/configure --- old/s3backer-1.3.4/configure 2013-04-03 03:45:22.000000000 +0200 +++ new/s3backer-1.3.5/configure 2013-05-29 19:43:26.000000000 +0200 @@ -1,7 +1,7 @@ #! /bin/sh -# From configure.ac Id: configure.ac 470 2013-03-04 18:31:13Z archie.cobbs . +# From configure.ac Id: configure.ac 477 2013-04-03 01:57:08Z archie.cobbs . # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for s3backer FUSE filesystem backed by Amazon S3 1.3.4. +# Generated by GNU Autoconf 2.69 for s3backer FUSE filesystem backed by Amazon S3 1.3.5. # # Report bugs to <http://s3backer.googlecode.com/>. # @@ -581,8 +581,8 @@ # Identity of this package. PACKAGE_NAME='s3backer FUSE filesystem backed by Amazon S3' PACKAGE_TARNAME='s3backer' -PACKAGE_VERSION='1.3.4' -PACKAGE_STRING='s3backer FUSE filesystem backed by Amazon S3 1.3.4' +PACKAGE_VERSION='1.3.5' +PACKAGE_STRING='s3backer FUSE filesystem backed by Amazon S3 1.3.5' PACKAGE_BUGREPORT='http://s3backer.googlecode.com/' PACKAGE_URL='' @@ -1275,7 +1275,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures s3backer FUSE filesystem backed by Amazon S3 1.3.4 to adapt to many kinds of systems. +\`configure' configures s3backer FUSE filesystem backed by Amazon S3 1.3.5 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1341,7 +1341,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of s3backer FUSE filesystem backed by Amazon S3 1.3.4:";; + short | recursive ) echo "Configuration of s3backer FUSE filesystem backed by Amazon S3 1.3.5:";; esac cat <<\_ACEOF @@ -1440,7 +1440,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -s3backer FUSE filesystem backed by Amazon S3 configure 1.3.4 +s3backer FUSE filesystem backed by Amazon S3 configure 1.3.5 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -1788,7 +1788,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by s3backer FUSE filesystem backed by Amazon S3 $as_me 1.3.4, which was +It was created by s3backer FUSE filesystem backed by Amazon S3 $as_me 1.3.5, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2612,7 +2612,7 @@ # Define the identity of the package. PACKAGE='s3backer' - VERSION='1.3.4' + VERSION='1.3.5' cat >>confdefs.h <<_ACEOF @@ -5335,7 +5335,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by s3backer FUSE filesystem backed by Amazon S3 $as_me 1.3.4, which was +This file was extended by s3backer FUSE filesystem backed by Amazon S3 $as_me 1.3.5, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -5401,7 +5401,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -s3backer FUSE filesystem backed by Amazon S3 config.status 1.3.4 +s3backer FUSE filesystem backed by Amazon S3 config.status 1.3.5 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/s3backer-1.3.4/configure.ac new/s3backer-1.3.5/configure.ac --- old/s3backer-1.3.4/configure.ac 2013-03-04 19:31:21.000000000 +0100 +++ new/s3backer-1.3.5/configure.ac 2013-04-03 03:57:11.000000000 +0200 @@ -18,15 +18,15 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301, USA. # -# $Id: configure.ac 470 2013-03-04 18:31:13Z archie.cobbs $ +# $Id: configure.ac 477 2013-04-03 01:57:08Z archie.cobbs $ # -AC_INIT([s3backer FUSE filesystem backed by Amazon S3], [1.3.4], [http://s3backer.googlecode.com/], [s3backer]) +AC_INIT([s3backer FUSE filesystem backed by Amazon S3], [1.3.5], [http://s3backer.googlecode.com/], [s3backer]) AC_CONFIG_AUX_DIR(scripts) AM_INIT_AUTOMAKE dnl AM_MAINTAINER_MODE AC_PREREQ(2.59) -AC_REVISION($Id: configure.ac 470 2013-03-04 18:31:13Z archie.cobbs $) +AC_REVISION($Id: configure.ac 477 2013-04-03 01:57:08Z archie.cobbs $) AC_PREFIX_DEFAULT(/usr) AC_PROG_MAKE_SET diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/s3backer-1.3.4/ec_protect.c new/s3backer-1.3.5/ec_protect.c --- old/s3backer-1.3.4/ec_protect.c 2011-02-01 18:31:15.000000000 +0100 +++ new/s3backer-1.3.5/ec_protect.c 2013-05-11 19:07:54.000000000 +0200 @@ -19,7 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. * - * $Id: ec_protect.c 448 2011-02-01 17:31:15Z archie.cobbs $ + * $Id: ec_protect.c 482 2013-05-11 17:07:49Z archie.cobbs $ */ #include "s3backer.h" @@ -113,12 +113,15 @@ }; /* s3backer_store functions */ +static int ec_protect_meta_data(struct s3backer_store *s3b, off_t *file_sizep, u_int *block_sizep); +static int ec_protect_set_mounted(struct s3backer_store *s3b, int *old_valuep, int new_value); static int ec_protect_read_block(struct s3backer_store *s3b, s3b_block_t block_num, void *dest, u_char *actual_md5, const u_char *expect_md5, int strict); static int ec_protect_write_block(struct s3backer_store *s3b, s3b_block_t block_num, const void *src, u_char *md5, check_cancel_t *check_cancel, void *check_cancel_arg); static int ec_protect_read_block_part(struct s3backer_store *s3b, s3b_block_t block_num, u_int off, u_int len, void *dest); static int ec_protect_write_block_part(struct s3backer_store *s3b, s3b_block_t block_num, u_int off, u_int len, const void *src); +static int ec_protect_flush(struct s3backer_store *s3b); static void ec_protect_destroy(struct s3backer_store *s3b); /* Misc */ @@ -160,11 +163,14 @@ (*config->log)(LOG_ERR, "calloc(): %s", strerror(r)); goto fail0; } + s3b->meta_data = ec_protect_meta_data; + s3b->set_mounted = ec_protect_set_mounted; s3b->read_block = ec_protect_read_block; s3b->write_block = ec_protect_write_block; s3b->read_block_part = ec_protect_read_block_part; s3b->write_block_part = ec_protect_write_block_part; s3b->list_blocks = ec_protect_list_blocks; + s3b->flush = ec_protect_flush; s3b->destroy = ec_protect_destroy; if ((priv = calloc(1, sizeof(*priv))) == NULL) { r = errno; @@ -208,9 +214,40 @@ return NULL; } -/* - * Destructor - */ +static int +ec_protect_meta_data(struct s3backer_store *s3b, off_t *file_sizep, u_int *block_sizep) +{ + struct ec_protect_private *const priv = s3b->data; + + return (*priv->inner->meta_data)(priv->inner, file_sizep, block_sizep); +} + +static int +ec_protect_set_mounted(struct s3backer_store *s3b, int *old_valuep, int new_value) +{ + struct ec_protect_private *const priv = s3b->data; + + return (*priv->inner->set_mounted)(priv->inner, old_valuep, new_value); +} + +static int +ec_protect_flush(struct s3backer_store *const s3b) +{ + struct ec_protect_private *const priv = s3b->data; + + /* Grab lock and sanity check */ + pthread_mutex_lock(&priv->mutex); + EC_PROTECT_CHECK_INVARIANTS(priv); + + /* Wait for all sleeping writers to finish */ + while (priv->num_sleepers > 0) + pthread_cond_wait(&priv->sleepers_cond, &priv->mutex); + + /* Release lock */ + pthread_mutex_unlock(&priv->mutex); + return 0; +} + static void ec_protect_destroy(struct s3backer_store *const s3b) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/s3backer-1.3.4/erase.c new/s3backer-1.3.5/erase.c --- old/s3backer-1.3.4/erase.c 2011-02-01 18:31:15.000000000 +0100 +++ new/s3backer-1.3.5/erase.c 2013-05-11 19:07:54.000000000 +0200 @@ -19,7 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. * - * $Id: erase.c 448 2011-02-01 17:31:15Z archie.cobbs $ + * $Id: erase.c 482 2013-05-11 17:07:49Z archie.cobbs $ */ #include "s3backer.h" @@ -115,6 +115,12 @@ goto fail3; } + /* Clear mounted flag */ + if ((r = (*priv->s3b->set_mounted)(priv->s3b, NULL, 1)) != 0) { + warnx("can't clear mounted flag: %s", strerror(r)); + goto fail3; + } + /* Success */ ok = 1; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/s3backer-1.3.4/fuse_ops.c new/s3backer-1.3.5/fuse_ops.c --- old/s3backer-1.3.4/fuse_ops.c 2013-03-04 19:31:21.000000000 +0100 +++ new/s3backer-1.3.5/fuse_ops.c 2013-05-11 19:07:54.000000000 +0200 @@ -19,7 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. * - * $Id: fuse_ops.c 470 2013-03-04 18:31:13Z archie.cobbs $ + * $Id: fuse_ops.c 482 2013-05-11 17:07:49Z archie.cobbs $ */ #include "s3backer.h" @@ -139,6 +139,7 @@ static void * fuse_op_init(struct fuse_conn_info *conn) { + struct s3b_config *const s3bconf = config->s3bconf; struct fuse_ops_private *priv; /* Create private structure */ @@ -154,13 +155,14 @@ priv->file_size = config->num_blocks * config->block_size; /* Create backing store */ - if ((priv->s3b = s3backer_create_store(config->s3bconf)) == NULL) { + if ((priv->s3b = s3backer_create_store(s3bconf)) == NULL) { (*config->log)(LOG_ERR, "fuse_op_init(): can't create s3backer_store: %s", strerror(errno)); free(priv); return NULL; } /* Done */ + (*config->log)(LOG_INFO, "mounting %s", s3bconf->mount); return priv; } @@ -168,11 +170,33 @@ fuse_op_destroy(void *data) { struct fuse_ops_private *const priv = data; + struct s3backer_store *const s3b = priv->s3b; + struct s3b_config *const s3bconf = config->s3bconf; + int r; + + /* Sanity check */ + if (priv == NULL) + return; + (*config->log)(LOG_INFO, "unmount %s: initiated", s3bconf->mount); + + /* Flush dirty data */ + if (!config->read_only) { + (*config->log)(LOG_INFO, "unmount %s: flushing dirty data", s3bconf->mount); + if ((r = (*s3b->flush)(s3b)) != 0) + (*config->log)(LOG_ERR, "unmount %s: flushing filesystem failed: %s", s3bconf->mount, strerror(r)); + } - if (priv != NULL) { - (*priv->s3b->destroy)(priv->s3b); - free(priv); + /* Clear mounted flag */ + if (!config->read_only) { + (*config->log)(LOG_INFO, "unmount %s: clearing mounted flag", s3bconf->mount); + if ((r = (*s3b->set_mounted)(s3b, NULL, 0)) != 0) + (*config->log)(LOG_ERR, "unmount %s: clearing mounted flag failed: %s", s3bconf->mount, strerror(r)); } + + /* Shutdown */ + (*s3b->destroy)(s3b); + (*config->log)(LOG_INFO, "unmount %s: completed", s3bconf->mount); + free(priv); } static int diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/s3backer-1.3.4/http_io.c new/s3backer-1.3.5/http_io.c --- old/s3backer-1.3.4/http_io.c 2013-03-04 19:33:15.000000000 +0100 +++ new/s3backer-1.3.5/http_io.c 2013-05-11 19:07:54.000000000 +0200 @@ -19,7 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. * - * $Id: http_io.c 471 2013-03-04 18:33:11Z archie.cobbs $ + * $Id: http_io.c 482 2013-05-11 17:07:49Z archie.cobbs $ */ #include "s3backer.h" @@ -57,6 +57,12 @@ /* MIME type for blocks */ #define CONTENT_TYPE "application/x-s3backer-block" +/* MIME type for mounted flag */ +#define MOUNTED_FLAG_CONTENT_TYPE "text/plain" + +/* Mounted file object name */ +#define MOUNTED_FLAG "s3backer-mounted" + /* HTTP `Date' header format */ #define DATE_BUF_SIZE 64 #define DATE_BUF_FMT "%a, %d %b %Y %H:%M:%S GMT" @@ -166,6 +172,8 @@ typedef void http_io_curl_prepper_t(CURL *curl, struct http_io *io); /* s3backer_store functions */ +static int http_io_meta_data(struct s3backer_store *s3b, off_t *file_sizep, u_int *block_sizep); +static int http_io_set_mounted(struct s3backer_store *s3b, int *old_valuep, int new_value); static int http_io_read_block(struct s3backer_store *s3b, s3b_block_t block_num, void *dest, u_char *actual_md5, const u_char *expect_md5, int strict); static int http_io_write_block(struct s3backer_store *s3b, s3b_block_t block_num, const void *src, u_char *md5, @@ -173,16 +181,18 @@ static int http_io_read_block_part(struct s3backer_store *s3b, s3b_block_t block_num, u_int off, u_int len, void *dest); static int http_io_write_block_part(struct s3backer_store *s3b, s3b_block_t block_num, u_int off, u_int len, const void *src); static int http_io_list_blocks(struct s3backer_store *s3b, block_list_func_t *callback, void *arg); +static int http_io_flush(struct s3backer_store *s3b); static void http_io_destroy(struct s3backer_store *s3b); /* Other functions */ -static http_io_curl_prepper_t http_io_detect_prepper; +static http_io_curl_prepper_t http_io_head_prepper; static http_io_curl_prepper_t http_io_read_prepper; static http_io_curl_prepper_t http_io_write_prepper; static http_io_curl_prepper_t http_io_list_prepper; /* S3 REST API functions */ static char *http_io_get_url(char *buf, size_t bufsiz, struct http_io_conf *config, s3b_block_t block_num); +static char *http_io_get_mounted_flag(char *buf, size_t bufsiz, struct http_io_conf *config); static void http_io_get_auth(char *buf, size_t bufsiz, struct http_io_conf *config, const char *method, const char *ctype, const char *md5, const char *date, const struct curl_slist *headers, const char *resource); @@ -244,11 +254,14 @@ r = errno; goto fail0; } + s3b->meta_data = http_io_meta_data; + s3b->set_mounted = http_io_set_mounted; s3b->read_block = http_io_read_block; s3b->write_block = http_io_write_block; s3b->read_block_part = http_io_read_block_part; s3b->write_block_part = http_io_write_block_part; s3b->list_blocks = http_io_list_blocks; + s3b->flush = http_io_flush; s3b->destroy = http_io_destroy; if ((priv = calloc(1, sizeof(*priv))) == NULL) { r = errno; @@ -374,6 +387,12 @@ free(s3b); } +static int +http_io_flush(struct s3backer_store *const s3b) +{ + return 0; +} + void http_io_get_stats(struct s3backer_store *s3b, struct http_io_stats *stats) { @@ -626,24 +645,13 @@ return 0; } -/* - * Auto-detect block size and total size based on the first block. - * - * Returns: - * - * 0 Success - * ENOENT Block not found - * ENXIO Response was missing one of the two required headers - * Other Other error - */ -int -http_io_detect_sizes(struct s3backer_store *s3b, off_t *file_sizep, u_int *block_sizep) +static int +http_io_meta_data(struct s3backer_store *s3b, off_t *file_sizep, u_int *block_sizep) { struct http_io_private *const priv = s3b->data; struct http_io_conf *const config = priv->config; char urlbuf[URL_BUF_SIZE(config)]; const char *resource; - u_int content_len; char authbuf[200]; struct http_io io; char datebuf[64]; @@ -653,7 +661,6 @@ memset(&io, 0, sizeof(io)); io.url = urlbuf; io.method = HTTP_HEAD; - io.content_lengthp = &content_len; /* Construct URL for the first block */ resource = http_io_get_url(urlbuf, sizeof(urlbuf), config, 0); @@ -669,21 +676,16 @@ } /* Perform operation */ - if ((r = http_io_perform_io(priv, &io, http_io_detect_prepper)) != 0) + if ((r = http_io_perform_io(priv, &io, http_io_head_prepper)) != 0) goto done; /* Extract filesystem sizing information */ - if (io.file_size == 0) { - r = ENXIO; + if (io.file_size == 0 || io.block_size == 0) { + r = ENOENT; goto done; } *file_sizep = (off_t)io.file_size; - if (io.block_size != 0) - *block_sizep = io.block_size; - else if (content_len != 0) - *block_sizep = content_len; /* backward compatible */ - else - r = ENXIO; + *block_sizep = io.block_size; done: /* Clean up */ @@ -692,7 +694,7 @@ } static void -http_io_detect_prepper(CURL *curl, struct http_io *io) +http_io_head_prepper(CURL *curl, struct http_io *io) { memset(&io->bufs, 0, sizeof(io->bufs)); curl_easy_setopt(curl, CURLOPT_NOBODY, 1); @@ -704,6 +706,116 @@ } static int +http_io_set_mounted(struct s3backer_store *s3b, int *old_valuep, int new_value) +{ + struct http_io_private *const priv = s3b->data; + struct http_io_conf *const config = priv->config; + char urlbuf[URL_BUF_SIZE(config) + sizeof(MOUNTED_FLAG)]; + const char *resource; + char authbuf[200]; + struct http_io io; + char datebuf[64]; + int r = 0; + + /* Initialize I/O info */ + memset(&io, 0, sizeof(io)); + io.url = urlbuf; + io.method = HTTP_HEAD; + + /* Construct URL for the mounted flag */ + resource = http_io_get_mounted_flag(urlbuf, sizeof(urlbuf), config); + + /* Get old value */ + if (old_valuep != NULL) { + + /* Add Date header */ + http_io_get_date(datebuf, sizeof(datebuf)); + io.headers = http_io_add_header(io.headers, "%s: %s", DATE_HEADER, datebuf); + + /* Add Authorization header */ + if (config->accessId != NULL) { + http_io_get_auth(authbuf, sizeof(authbuf), config, io.method, NULL, NULL, datebuf, io.headers, resource); + io.headers = http_io_add_header(io.headers, "%s: AWS %s:%s", AUTH_HEADER, config->accessId, authbuf); + } + + /* See if object exists */ + switch ((r = http_io_perform_io(priv, &io, http_io_head_prepper))) { + case ENOENT: + *old_valuep = 0; + r = 0; + break; + case 0: + *old_valuep = 1; + break; + default: + goto done; + } + } + + /* Set new value */ + if (new_value != -1) { + u_char md5[MD5_DIGEST_LENGTH]; + char md5buf[MD5_DIGEST_LENGTH * 2 + 1]; + char content[HOST_NAME_MAX + 64]; + MD5_CTX ctx; + + /* Reset I/O info */ + curl_slist_free_all(io.headers); + memset(&io, 0, sizeof(io)); + io.url = urlbuf; + io.method = new_value ? HTTP_PUT : HTTP_DELETE; + + /* Add Date header */ + http_io_get_date(datebuf, sizeof(datebuf)); + io.headers = http_io_add_header(io.headers, "%s: %s", DATE_HEADER, datebuf); + + /* To set the flag PUT some content containing current date */ + if (new_value) { + + /* Create content for the mounted flag object */ + snprintf(content, sizeof(content), "%s\n", datebuf); + io.src = content; + io.buf_size = strlen(content); + MD5_Init(&ctx); + MD5_Update(&ctx, content, strlen(content)); + MD5_Final(md5, &ctx); + + /* Add Content-Type header */ + io.headers = http_io_add_header(io.headers, "%s: %s", CTYPE_HEADER, MOUNTED_FLAG_CONTENT_TYPE); + + /* Add Content-MD5 header */ + http_io_base64_encode(md5buf, sizeof(md5buf), md5, MD5_DIGEST_LENGTH); + io.headers = http_io_add_header(io.headers, "%s: %s", MD5_HEADER, md5buf); + } + + /**** NOTE: we add the following "x-amz" headers in lexicographic order as required by http_io_get_auth() ****/ + + /* Add ACL header (PUT only) */ + if (new_value) + io.headers = http_io_add_header(io.headers, "%s: %s", ACL_HEADER, config->accessType); + + /* Add storage class header (if needed) */ + if (config->rrs) + io.headers = http_io_add_header(io.headers, "%s: %s", STORAGE_CLASS_HEADER, SCLASS_REDUCED_REDUNDANCY); + + /* Add Authorization header */ + if (config->accessId != NULL) { + http_io_get_auth(authbuf, sizeof(authbuf), config, io.method, + new_value ? MOUNTED_FLAG_CONTENT_TYPE : NULL, new_value ? md5buf : NULL, datebuf, io.headers, resource); + io.headers = http_io_add_header(io.headers, "%s: AWS %s:%s", AUTH_HEADER, config->accessId, authbuf); + } + + /* Perform operation to set or clear mounted flag */ + r = http_io_perform_io(priv, &io, http_io_write_prepper); + } + +done: + /* Clean up */ + curl_slist_free_all(io.headers); + return r; +} + +static int http_io_read_block(struct s3backer_store *const s3b, s3b_block_t block_num, void *dest, u_char *actual_md5, const u_char *expect_md5, int strict) { @@ -1566,6 +1678,27 @@ resource = buf + strlen(config->baseURL) + strlen(config->bucket); } (void)len; /* avoid compiler warning when NDEBUG defined */ + assert(len < bufsiz); + return resource; +} + +/* + * Create URL for the mounted flag, and return pointer to the URL's path not including any "/bucket" prefix. + */ +static char * +http_io_get_mounted_flag(char *buf, size_t bufsiz, struct http_io_conf *config) +{ + char *resource; + int len; + + if (config->vhost) { + len = snprintf(buf, bufsiz, "%s%s%s", config->baseURL, config->prefix, MOUNTED_FLAG); + resource = buf + strlen(config->baseURL) - 1; + } else { + len = snprintf(buf, bufsiz, "%s%s/%s%s", config->baseURL, config->bucket, config->prefix, MOUNTED_FLAG); + resource = buf + strlen(config->baseURL) + strlen(config->bucket); + } + (void)len; /* avoid compiler warning when NDEBUG defined */ assert(len < bufsiz); return resource; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/s3backer-1.3.4/http_io.h new/s3backer-1.3.5/http_io.h --- old/s3backer-1.3.4/http_io.h 2011-02-01 18:31:15.000000000 +0100 +++ new/s3backer-1.3.5/http_io.h 2013-05-11 19:07:54.000000000 +0200 @@ -19,7 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. * - * $Id: http_io.h 448 2011-02-01 17:31:15Z archie.cobbs $ + * $Id: http_io.h 482 2013-05-11 17:07:49Z archie.cobbs $ */ /* Upload/download indexes */ @@ -106,6 +106,5 @@ /* http_io.c */ extern struct s3backer_store *http_io_create(struct http_io_conf *config); extern void http_io_get_stats(struct s3backer_store *s3b, struct http_io_stats *stats); -extern int http_io_detect_sizes(struct s3backer_store *s3b, off_t *file_sizep, u_int *block_sizep); extern int http_io_parse_block(struct http_io_conf *config, const char *name, s3b_block_t *block_num); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/s3backer-1.3.4/main.c new/s3backer-1.3.5/main.c --- old/s3backer-1.3.4/main.c 2013-03-04 19:31:21.000000000 +0100 +++ new/s3backer-1.3.5/main.c 2013-05-11 19:07:54.000000000 +0200 @@ -19,7 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. * - * $Id: main.c 470 2013-03-04 18:31:13Z archie.cobbs $ + * $Id: main.c 482 2013-05-11 17:07:49Z archie.cobbs $ */ #include "s3backer.h" @@ -29,6 +29,7 @@ #include "http_io.h" #include "s3b_config.h" #include "erase.h" +#include "reset.h" int main(int argc, char **argv) @@ -38,7 +39,7 @@ /* Get configuration */ if ((config = s3backer_get_config(argc, argv)) == NULL) - exit(1); + return 1; /* Handle `--erase' flag */ if (config->erase) { @@ -46,6 +47,13 @@ return 1; return 0; } + + /* Handle `--reset' flag */ + if (config->reset) { + if (s3backer_reset(config) != 0) + return 1; + return 0; + } /* Get FUSE operation hooks */ fuse_ops = fuse_ops_create(&config->fuse_ops); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/s3backer-1.3.4/reset.c new/s3backer-1.3.5/reset.c --- old/s3backer-1.3.4/reset.c 1970-01-01 01:00:00.000000000 +0100 +++ new/s3backer-1.3.5/reset.c 2013-05-11 19:07:54.000000000 +0200 @@ -0,0 +1,68 @@ + +/* + * s3backer - FUSE-based single file backing store via Amazon S3 + * + * Copyright 2008-2011 Archie L. Cobbs <[email protected]> + * + * 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 the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + * $Id: reset.c 482 2013-05-11 17:07:49Z archie.cobbs $ + */ + +#include "s3backer.h" +#include "block_cache.h" +#include "ec_protect.h" +#include "fuse_ops.h" +#include "http_io.h" +#include "test_io.h" +#include "s3b_config.h" +#include "reset.h" + +int +s3backer_reset(struct s3b_config *config) +{ + struct s3backer_store *s3b = NULL; + int ok = 0; + int r; + + /* Logging */ + if (!config->quiet) + warnx("resetting mounted flag for %s", config->description); + + /* Create temporary lower layer */ + if ((s3b = config->test ? test_io_create(&config->http_io) : http_io_create(&config->http_io)) == NULL) { + warnx(config->test ? "test_io_create" : "http_io_create"); + goto fail; + } + + /* Clear mounted flag */ + if ((r = (*s3b->set_mounted)(s3b, NULL, 0)) != 0) { + warnx("error clearing mounted flag: %s", strerror(r)); + goto fail; + } + + /* Success */ + if (!config->quiet) + warnx("done"); + ok = 1; + +fail: + /* Clean up */ + if (s3b != NULL) + (*s3b->destroy)(s3b); + return ok ? 0 : -1; +} + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/s3backer-1.3.4/reset.h new/s3backer-1.3.5/reset.h --- old/s3backer-1.3.4/reset.h 1970-01-01 01:00:00.000000000 +0100 +++ new/s3backer-1.3.5/reset.h 2013-05-11 19:07:54.000000000 +0200 @@ -0,0 +1,27 @@ + +/* + * s3backer - FUSE-based single file backing store via Amazon S3 + * + * Copyright 2008-2011 Archie L. Cobbs <[email protected]> + * + * 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 the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + * $Id: reset.h 482 2013-05-11 17:07:49Z archie.cobbs $ + */ + +/* reset.c */ +extern int s3backer_reset(struct s3b_config *config); + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/s3backer-1.3.4/s3b_config.c new/s3backer-1.3.5/s3b_config.c --- old/s3backer-1.3.4/s3b_config.c 2012-06-25 19:16:14.000000000 +0200 +++ new/s3backer-1.3.5/s3b_config.c 2013-05-11 19:07:54.000000000 +0200 @@ -19,7 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. * - * $Id: s3b_config.c 468 2012-06-25 17:16:14Z archie.cobbs $ + * $Id: s3b_config.c 482 2013-05-11 17:07:49Z archie.cobbs $ */ #include "s3backer.h" @@ -170,6 +170,7 @@ .quiet= 0, .erase= 0, .no_auto_detect= 0, + .reset= 0, .log= syslog_logger }; @@ -288,6 +289,11 @@ .value= 1 }, { + .templ= "--reset-mounted-flag", + .offset= offsetof(struct s3b_config, reset), + .value= 1 + }, + { .templ= "--vhost", .offset= offsetof(struct s3b_config, http_io.vhost), .value= 1 @@ -529,10 +535,15 @@ return &config; } +/* + * Create the s3backer_store used at runtime. This method is invoked by fuse_op_init(). + */ struct s3backer_store * s3backer_create_store(struct s3b_config *conf) { struct s3backer_store *store; + int mounted; + int r; /* Sanity check */ if (http_io_store != NULL || test_io_store != NULL) @@ -551,29 +562,43 @@ /* Create eventual consistency protection layer (if desired) */ if (conf->ec_protect.cache_size > 0) { - if ((ec_protect_store = ec_protect_create(&conf->ec_protect, store)) == NULL) { - (*store->destroy)(store); - http_io_store = NULL; - test_io_store = NULL; - return NULL; - } + if ((ec_protect_store = ec_protect_create(&conf->ec_protect, store)) == NULL) + goto fail; store = ec_protect_store; } /* Create block cache layer (if desired) */ if (conf->block_cache.cache_size > 0) { - if ((block_cache_store = block_cache_create(&conf->block_cache, store)) == NULL) { - (*store->destroy)(store); - ec_protect_store = NULL; - http_io_store = NULL; - test_io_store = NULL; - return NULL; - } + if ((block_cache_store = block_cache_create(&conf->block_cache, store)) == NULL) + goto fail; store = block_cache_store; } + /* Set mounted flag and check previous value one last time */ + r = (*store->set_mounted)(store, &mounted, conf->fuse_ops.read_only ? -1 : 1); + if (r != 0) { + (*conf->log)(LOG_ERR, "error reading mounted flag on %s: %s", + conf->description, strerror(r)); + goto fail; + } + if (mounted) { + if (!conf->force) { + (*conf->log)(LOG_ERR, "%s appears to be mounted by another s3backer process", config.description); + goto fail; + } + } + /* Done */ return store; + +fail: + if (store != NULL) + (*store->destroy)(store); + block_cache_store = NULL; + ec_protect_store = NULL; + http_io_store = NULL; + test_io_store = NULL; + return NULL; } /**************************************************************************** @@ -1125,9 +1150,9 @@ } /* Check mount point */ - if (config.erase) { + if (config.erase || config.reset) { if (config.mount != NULL) { - warnx("no mount point required with `--erase'"); + warnx("no mount point should be specified with `--erase' or `--reset-mounted-flag'"); return -1; } } else { @@ -1164,7 +1189,7 @@ err(1, "http_io_create"); if (!config.quiet) warnx("auto-detecting block size and total file size..."); - r = http_io_detect_sizes(s3b, &auto_file_size, &auto_block_size); + r = (*s3b->meta_data)(s3b, &auto_file_size, &auto_block_size); (*s3b->destroy)(s3b); } @@ -1207,7 +1232,6 @@ } break; case ENOENT: - case ENXIO: { const char *why = config.no_auto_detect ? "disabled" : "failed"; int config_block_size = config.block_size; @@ -1226,10 +1250,35 @@ } default: errno = r; - err(1, "can't read block zero meta-data"); + err(1, "can't read data store meta-data"); break; } + /* Check whether already mounted */ + if (!config.test && !config.erase && !config.reset) { + int mounted; + + config.http_io.debug = config.debug; + config.http_io.quiet = config.quiet; + config.http_io.log = config.log; + if ((s3b = http_io_create(&config.http_io)) == NULL) + err(1, "http_io_create"); + r = (*s3b->set_mounted)(s3b, &mounted, -1); + (*s3b->destroy)(s3b); + if (r != 0) { + errno = r; + err(1, "error reading mounted flag"); + } + if (mounted) { + if (!config.force) + errx(1, "error: %s appears to be already mounted", config.description); + if (!config.quiet) { + warnx("warning: filesystem appears already mounted but you said `--force'\n" + " so I'll proceed anyway even though your data may get corrupted.\n"); + } + } + } + /* Check computed block and file sizes */ if (config.block_size != (1 << (ffs(config.block_size) - 1))) { warnx("block size must be a power of 2"); @@ -1319,7 +1368,7 @@ config.fuse_ops.log = config.log; /* If `--listBlocks' was given, build non-empty block bitmap */ - if (config.erase) + if (config.erase || config.reset) config.list_blocks = 0; if (config.list_blocks) { struct s3backer_store *temp_store; @@ -1505,6 +1554,7 @@ fprintf(stderr, "\ts3backer [options] bucket /mount/point\n"); fprintf(stderr, "\ts3backer --test [options] directory /mount/point\n"); fprintf(stderr, "\ts3backer --erase [options] bucket\n"); + fprintf(stderr, "\ts3backer --reset-mounted-flag [options] bucket\n"); fprintf(stderr, "Options:\n"); fprintf(stderr, "\t--%-27s %s\n", "accessFile=FILE", "File containing `accessID:accessKey' pairs"); fprintf(stderr, "\t--%-27s %s\n", "accessId=ID", "S3 access key ID"); @@ -1529,7 +1579,7 @@ fprintf(stderr, "\t--%-27s %s\n", "debug", "Enable logging of debug messages"); fprintf(stderr, "\t--%-27s %s\n", "debug-http", "Print HTTP headers to standard output"); fprintf(stderr, "\t--%-27s %s\n", "directIO", "Disable kernel caching of the backed file"); - fprintf(stderr, "\t--%-27s %s\n", "encryption[=CIPHER]", "Enable encryption (implies `--compress')"); + fprintf(stderr, "\t--%-27s %s\n", "encrypt[=CIPHER]", "Enable encryption (implies `--compress')"); fprintf(stderr, "\t--%-27s %s\n", "erase", "Erase all blocks in the filesystem"); fprintf(stderr, "\t--%-27s %s\n", "fileMode=MODE", "Permissions of backed file in filesystem"); fprintf(stderr, "\t--%-27s %s\n", "filename=NAME", "Name of backed file in filesystem"); @@ -1551,6 +1601,7 @@ fprintf(stderr, "\t--%-27s %s\n", "readAhead=NUM", "Number of blocks to read-ahead"); fprintf(stderr, "\t--%-27s %s\n", "readAheadTrigger=NUM", "# of sequentially read blocks to trigger read-ahead"); fprintf(stderr, "\t--%-27s %s\n", "readOnly", "Return `Read-only file system' error for write attempts"); + fprintf(stderr, "\t--%-27s %s\n", "reset-mounted-flag", "Reset `already mounted' flag in the filesystem"); fprintf(stderr, "\t--%-27s %s\n", "rrs", "Target written blocks for Reduced Redundancy Storage"); fprintf(stderr, "\t--%-27s %s\n", "size=SIZE", "File size (with optional suffix 'K', 'M', 'G', etc.)"); fprintf(stderr, "\t--%-27s %s\n", "ssl", "Same as --baseURL " S3_BASE_URL_HTTPS); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/s3backer-1.3.4/s3b_config.h new/s3backer-1.3.5/s3b_config.h --- old/s3backer-1.3.4/s3b_config.h 2011-02-01 18:31:15.000000000 +0100 +++ new/s3backer-1.3.5/s3b_config.h 2013-05-11 19:07:54.000000000 +0200 @@ -19,7 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. * - * $Id: s3b_config.h 448 2011-02-01 17:31:15Z archie.cobbs $ + * $Id: s3b_config.h 482 2013-05-11 17:07:49Z archie.cobbs $ */ /* Overal application configuration info */ @@ -40,6 +40,7 @@ off_t num_blocks; int debug; int erase; + int reset; int quiet; int force; int test; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/s3backer-1.3.4/s3backer.1 new/s3backer-1.3.5/s3backer.1 --- old/s3backer-1.3.4/s3backer.1 2011-08-04 22:35:12.000000000 +0200 +++ new/s3backer-1.3.5/s3backer.1 2013-05-11 19:07:54.000000000 +0200 @@ -19,7 +19,7 @@ .\" Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA .\" 02110-1301, USA. .\" -.\" $Id: s3backer.1 457 2011-08-04 20:35:12Z archie.cobbs $ +.\" $Id: s3backer.1 482 2013-05-11 17:07:49Z archie.cobbs $ .\" .Dd September 7, 2009 .Dt S3BACKER 1 @@ -49,6 +49,13 @@ .Op options .Ar bucket .Ek +.Pp +.Nm s3backer +.Bk -words +.Fl \-reset-mounted-flag +.Op options +.Ar bucket +.Ek .Sh DESCRIPTION .Nm is a filesystem that contains a single file backed by the Amazon Simple Storage Service (Amazon S3). @@ -235,8 +242,17 @@ .Nm filesystem is not a distributed filesystem and does not support simultaneous read/write mounts. (This is not something you would normally do with a hard-disk partition either.) +As a safety measure, +.Nm +attempts to detect this situation using an 'already mounted' flag +in the data store, and will fail to start if it does. +.Pp +This detection may produce a false positive if a former .Nm -does not detect this situation; it is up to the user to ensure that it doesn't happen. +process was not shutdown cleanly; if so, the +.Fl \-reset-mounted-flag +flag can be used to reset the 'already mounted' flag. +But see also BUGS below. .Ss Statistics File .Nm populates the filesystem with a human-readable statistics file. @@ -465,10 +481,11 @@ This flag implies .Fl \-compress . .It Fl \-erase -Completely erase the file system by deleting all non-zero blocks, and then exit. +Completely erase the file system by deleting all non-zero blocks, clear the 'already mounted' flag, and then exit. User confirmation is required unless the .Fl \-force flag is also given. +Note, no simultaneous mount detection is performed in this case. .Pp This option implies .Fl \-listBlocks . @@ -489,12 +506,33 @@ .Fl \-blockSize or .Fl \-size -disagrees with the auto-detected value. -This is will certainly lead to garbled data and should be avoided for normal use. +disagrees with the auto-detected value, or +.Nm +detects that another +.Nm +instance is still mounted on top of the same S3 bucket (and prefix). +In any of these cases, proceeding will lead to corrupted data, so the +.Fl \-force +flag should be avoided for normal use. +.Pp +The simultaneous mount detection can produce a false positive when a previous +.Nm +instance was not shut down cleanly. +In this case, don't use +.Fl \-force +but rather run +.Nm +once with the +.Fl \-reset-mounted-flag +flag. .Pp If .Fl \-erase -is given, proceed without user confirmation. +is given, +.Fl \-force +causes +.Nm +to proceed without user confirmation. .It Fl h Fl \-help Print a help message and exit. .It Fl \-initialRetryPause=MILLIS @@ -620,6 +658,20 @@ in response to any attempt to write. This flag also changes the default mode of the backed file from 0600 to 0400 and disables the MD5 checksum cache. +.It Fl \-reset-mounted-flag +Reset the 'already mounted' flag on the underlying S3 data store. +.Pp +.Nm +detects simultaneous mounts by checking a special flag. +If a previous invocation of +.Nm +was not shut down cleanly, the flag may not have been cleared. +Running +.Nm +.Fl \-erase +will clear it manually. +But see also BUGS below. +.Pp .It Fl \-rrs When writing blocks, specify Reduced Redundancy Storage. .It Fl \-size=SIZE @@ -755,6 +807,22 @@ .%O http://www.google.com/search?q=linux+page+cache .Re .Sh BUGS +Due to a design flaw in FUSE, an unmount of the +.Nm +filesystem will complete successfully before +.Nm +has finished writing back all dirty blocks. +Therefore, when using the block cache, attempts to remount the same bucket and prefix +may fail with an 'already mounted' error while the former +.Nm +process finishes flusing its cache. +Before assuming a false positive and using +.Fl \-reset-mounted-flag, +ensure that any previous +.Nm +process attached to the same bucket and prefix has exited. +See issue #40 for details. +.Pp For cache space efficiency, .Nm uses 32 bit values to index individual blocks. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/s3backer-1.3.4/s3backer.h new/s3backer-1.3.5/s3backer.h --- old/s3backer-1.3.4/s3backer.h 2013-03-04 19:31:21.000000000 +0100 +++ new/s3backer-1.3.5/s3backer.h 2013-05-11 19:07:54.000000000 +0200 @@ -19,7 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. * - * $Id: s3backer.h 470 2013-03-04 18:31:13Z archie.cobbs $ + * $Id: s3backer.h 482 2013-05-11 17:07:49Z archie.cobbs $ */ #include "config.h" @@ -107,6 +107,35 @@ struct s3backer_store { /* + * Get meta-data associated with the underlying store. + * + * The information we acquire is: + * o Block size + * o Total size + * + * Returns: + * + * 0 Success + * ENOENT Information not found + * Other Other error + */ + int (*meta_data)(struct s3backer_store *s3b, off_t *file_sizep, u_int *block_sizep); + + /* + * Read and (optionally) set the mounted flag. + * + * Previous value is returned in *old_valuep (if not NULL). + * + * new_value can be: + * -1 Don't change it + * 0 Clear it + * 1 Set it + * + * Returns zero on success or a (positive) errno value on error. + */ + int (*set_mounted)(struct s3backer_store *s3b, int *old_valuep, int new_value); + + /* * Read one block. Never-written-to blocks will return all zeroes. * * If not NULL, 'actual_md5' should be filled in with a value suitable for the 'expect_md5' parameter, @@ -165,6 +194,11 @@ int (*list_blocks)(struct s3backer_store *s3b, block_list_func_t *callback, void *arg); /* + * Sync any dirty data to the underlying data store. + */ + int (*flush)(struct s3backer_store *s3b); + + /* * Destroy this instance. */ void (*destroy)(struct s3backer_store *s3b); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/s3backer-1.3.4/s3backer.spec new/s3backer-1.3.5/s3backer.spec --- old/s3backer-1.3.4/s3backer.spec 2013-04-03 03:45:29.000000000 +0200 +++ new/s3backer-1.3.5/s3backer.spec 2013-05-29 19:43:31.000000000 +0200 @@ -17,7 +17,7 @@ # Name: s3backer -Version: 1.3.4 +Version: 1.3.5 Release: 1 License: GNU General Public License, Version 2 Summary: FUSE-based single file backing store via Amazon S3 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/s3backer-1.3.4/svnrev.c new/s3backer-1.3.5/svnrev.c --- old/s3backer-1.3.4/svnrev.c 2013-04-03 03:45:30.000000000 +0200 +++ new/s3backer-1.3.5/svnrev.c 2013-05-29 19:43:32.000000000 +0200 @@ -1 +1 @@ -const int s3backer_svnrev = 476; +const int s3backer_svnrev = 485; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/s3backer-1.3.4/test_io.c new/s3backer-1.3.5/test_io.c --- old/s3backer-1.3.4/test_io.c 2011-02-01 18:31:15.000000000 +0100 +++ new/s3backer-1.3.5/test_io.c 2013-05-11 19:07:54.000000000 +0200 @@ -19,7 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. * - * $Id: test_io.c 448 2011-02-01 17:31:15Z archie.cobbs $ + * $Id: test_io.c 482 2013-05-11 17:07:49Z archie.cobbs $ */ #include "s3backer.h" @@ -37,6 +37,8 @@ }; /* s3backer_store functions */ +static int test_io_meta_data(struct s3backer_store *s3b, off_t *file_sizep, u_int *block_sizep); +static int test_io_set_mounted(struct s3backer_store *s3b, int *old_valuep, int new_value); static int test_io_read_block(struct s3backer_store *s3b, s3b_block_t block_num, void *dest, u_char *actual_md5, const u_char *expect_md5, int strict); static int test_io_write_block(struct s3backer_store *s3b, s3b_block_t block_num, const void *src, u_char *md5, @@ -44,6 +46,7 @@ static int test_io_read_block_part(struct s3backer_store *s3b, s3b_block_t block_num, u_int off, u_int len, void *dest); static int test_io_write_block_part(struct s3backer_store *s3b, s3b_block_t block_num, u_int off, u_int len, const void *src); static int test_io_list_blocks(struct s3backer_store *s3b, block_list_func_t *callback, void *arg); +static int test_io_flush(struct s3backer_store *s3b); static void test_io_destroy(struct s3backer_store *s3b); /* @@ -60,11 +63,14 @@ /* Initialize structures */ if ((s3b = calloc(1, sizeof(*s3b))) == NULL) return NULL; + s3b->meta_data = test_io_meta_data; + s3b->set_mounted = test_io_set_mounted; s3b->read_block = test_io_read_block; s3b->write_block = test_io_write_block; s3b->read_block_part = test_io_read_block_part; s3b->write_block_part = test_io_write_block_part; s3b->list_blocks = test_io_list_blocks; + s3b->flush = test_io_flush; s3b->destroy = test_io_destroy; if ((priv = calloc(1, sizeof(*priv) + config->block_size)) == NULL) { free(s3b); @@ -81,9 +87,26 @@ return s3b; } -/* - * Destructor - */ +static int +test_io_meta_data(struct s3backer_store *s3b, off_t *file_sizep, u_int *block_sizep) +{ + return 0; +} + +static int +test_io_set_mounted(struct s3backer_store *s3b, int *old_valuep, int new_value) +{ + if (old_valuep != NULL) + *old_valuep = 0; + return 0; +} + +static int +test_io_flush(struct s3backer_store *const s3b) +{ + return 0; +} + static void test_io_destroy(struct s3backer_store *const s3b) { -- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
