fsck: Mark commits with missing or deleted object partial
This means we can later use various operations to heal the repository because ostree does not assume all objects are there. This the begining of a fix for https://github.com/ostreedev/ostree/pull/345 Closes: #1533 Approved by: cgwalters
This commit is contained in:
parent
f258e9e5ff
commit
474556b955
|
|
@ -53,6 +53,8 @@ static gboolean
|
||||||
fsck_one_object (OstreeRepo *repo,
|
fsck_one_object (OstreeRepo *repo,
|
||||||
const char *checksum,
|
const char *checksum,
|
||||||
OstreeObjectType objtype,
|
OstreeObjectType objtype,
|
||||||
|
GHashTable *object_parents,
|
||||||
|
GVariant *key,
|
||||||
gboolean *out_found_corruption,
|
gboolean *out_found_corruption,
|
||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
GError **error)
|
GError **error)
|
||||||
|
|
@ -60,12 +62,14 @@ fsck_one_object (OstreeRepo *repo,
|
||||||
g_autoptr(GError) temp_error = NULL;
|
g_autoptr(GError) temp_error = NULL;
|
||||||
if (!ostree_repo_fsck_object (repo, objtype, checksum, cancellable, &temp_error))
|
if (!ostree_repo_fsck_object (repo, objtype, checksum, cancellable, &temp_error))
|
||||||
{
|
{
|
||||||
|
gboolean object_missing = FALSE;
|
||||||
|
|
||||||
if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
|
if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
|
||||||
{
|
{
|
||||||
g_clear_error (&temp_error);
|
g_clear_error (&temp_error);
|
||||||
g_printerr ("Object missing: %s.%s\n", checksum,
|
g_printerr ("Object missing: %s.%s\n", checksum,
|
||||||
ostree_object_type_to_string (objtype));
|
ostree_object_type_to_string (objtype));
|
||||||
*out_found_corruption = TRUE;
|
object_missing = TRUE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -73,7 +77,7 @@ fsck_one_object (OstreeRepo *repo,
|
||||||
{
|
{
|
||||||
g_printerr ("%s\n", temp_error->message);
|
g_printerr ("%s\n", temp_error->message);
|
||||||
(void) ostree_repo_delete_object (repo, objtype, checksum, cancellable, NULL);
|
(void) ostree_repo_delete_object (repo, objtype, checksum, cancellable, NULL);
|
||||||
*out_found_corruption = TRUE;
|
object_missing = TRUE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -81,6 +85,26 @@ fsck_one_object (OstreeRepo *repo,
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (object_missing)
|
||||||
|
{
|
||||||
|
*out_found_corruption = TRUE;
|
||||||
|
|
||||||
|
if (object_parents != NULL && objtype != OSTREE_OBJECT_TYPE_COMMIT)
|
||||||
|
{
|
||||||
|
g_auto(GStrv) parent_commits = ostree_repo_traverse_parents_get_commits (object_parents, key);
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* The commit was missing or deleted, mark the commit partial */
|
||||||
|
for (i = 0; parent_commits[i] != NULL; i++)
|
||||||
|
{
|
||||||
|
const char *parent_commit = parent_commits[i];
|
||||||
|
g_printerr ("Marking commit %s as partial\n", parent_commit);
|
||||||
|
if (!ostree_repo_mark_commit_partial (repo, parent_commit, TRUE, error))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
@ -94,6 +118,7 @@ fsck_reachable_objects_from_commits (OstreeRepo *repo,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
g_autoptr(GHashTable) reachable_objects = ostree_repo_traverse_new_reachable ();
|
g_autoptr(GHashTable) reachable_objects = ostree_repo_traverse_new_reachable ();
|
||||||
|
g_autoptr(GHashTable) object_parents = ostree_repo_traverse_new_parents ();
|
||||||
|
|
||||||
GHashTableIter hash_iter;
|
GHashTableIter hash_iter;
|
||||||
gpointer key, value;
|
gpointer key, value;
|
||||||
|
|
@ -108,7 +133,7 @@ fsck_reachable_objects_from_commits (OstreeRepo *repo,
|
||||||
|
|
||||||
g_assert (objtype == OSTREE_OBJECT_TYPE_COMMIT);
|
g_assert (objtype == OSTREE_OBJECT_TYPE_COMMIT);
|
||||||
|
|
||||||
if (!ostree_repo_traverse_commit_union (repo, checksum, 0, reachable_objects,
|
if (!ostree_repo_traverse_commit_union_with_parents (repo, checksum, 0, reachable_objects, object_parents,
|
||||||
cancellable, error))
|
cancellable, error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
@ -127,8 +152,9 @@ fsck_reachable_objects_from_commits (OstreeRepo *repo,
|
||||||
|
|
||||||
ostree_object_name_deserialize (serialized_key, &checksum, &objtype);
|
ostree_object_name_deserialize (serialized_key, &checksum, &objtype);
|
||||||
|
|
||||||
if (!fsck_one_object (repo, checksum, objtype, out_found_corruption,
|
if (!fsck_one_object (repo, checksum, objtype,
|
||||||
cancellable, error))
|
object_parents, serialized_key,
|
||||||
|
out_found_corruption, cancellable, error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
|
|
@ -150,7 +176,7 @@ fsck_commit_for_ref (OstreeRepo *repo,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
if (!fsck_one_object (repo, checksum, OSTREE_OBJECT_TYPE_COMMIT,
|
if (!fsck_one_object (repo, checksum, OSTREE_OBJECT_TYPE_COMMIT,
|
||||||
found_corruption,
|
NULL, NULL, found_corruption,
|
||||||
cancellable, error))
|
cancellable, error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,20 @@ ostree --repo=bare-repo init --mode=bare-user
|
||||||
ostree --repo=bare-repo remote add origin --set=gpg-verify=false $(cat ${test_tmpdir}/httpd-address)
|
ostree --repo=bare-repo remote add origin --set=gpg-verify=false $(cat ${test_tmpdir}/httpd-address)
|
||||||
log_timestamps ostree --repo=bare-repo pull --disable-static-deltas origin ${host_nonremoteref}
|
log_timestamps ostree --repo=bare-repo pull --disable-static-deltas origin ${host_nonremoteref}
|
||||||
|
|
||||||
|
echo "ok pull"
|
||||||
|
|
||||||
|
# fsck marks commits partial
|
||||||
|
# https://github.com/ostreedev/ostree/pull/1533
|
||||||
|
for d in $(find bare-repo/objects/ -maxdepth 1 -type d); do
|
||||||
|
(find ${d} -name '*.file' || true) | head -20 | xargs rm -vf
|
||||||
|
done
|
||||||
|
if ostree --repo=bare-repo fsck; then
|
||||||
|
fatal "fsck unexpectedly succeeded"
|
||||||
|
fi
|
||||||
|
ostree --repo=bare-repo pull origin ${host_nonremoteref}
|
||||||
|
# Don't need a full fsck here
|
||||||
|
ostree --repo=bare-repo ls origin:${host_nonremoteref} >/dev/null
|
||||||
|
|
||||||
rm bare-repo repo -rf
|
rm bare-repo repo -rf
|
||||||
|
|
||||||
# Try copying the host's repo across a mountpoint for direct
|
# Try copying the host's repo across a mountpoint for direct
|
||||||
|
|
@ -44,6 +58,7 @@ log_timestamps ostree --repo=repo fsck
|
||||||
cd ..
|
cd ..
|
||||||
umount mnt
|
umount mnt
|
||||||
|
|
||||||
|
# Cleanup
|
||||||
kill -TERM $(cat ${test_tmpdir}/httpd-pid)
|
kill -TERM $(cat ${test_tmpdir}/httpd-pid)
|
||||||
echo "ok"
|
echo "ok"
|
||||||
date
|
date
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
echo "1..6"
|
echo "1..8"
|
||||||
|
|
||||||
. $(dirname $0)/libtest.sh
|
. $(dirname $0)/libtest.sh
|
||||||
|
|
||||||
|
|
@ -89,3 +89,43 @@ if ${CMD_PREFIX} ostree --repo=ostree-path-traverse/repo checkout pathtraverse-t
|
||||||
fi
|
fi
|
||||||
assert_file_has_content_literal err.txt 'Invalid / in filename ../afile'
|
assert_file_has_content_literal err.txt 'Invalid / in filename ../afile'
|
||||||
echo "ok path traverse checkout"
|
echo "ok path traverse checkout"
|
||||||
|
|
||||||
|
cd ${test_tmpdir}
|
||||||
|
rm repo files -rf
|
||||||
|
setup_test_repository "bare"
|
||||||
|
|
||||||
|
rev=$($OSTREE rev-parse test2)
|
||||||
|
|
||||||
|
filechecksum=$(ostree_file_path_to_checksum repo test2 /firstfile)
|
||||||
|
rm repo/$(ostree_checksum_to_relative_object_path repo $filechecksum)
|
||||||
|
|
||||||
|
assert_not_has_file repo/state/${rev}.commitpartial
|
||||||
|
|
||||||
|
if $OSTREE fsck -q 2>err.txt; then
|
||||||
|
assert_not_reached "fsck unexpectedly succeeded"
|
||||||
|
fi
|
||||||
|
assert_file_has_content_literal err.txt "Object missing:"
|
||||||
|
assert_file_has_content_literal err.txt "Marking commit $rev as partial"
|
||||||
|
assert_has_file repo/state/${rev}.commitpartial
|
||||||
|
|
||||||
|
echo "ok missing file"
|
||||||
|
|
||||||
|
cd ${test_tmpdir}
|
||||||
|
rm repo files -rf
|
||||||
|
setup_test_repository "bare"
|
||||||
|
|
||||||
|
rev=$($OSTREE rev-parse test2)
|
||||||
|
|
||||||
|
filechecksum=$(ostree_file_path_to_checksum repo test2 /firstfile)
|
||||||
|
echo corrupted >> repo/$(ostree_checksum_to_relative_object_path repo $filechecksum)
|
||||||
|
|
||||||
|
assert_not_has_file repo/state/${rev}.commitpartial
|
||||||
|
|
||||||
|
if $OSTREE fsck -q --delete 2>err.txt; then
|
||||||
|
assert_not_reached "fsck unexpectedly succeeded"
|
||||||
|
fi
|
||||||
|
assert_file_has_content_literal err.txt "Corrupted file object;"
|
||||||
|
assert_file_has_content_literal err.txt "Marking commit $rev as partial"
|
||||||
|
assert_has_file repo/state/${rev}.commitpartial
|
||||||
|
|
||||||
|
echo "ok corrupt file"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue