Branko Čibej wrote on Wed, Mar 27, 2013 at 12:57:13 +0100: > On 27.03.2013 07:54, Daniel Shahaf wrote: > > Branko Čibej wrote on Wed, Mar 27, 2013 at 05:14:51 +0100: > >> On 26.03.2013 23:11, Daniel Shahaf wrote: > >>> [[[ > >>> Run the per-revision verify code on a transaction just before it becomes > >>> a revision. The intent is to catch corruption bugs as early as possible. > >>> > >>> * subversion/libsvn_fs/fs-loader.c > >>> (svn_fs_commit_txn): As above. > >>> ]]] > >>> > >>> Maybe this should be optional behaviour in release mode, too?
And here's the new one. (I haven't colored the section name bikeshed yet, nor moved the new macros to svn_fs.h.) I wonder whether doing a verify of a revision root as the very last thing before incrementing db/current -- specifically, in commit_body() immediately before the sole call to write_final_current() --- would be better. Thoughts? [[[ Index: subversion/libsvn_fs/fs-loader.c =================================================================== --- subversion/libsvn_fs/fs-loader.c (revision 1461743) +++ subversion/libsvn_fs/fs-loader.c (working copy) @@ -1,3 +1,6 @@ +#define SVN_FS_CONFIG_SECTION_FOO "foo" +#define SVN_FS_CONFIG_OPTION_VERIFY_AT_COMMIT "verify-at-commit" + /* * fs_loader.c: Front-end to the various FS back ends * @@ -32,6 +35,7 @@ #include "svn_hash.h" #include "svn_ctype.h" +#include "svn_config.h" #include "svn_types.h" #include "svn_dso.h" #include "svn_version.h" @@ -57,6 +61,7 @@ #endif #define FS_TYPE_FILENAME "fs-type" +#define CONFIG_FILENAME "fs.conf" /* A pool common to all FS objects. See the documentation on the open/create functions in fs-loader.h and for svn_fs_initialize(). */ @@ -338,6 +343,26 @@ write_fs_type(const char *path, const char *fs_typ return svn_error_trace(svn_io_file_close(file, pool)); } +static svn_error_t * +write_config(const char *path, apr_pool_t *pool) +{ + static const char * const fs_conf_contents = +#define NL APR_EOL_STR +"### This file controls backend-independent filesystem configuration." NL +"" NL +"[" SVN_FS_CONFIG_SECTION_FOO "]" NL +"### When set, Subversion will run the equivalent of 'svnadmin verify -r'" NL +"### on each transaction (commit-in-progress) just before it becomes" NL +"### a revision. This may slow down commits, since the cost of" NL +"### verification is proportional to the size of the commit (e.g., number" NL +"### of files 'svn log -q -v -r N' shows)." NL +"# " SVN_FS_CONFIG_OPTION_VERIFY_AT_COMMIT " = false" NL +; +#undef NL + SVN_ERR(svn_io_file_create(svn_dirent_join(path, CONFIG_FILENAME, pool), + fs_conf_contents, pool)); + return SVN_NO_ERROR; +} /* --- Functions for operating on filesystems by pathname --- */ @@ -414,6 +439,11 @@ fs_new(apr_hash_t *fs_config, apr_pool_t *pool) fs->vtable = NULL; fs->fsap_data = NULL; fs->uuid = NULL; +#ifdef SVN_DEBUG + fs->verify_at_commit = TRUE; +#else + fs->verify_at_commit = FALSE; +#endif return fs; } @@ -445,6 +475,7 @@ svn_fs_create(svn_fs_t **fs_p, const char *path, a /* Create the FS directory and write out the fsap-name file. */ SVN_ERR(svn_io_dir_make_sgid(path, APR_OS_DEFAULT, pool)); SVN_ERR(write_fs_type(path, fs_type, pool)); + SVN_ERR(write_config(path, pool)); /* Perform the actual creation. */ *fs_p = fs_new(fs_config, pool); @@ -459,9 +490,20 @@ svn_fs_open(svn_fs_t **fs_p, const char *path, apr apr_pool_t *pool) { fs_library_vtable_t *vtable; + svn_config_t *config; SVN_ERR(fs_library_vtable(&vtable, path, pool)); *fs_p = fs_new(fs_config, pool); + + SVN_ERR(svn_config_read2(&config, + svn_dirent_join(path, CONFIG_FILENAME, pool), + FALSE /* must_exist */, TRUE /* case-sensitive */, + pool)); + SVN_ERR(svn_config_get_bool(config, &(*fs_p)->verify_at_commit, + SVN_FS_CONFIG_SECTION_FOO, + SVN_FS_CONFIG_OPTION_VERIFY_AT_COMMIT, + (*fs_p)->verify_at_commit)); + SVN_MUTEX__WITH_LOCK(common_pool_lock, vtable->open_fs(*fs_p, path, pool, common_pool)); return SVN_NO_ERROR; @@ -750,22 +792,18 @@ svn_fs_commit_txn(const char **conflict_p, svn_rev svn_fs_txn_t *txn, apr_pool_t *pool) { svn_error_t *err; -#if defined(PACK_AFTER_EVERY_COMMIT) || defined(SVN_DEBUG) - svn_fs_root_t *txn_root; -#endif + svn_fs_t *fs = txn->fs; *new_rev = SVN_INVALID_REVNUM; -#if defined(PACK_AFTER_EVERY_COMMIT) || defined(SVN_DEBUG) - SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool)); -#endif + if (fs->verify_at_commit) + { + /* ### TODO: should this run just before incrementing 'current'? */ + svn_fs_root_t *txn_root; + SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool)); + SVN_ERR(svn_fs_verify_root(txn_root, pool)); + } -#ifdef SVN_DEBUG - /* ### TODO: add db/fs.conf with a knob to enable this in release builds */ - /* ### TODO: should this run just before incrementing 'current'? */ - SVN_ERR(svn_fs_verify_root(txn_root, pool)); -#endif - err = txn->vtable->commit(conflict_p, new_rev, txn, pool); #ifdef SVN_DEBUG @@ -784,7 +822,6 @@ svn_fs_commit_txn(const char **conflict_p, svn_rev #ifdef PACK_AFTER_EVERY_COMMIT { - svn_fs_t *fs = svn_fs_root_fs(txn_root); const char *fs_path = svn_fs_path(fs, pool); err = svn_fs_pack(fs_path, NULL, NULL, NULL, NULL, pool); if (err && err->apr_err == SVN_ERR_UNSUPPORTED_FEATURE) Index: subversion/libsvn_fs/fs-loader.h =================================================================== --- subversion/libsvn_fs/fs-loader.h (revision 1461737) +++ subversion/libsvn_fs/fs-loader.h (working copy) @@ -407,6 +407,9 @@ struct svn_fs_t /* UUID, stored by open(), create(), and set_uuid(). */ const char *uuid; + + /* Parsed contents of fs.conf */ + svn_boolean_t verify_at_commit; }; ]]]