checkout: Add an option to require hardlinks
I've seen a few people hit this and wonder why checkouts are slow/take space. Really, ensuring this happens is the *point* of OSTree. Physical copies should be a last resort fallback for very unusual situations (one of those is rpm-ostree checking out the db since librpm doesn't know how to read from libostree). Even I hit the fact that `/var` is a mountpoint disallowing hardlinks with `/ostree` once and was confused. =) Add this to the rofiles-fuse test case because it creates a mount point. Closes: #368 Approved by: jlebon
This commit is contained in:
parent
da989b473d
commit
439069b2bb
|
|
@ -346,7 +346,7 @@ checkout_file_hardlink (OstreeRepo *self,
|
||||||
again:
|
again:
|
||||||
if (linkat (srcfd, loose_path, destination_dfd, destination_name, 0) != -1)
|
if (linkat (srcfd, loose_path, destination_dfd, destination_name, 0) != -1)
|
||||||
ret_was_supported = TRUE;
|
ret_was_supported = TRUE;
|
||||||
else if (errno == EMLINK || errno == EXDEV || errno == EPERM)
|
else if (!options->no_copy_fallback && (errno == EMLINK || errno == EXDEV || errno == EPERM))
|
||||||
{
|
{
|
||||||
/* EMLINK, EXDEV and EPERM shouldn't be fatal; we just can't do the
|
/* EMLINK, EXDEV and EPERM shouldn't be fatal; we just can't do the
|
||||||
* optimization of hardlinking instead of copying.
|
* optimization of hardlinking instead of copying.
|
||||||
|
|
|
||||||
|
|
@ -750,7 +750,8 @@ typedef struct {
|
||||||
guint enable_uncompressed_cache : 1;
|
guint enable_uncompressed_cache : 1;
|
||||||
guint disable_fsync : 1;
|
guint disable_fsync : 1;
|
||||||
guint process_whiteouts : 1;
|
guint process_whiteouts : 1;
|
||||||
guint reserved : 29;
|
guint no_copy_fallback : 1;
|
||||||
|
guint reserved : 28;
|
||||||
|
|
||||||
const char *subpath;
|
const char *subpath;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ static gboolean opt_whiteouts;
|
||||||
static gboolean opt_from_stdin;
|
static gboolean opt_from_stdin;
|
||||||
static char *opt_from_file;
|
static char *opt_from_file;
|
||||||
static gboolean opt_disable_fsync;
|
static gboolean opt_disable_fsync;
|
||||||
|
static gboolean opt_require_hardlinks;
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
parse_fsync_cb (const char *option_name,
|
parse_fsync_cb (const char *option_name,
|
||||||
|
|
@ -67,6 +68,7 @@ static GOptionEntry options[] = {
|
||||||
{ "from-stdin", 0, 0, G_OPTION_ARG_NONE, &opt_from_stdin, "Process many checkouts from standard input", NULL },
|
{ "from-stdin", 0, 0, G_OPTION_ARG_NONE, &opt_from_stdin, "Process many checkouts from standard input", NULL },
|
||||||
{ "from-file", 0, 0, G_OPTION_ARG_STRING, &opt_from_file, "Process many checkouts from input file", "FILE" },
|
{ "from-file", 0, 0, G_OPTION_ARG_STRING, &opt_from_file, "Process many checkouts from input file", "FILE" },
|
||||||
{ "fsync", 0, 0, G_OPTION_ARG_CALLBACK, parse_fsync_cb, "Specify how to invoke fsync()", "POLICY" },
|
{ "fsync", 0, 0, G_OPTION_ARG_CALLBACK, parse_fsync_cb, "Specify how to invoke fsync()", "POLICY" },
|
||||||
|
{ "require-hardlinks", 'H', 0, G_OPTION_ARG_NONE, &opt_require_hardlinks, "Do not fall back to full copies if hardlinking fails", NULL },
|
||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -85,7 +87,7 @@ process_one_checkout (OstreeRepo *repo,
|
||||||
* `ostree_repo_checkout_tree_at` until such time as we have a more
|
* `ostree_repo_checkout_tree_at` until such time as we have a more
|
||||||
* convenient infrastructure for testing C APIs with data.
|
* convenient infrastructure for testing C APIs with data.
|
||||||
*/
|
*/
|
||||||
if (opt_disable_cache || opt_whiteouts)
|
if (opt_disable_cache || opt_whiteouts || opt_require_hardlinks)
|
||||||
{
|
{
|
||||||
OstreeRepoCheckoutOptions options = { 0, };
|
OstreeRepoCheckoutOptions options = { 0, };
|
||||||
|
|
||||||
|
|
@ -97,6 +99,7 @@ process_one_checkout (OstreeRepo *repo,
|
||||||
options.process_whiteouts = TRUE;
|
options.process_whiteouts = TRUE;
|
||||||
if (subpath)
|
if (subpath)
|
||||||
options.subpath = subpath;
|
options.subpath = subpath;
|
||||||
|
options.no_copy_fallback = opt_require_hardlinks;
|
||||||
|
|
||||||
if (!ostree_repo_checkout_tree_at (repo, &options,
|
if (!ostree_repo_checkout_tree_at (repo, &options,
|
||||||
AT_FDCWD, destination,
|
AT_FDCWD, destination,
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ skip_without_user_xattrs
|
||||||
|
|
||||||
setup_test_repository "bare-user"
|
setup_test_repository "bare-user"
|
||||||
|
|
||||||
echo "1..5"
|
echo "1..6"
|
||||||
|
|
||||||
mkdir mnt
|
mkdir mnt
|
||||||
|
|
||||||
|
|
@ -71,3 +71,13 @@ echo "ok deletion"
|
||||||
${CMD_PREFIX} ostree --repo=repo commit -b test2 -s fromfuse --link-checkout-speedup --tree=dir=checkout-test2
|
${CMD_PREFIX} ostree --repo=repo commit -b test2 -s fromfuse --link-checkout-speedup --tree=dir=checkout-test2
|
||||||
|
|
||||||
echo "ok commit"
|
echo "ok commit"
|
||||||
|
|
||||||
|
${CMD_PREFIX} ostree --repo=repo checkout -U test2 mnt/test2-checkout-copy-fallback
|
||||||
|
assert_file_has_content mnt/test2-checkout-copy-fallback/anewfile-for-fuse anewfile-for-fuse
|
||||||
|
|
||||||
|
if ${CMD_PREFIX} ostree --repo=repo checkout -UH test2 mnt/test2-checkout-copy-hardlinked 2>err.txt; then
|
||||||
|
assert_not_reached "Checking out via hardlinks across mountpoint unexpectedly succeeded!"
|
||||||
|
fi
|
||||||
|
assert_file_has_content err.txt "Invalid cross-device link"
|
||||||
|
|
||||||
|
echo "ok checkout copy fallback"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue