Author: danielsh
Date: Sun Oct 2 23:44:30 2011
New Revision: 1178280
URL: http://svn.apache.org/viewvc?rev=1178280&view=rev
Log:
FSFS: add a sanity check: the root noderev's PREDECESSOR_COUNT (aka
HEADER_COUNT), when known, must equal the revision that noderev is the
root of.
* subversion/libsvn_fs_fs/fs_fs.c
(validate_root_noderev): New function.
(write_final_rev): New parameter, AT_ROOT.
Use it to decide when to call validate_root_noderev().
(commit_body): Update call to write_final_rev().
Modified:
subversion/trunk/subversion/libsvn_fs_fs/fs_fs.c
Modified: subversion/trunk/subversion/libsvn_fs_fs/fs_fs.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/fs_fs.c?rev=1178280&r1=1178279&r2=1178280&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/fs_fs.c (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/fs_fs.c Sun Oct 2 23:44:30 2011
@@ -5880,6 +5880,35 @@ write_hash_rep(svn_filesize_t *size,
return svn_stream_printf(whb->stream, pool, "ENDREP\n");
}
+/* Sanity check ROOT_NODEREV, a candidate for being the root node-revision
+ of (not yet committed) revision REV. Use OCEAN for temporary allocations.
+ */
+static APR_INLINE svn_error_t *
+validate_root_noderev(node_revision_t *root_noderev,
+ svn_revnum_t rev,
+ apr_pool_t *pool)
+{
+ SVN_DBG(("root_noderev->predecessor_id=%s\n",
+ svn_fs_fs__id_unparse(root_noderev->predecessor_id, pool)->data));
+ SVN_DBG(("root_noderev->predecessor_count=%d\n",
+ root_noderev->predecessor_count));
+
+ /* Bogosity seen on svn.apache.org; see
+ http://mid.gmane.org/[email protected]
+ */
+ if (root_noderev->predecessor_count != -1
+ && root_noderev->predecessor_count != rev)
+ {
+ return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
+ _("predecessor count for "
+ "the root node-revision is wrong: "
+ "found %d, committing r%ld"),
+ root_noderev->predecessor_count, rev);
+ }
+
+ return SVN_NO_ERROR;
+}
+
/* Copy a node-revision specified by id ID in fileystem FS from a
transaction into the proto-rev-file FILE. Set *NEW_ID_P to a
pointer to the new node-id which will be allocated in POOL.
@@ -5897,6 +5926,10 @@ write_hash_rep(svn_filesize_t *size,
If REPS_TO_CACHE is not NULL, append to it a copy (allocated in
REPS_POOL) of each data rep that is new in this revision.
+ AT_ROOT is true if the node revision being written is the root
+ node-revision. It is only controls additional sanity checking
+ logic.
+
Temporary allocations are also from POOL. */
static svn_error_t *
write_final_rev(const svn_fs_id_t **new_id_p,
@@ -5909,6 +5942,7 @@ write_final_rev(const svn_fs_id_t **new_
apr_off_t initial_offset,
apr_array_header_t *reps_to_cache,
apr_pool_t *reps_pool,
+ svn_boolean_t at_root,
apr_pool_t *pool)
{
node_revision_t *noderev;
@@ -5945,7 +5979,7 @@ write_final_rev(const svn_fs_id_t **new_
svn_pool_clear(subpool);
SVN_ERR(write_final_rev(&new_id, file, rev, fs, dirent->id,
start_node_id, start_copy_id, initial_offset,
- reps_to_cache, reps_pool,
+ reps_to_cache, reps_pool, FALSE,
subpool));
if (new_id && (svn_fs_fs__id_rev(new_id) == rev))
dirent->id = svn_fs_fs__id_copy(new_id, pool);
@@ -6043,6 +6077,8 @@ write_final_rev(const svn_fs_id_t **new_
noderev->id = new_id;
/* Write out our new node-revision. */
+ if (at_root)
+ SVN_ERR(validate_root_noderev(noderev, rev, pool));
SVN_ERR(svn_fs_fs__write_noderev(svn_stream_from_aprfile2(file, TRUE, pool),
noderev, ffd->format,
svn_fs_fs__fs_supports_mergeinfo(fs),
@@ -6322,7 +6358,7 @@ commit_body(void *baton, apr_pool_t *poo
root_id = svn_fs_fs__id_txn_create("0", "0", cb->txn->id, pool);
SVN_ERR(write_final_rev(&new_root_id, proto_file, new_rev, cb->fs, root_id,
start_node_id, start_copy_id, initial_offset,
- cb->reps_to_cache, cb->reps_pool,
+ cb->reps_to_cache, cb->reps_pool, TRUE,
pool));
/* Write the changed-path information. */