You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2012/03/20 17:38:17 UTC
svn commit: r1302987 - in /subversion/branches/1.6.x-issue4129: ./
subversion/libsvn_fs_fs/fs_fs.c subversion/libsvn_fs_fs/tree.c
subversion/libsvn_fs_fs/tree.h
Author: stsp
Date: Tue Mar 20 16:38:17 2012
New Revision: 1302987
URL: http://svn.apache.org/viewvc?rev=1302987&view=rev
Log:
On the 1.6.x-issue4129 branch, merge r1178280, r1178282, r1186121,
and r1186231 from trunk. The regression test added for issue #4129
relies on these changes.
Modified:
subversion/branches/1.6.x-issue4129/ (props changed)
subversion/branches/1.6.x-issue4129/subversion/libsvn_fs_fs/fs_fs.c
subversion/branches/1.6.x-issue4129/subversion/libsvn_fs_fs/tree.c
subversion/branches/1.6.x-issue4129/subversion/libsvn_fs_fs/tree.h
Propchange: subversion/branches/1.6.x-issue4129/
------------------------------------------------------------------------------
Merged /subversion/trunk:r1178280,1178282,1186121,1186231
Modified: subversion/branches/1.6.x-issue4129/subversion/libsvn_fs_fs/fs_fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.6.x-issue4129/subversion/libsvn_fs_fs/fs_fs.c?rev=1302987&r1=1302986&r2=1302987&view=diff
==============================================================================
--- subversion/branches/1.6.x-issue4129/subversion/libsvn_fs_fs/fs_fs.c (original)
+++ subversion/branches/1.6.x-issue4129/subversion/libsvn_fs_fs/fs_fs.c Tue Mar 20 16:38:17 2012
@@ -5345,6 +5345,62 @@ 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 in FS. Use POOL for temporary
+ allocations.
+ */
+static svn_error_t *
+validate_root_noderev(svn_fs_t *fs,
+ node_revision_t *root_noderev,
+ svn_revnum_t rev,
+ apr_pool_t *pool)
+{
+ svn_revnum_t head_revnum = rev-1;
+ int head_predecessor_count;
+
+ SVN_ERR_ASSERT(rev > 0);
+
+ /* Compute HEAD_PREDECESSOR_COUNT. */
+ {
+ svn_fs_root_t *head_revision;
+ const svn_fs_id_t *head_root_id;
+ node_revision_t *head_root_noderev;
+
+ /* Get /@HEAD's noderev. */
+ SVN_ERR(svn_fs_fs__revision_root(&head_revision, fs, head_revnum, pool));
+ SVN_ERR(svn_fs_fs__node_id(&head_root_id, head_revision, "/", pool));
+ SVN_ERR(svn_fs_fs__get_node_revision(&head_root_noderev, fs, head_root_id,
+ pool));
+
+ head_predecessor_count = head_root_noderev->predecessor_count;
+ }
+
+ /* Check that the root noderev's predecessor count equals REV.
+
+ This kind of corruption was seen on svn.apache.org (both on
+ the root noderev and on other fspaths' noderevs); see
+ http://mid.gmane.org/20111002202833.GA12373@daniel3.local
+
+ Normally (rev == root_noderev->predecessor_count), but here we
+ use a more roundabout check that should only trigger on new instances
+ of the corruption, rather then trigger on each and every new commit
+ to a repository that has triggered the bug somewhere in its root
+ noderev's history.
+ */
+ if (root_noderev->predecessor_count != -1
+ && (root_noderev->predecessor_count - head_predecessor_count)
+ != (rev - head_revnum))
+ {
+ 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. Return the offset of
the new node-revision in *OFFSET. If this is a directory, all
@@ -5360,7 +5416,11 @@ 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.
- Temporary allocations are from POOL. */
+ 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,
apr_file_t *file,
@@ -5372,6 +5432,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;
@@ -5410,7 +5471,7 @@ write_final_rev(const svn_fs_id_t **new_
dirent = val;
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);
@@ -5508,6 +5569,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(fs, 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),
@@ -5818,7 +5881,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. */
Modified: subversion/branches/1.6.x-issue4129/subversion/libsvn_fs_fs/tree.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.6.x-issue4129/subversion/libsvn_fs_fs/tree.c?rev=1302987&r1=1302986&r2=1302987&view=diff
==============================================================================
--- subversion/branches/1.6.x-issue4129/subversion/libsvn_fs_fs/tree.c (original)
+++ subversion/branches/1.6.x-issue4129/subversion/libsvn_fs_fs/tree.c Tue Mar 20 16:38:17 2012
@@ -866,11 +866,11 @@ add_change(svn_fs_t *fs,
/* Get the id of a node referenced by path PATH in ROOT. Return the
id in *ID_P allocated in POOL. */
-static svn_error_t *
-fs_node_id(const svn_fs_id_t **id_p,
- svn_fs_root_t *root,
- const char *path,
- apr_pool_t *pool)
+svn_error_t *
+svn_fs_fs__node_id(const svn_fs_id_t **id_p,
+ svn_fs_root_t *root,
+ const char *path,
+ apr_pool_t *pool)
{
if ((! root->is_txn_root)
&& (path[0] == '\0' || ((path[0] == '/') && (path[1] == '\0'))))
@@ -935,7 +935,7 @@ node_kind(svn_node_kind_t *kind_p,
dag_node_t *node;
/* Get the node id. */
- SVN_ERR(fs_node_id(&node_id, root, path, pool));
+ SVN_ERR(svn_fs_fs__node_id(&node_id, root, path, pool));
/* Use the node id to get the real kind. */
SVN_ERR(svn_fs_fs__dag_get_node(&node, root->fs, node_id, pool));
@@ -2956,7 +2956,7 @@ fs_node_origin_rev(svn_revnum_t *revisio
path = svn_fs__canonicalize_abspath(path, pool);
/* Check the cache first. */
- SVN_ERR(fs_node_id(&given_noderev_id, root, path, pool));
+ SVN_ERR(svn_fs_fs__node_id(&given_noderev_id, root, path, pool));
node_id = svn_fs_fs__id_node_id(given_noderev_id);
/* Is it a brand new uncommitted node? */
@@ -3028,7 +3028,7 @@ fs_node_origin_rev(svn_revnum_t *revisio
}
/* Walk the predecessor links back to origin. */
- SVN_ERR(fs_node_id(&pred_id, curroot, lastpath->data, predidpool));
+ SVN_ERR(svn_fs_fs__node_id(&pred_id, curroot, lastpath->data, predidpool));
while (pred_id)
{
svn_pool_clear(subpool);
@@ -3654,7 +3654,7 @@ static root_vtable_t root_vtable = {
fs_paths_changed,
svn_fs_fs__check_path,
fs_node_history,
- fs_node_id,
+ svn_fs_fs__node_id,
svn_fs_fs__node_created_rev,
fs_node_origin_rev,
fs_node_created_path,
Modified: subversion/branches/1.6.x-issue4129/subversion/libsvn_fs_fs/tree.h
URL: http://svn.apache.org/viewvc/subversion/branches/1.6.x-issue4129/subversion/libsvn_fs_fs/tree.h?rev=1302987&r1=1302986&r2=1302987&view=diff
==============================================================================
--- subversion/branches/1.6.x-issue4129/subversion/libsvn_fs_fs/tree.h (original)
+++ subversion/branches/1.6.x-issue4129/subversion/libsvn_fs_fs/tree.h Tue Mar 20 16:38:17 2012
@@ -55,6 +55,13 @@ svn_fs_fs__check_path(svn_node_kind_t *k
const char *path,
apr_pool_t *pool);
+/* Implement root_vtable_t.node_id(). */
+svn_error_t *
+svn_fs_fs__node_id(const svn_fs_id_t **id_p,
+ svn_fs_root_t *root,
+ const char *path,
+ apr_pool_t *pool);
+
/* Set *REVISION to the revision in which PATH under ROOT was created.
Use POOL for any temporary allocations. If PATH is in an
uncommitted transaction, *REVISION will be set to