From c767f7b73995d6228c702fcaeb1fa2b97aa93e09 Mon Sep 17 00:00:00 2001 From: Matthew Leeds Date: Mon, 11 Jun 2018 19:09:28 -0700 Subject: [PATCH 01/12] admin: Fix list of subcommands in help and manpage This adds subcommands that were missing from the ostree-admin man page, and makes cosmetic fixes there and in the --help output to ensure alphabetical order and remove trailing whitespace. Closes: #1621 Approved by: jlebon --- man/ostree-admin.xml | 6 ++++-- src/ostree/ot-builtin-admin.c | 12 ++++++------ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/man/ostree-admin.xml b/man/ostree-admin.xml index 53d07db5..5dc81466 100644 --- a/man/ostree-admin.xml +++ b/man/ostree-admin.xml @@ -73,11 +73,13 @@ Boston, MA 02111-1307, USA. init-fs instutil os-init - status + pin set-origin + status switch undeploy - upgrade + unlock + upgrade diff --git a/src/ostree/ot-builtin-admin.c b/src/ostree/ot-builtin-admin.c index b26eea81..9f1a6156 100644 --- a/src/ostree/ot-builtin-admin.c +++ b/src/ostree/ot-builtin-admin.c @@ -42,6 +42,9 @@ static OstreeCommand admin_subcommands[] = { { "deploy", OSTREE_BUILTIN_FLAG_NO_REPO, ot_admin_builtin_deploy, "Checkout revision REFSPEC as the new default deployment" }, + { "finalize-staged", OSTREE_BUILTIN_FLAG_NO_REPO | OSTREE_BUILTIN_FLAG_HIDDEN, + ot_admin_builtin_finalize_staged, + "Internal command to run at shutdown time" }, { "init-fs", OSTREE_BUILTIN_FLAG_NO_REPO, ot_admin_builtin_init_fs, "Initialize a root filesystem" }, @@ -51,15 +54,12 @@ static OstreeCommand admin_subcommands[] = { { "os-init", OSTREE_BUILTIN_FLAG_NO_REPO, ot_admin_builtin_os_init, "Initialize empty state for given operating system" }, - { "set-origin", OSTREE_BUILTIN_FLAG_NO_REPO, - ot_admin_builtin_set_origin, - "Set Origin and create a new origin file" }, { "pin", OSTREE_BUILTIN_FLAG_NO_REPO, ot_admin_builtin_pin, "Change the \"pinning\" state of a deployment" }, - { "finalize-staged", OSTREE_BUILTIN_FLAG_NO_REPO | OSTREE_BUILTIN_FLAG_HIDDEN, - ot_admin_builtin_finalize_staged, - "Internal command to run at shutdown time" }, + { "set-origin", OSTREE_BUILTIN_FLAG_NO_REPO, + ot_admin_builtin_set_origin, + "Set Origin and create a new origin file" }, { "status", OSTREE_BUILTIN_FLAG_NO_REPO, ot_admin_builtin_status, "List deployments" }, From 31809d32f2268208a4f3e9e27b6882d39e4a75e0 Mon Sep 17 00:00:00 2001 From: Umang Jain Date: Tue, 12 Jun 2018 02:36:31 +0530 Subject: [PATCH 02/12] lib/repo: Add min-free-space-size option Similar to min-free-space-percent but it supports specific sizes (in MB, GB or TB). Also, making min-free-space-percent and -size mutually exclusive. min-free-space-percent does not give a fine tuning of the free disk space that a user might decide to keep. It can translate to very large size (e.g. 1% = ~10GB on 1TB HDD) or very small (e.g. 1% = ~330MB on 32GB system like Endless devices). Hence, it makes sense to introduce a config option to honor specific size as per the user. Closes: #1616 Approved by: jlebon --- man/ostree.repo-config.xml | 9 ++ src/libostree/ostree-repo-commit.c | 43 ++++++++-- src/libostree/ostree-repo-private.h | 1 + src/libostree/ostree-repo.c | 83 ++++++++++++++++--- .../nondestructive/itest-pull-space.sh | 15 ++++ 5 files changed, 132 insertions(+), 19 deletions(-) diff --git a/man/ostree.repo-config.xml b/man/ostree.repo-config.xml index cbc605f7..5a95cafa 100644 --- a/man/ostree.repo-config.xml +++ b/man/ostree.repo-config.xml @@ -124,6 +124,15 @@ Boston, MA 02111-1307, USA. keep free. The default value is 3. + + min-free-space-size + Value (in MB, GB or TB) that specifies a minimum space (in blocks) + in the underlying filesystem to keep free. Also, note that min-free-space-percent + and min-free-space-size are mutually exclusive. Examples of acceptable values: + 500MB, 1GB etc. + + + add-remotes-config-dir diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c index 8285a1a0..06ade885 100644 --- a/src/libostree/ostree-repo-commit.c +++ b/src/libostree/ostree-repo-commit.c @@ -889,7 +889,7 @@ write_content_object (OstreeRepo *self, size = 0; /* Free space check; only applies during transactions */ - if (self->min_free_space_percent > 0 && self->in_transaction) + if ((self->min_free_space_percent > 0 || self->min_free_space_size > 0) && self->in_transaction) { g_mutex_lock (&self->txn_lock); g_assert_cmpint (self->txn.blocksize, >, 0); @@ -898,8 +898,12 @@ write_content_object (OstreeRepo *self, { g_mutex_unlock (&self->txn_lock); g_autofree char *formatted_required = g_format_size ((guint64)object_blocks * self->txn.blocksize); - return glnx_throw (error, "min-free-space-percent '%u%%' would be exceeded, %s more required", - self->min_free_space_percent, formatted_required); + if (self->min_free_space_percent > 0) + return glnx_throw (error, "min-free-space-percent '%u%%' would be exceeded, %s more required", + self->min_free_space_percent, formatted_required); + else + return glnx_throw (error, "min-free-space-size %luMB would be exceeded, %s more required", + self->min_free_space_size, formatted_required); } /* This is the main bit that needs mutex protection */ self->txn.max_blocks -= object_blocks; @@ -1491,6 +1495,25 @@ devino_cache_lookup (OstreeRepo *self, return dev_ino_val->checksum; } +static guint64 +min_free_space_calculate_reserved_blocks (OstreeRepo *self, struct statvfs *stvfsbuf) +{ + guint64 reserved_blocks = 0; + + if (self->min_free_space_size > 0) + { + reserved_blocks = (self->min_free_space_size << 20) / stvfsbuf->f_bsize; + } + else if (self->min_free_space_percent > 0) + { + /* Convert fragment to blocks to compute the total */ + guint64 total_blocks = (stvfsbuf->f_frsize * stvfsbuf->f_blocks) / stvfsbuf->f_bsize; + reserved_blocks = ((double)total_blocks) * (self->min_free_space_percent/100.0); + } + + return reserved_blocks; +} + /** * ostree_repo_scan_hardlinks: * @self: An #OstreeRepo @@ -1572,26 +1595,28 @@ ostree_repo_prepare_transaction (OstreeRepo *self, return FALSE; self->in_transaction = TRUE; - if (self->min_free_space_percent > 0) + if (self->min_free_space_percent >= 0 || self->min_free_space_size >= 0) { struct statvfs stvfsbuf; if (TEMP_FAILURE_RETRY (fstatvfs (self->repo_dir_fd, &stvfsbuf)) < 0) return glnx_throw_errno_prefix (error, "fstatvfs"); g_mutex_lock (&self->txn_lock); self->txn.blocksize = stvfsbuf.f_bsize; - /* Convert fragment to blocks to compute the total */ - guint64 total_blocks = (stvfsbuf.f_frsize * stvfsbuf.f_blocks) / stvfsbuf.f_bsize; + guint64 reserved_blocks = min_free_space_calculate_reserved_blocks (self, &stvfsbuf); /* Use the appropriate free block count if we're unprivileged */ guint64 bfree = (getuid () != 0 ? stvfsbuf.f_bavail : stvfsbuf.f_bfree); - guint64 reserved_blocks = ((double)total_blocks) * (self->min_free_space_percent/100.0); if (bfree > reserved_blocks) self->txn.max_blocks = bfree - reserved_blocks; else { g_mutex_unlock (&self->txn_lock); g_autofree char *formatted_free = g_format_size (bfree * self->txn.blocksize); - return glnx_throw (error, "min-free-space-percent '%u%%' would be exceeded, %s available", - self->min_free_space_percent, formatted_free); + if (self->min_free_space_percent > 0) + return glnx_throw (error, "min-free-space-percent '%u%%' would be exceeded, %s available", + self->min_free_space_percent, formatted_free); + else + return glnx_throw (error, "min-free-space-size %luMB would be exceeded, %s available", + self->min_free_space_size, formatted_free); } g_mutex_unlock (&self->txn_lock); } diff --git a/src/libostree/ostree-repo-private.h b/src/libostree/ostree-repo-private.h index 63aa451a..eefb80e3 100644 --- a/src/libostree/ostree-repo-private.h +++ b/src/libostree/ostree-repo-private.h @@ -151,6 +151,7 @@ struct OstreeRepo { uid_t target_owner_uid; /* Ensure files are chowned to this uid/gid */ gid_t target_owner_gid; guint min_free_space_percent; /* See the min-free-space-percent config option */ + guint64 min_free_space_size; /* See the min-free-space-size config option */ guint test_error_flags; /* OstreeRepoTestErrorFlags */ diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index f3da1cae..fa5a9bf8 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -2654,6 +2654,48 @@ get_remotes_d_dir (OstreeRepo *self, return g_file_resolve_relative_path (sysroot, SYSCONF_REMOTES); } +static gboolean +min_free_space_size_validate_and_convert (OstreeRepo *self, + const char *min_free_space_size_str, + GError **error) +{ + static GRegex *regex; + static gsize regex_initialized; + if (g_once_init_enter (®ex_initialized)) + { + regex = g_regex_new ("^([0-9]+)(G|M|T)B$", 0, 0, NULL); + g_assert (regex); + g_once_init_leave (®ex_initialized, 1); + } + + g_autoptr(GMatchInfo) match = NULL; + if (!g_regex_match (regex, min_free_space_size_str, 0, &match)) + return glnx_prefix_error (error, "Error parsing min-free-space-size parameter: '%s'", min_free_space_size_str); + + g_autofree char *size_str = g_match_info_fetch (match, 1); + g_autofree char *unit = g_match_info_fetch (match, 2); + guint shifts; + + switch (*unit) + { + case 'M': + shifts = 0; + break; + case 'G': + shifts = 10; + break; + case 'T': + shifts = 20; + break; + default: + g_assert_not_reached (); + } + + self->min_free_space_size = g_ascii_strtoull (size_str, NULL, 10) << shifts; + + return TRUE; +} + static gboolean reload_core_config (OstreeRepo *self, GCancellable *cancellable, @@ -2771,18 +2813,39 @@ reload_core_config (OstreeRepo *self, self->zlib_compression_level = OSTREE_ARCHIVE_DEFAULT_COMPRESSION_LEVEL; } - { g_autofree char *min_free_space_percent_str = NULL; - /* If changing this, be sure to change the man page too */ - const char *default_min_free_space = "3"; + { + if (g_key_file_has_key (self->config, "core", "min-free-space-size", error) && + g_key_file_has_key (self->config, "core", "min-free-space-percent", error)) + { + return glnx_throw (error, "min-free-space-percent and min-free-space-size are mutually exclusive."); + } + else if (g_key_file_has_key (self->config, "core", "min-free-space-size", error)) + { + g_autofree char *min_free_space_size_str = NULL; - if (!ot_keyfile_get_value_with_default (self->config, "core", "min-free-space-percent", - default_min_free_space, - &min_free_space_percent_str, error)) - return FALSE; + if (!ot_keyfile_get_value_with_default (self->config, "core", "min-free-space-size", + NULL, &min_free_space_size_str, error)) + return FALSE; - self->min_free_space_percent = g_ascii_strtoull (min_free_space_percent_str, NULL, 10); - if (self->min_free_space_percent > 99) - return glnx_throw (error, "Invalid min-free-space-percent '%s'", min_free_space_percent_str); + /* Validate the string and convert the size to MBs */ + if (!min_free_space_size_validate_and_convert (self, min_free_space_size_str, error)) + return glnx_throw (error, "Invalid min-free-space-size '%s'", min_free_space_size_str); + } + else + { + g_autofree char *min_free_space_percent_str = NULL; + /* If changing this, be sure to change the man page too */ + const char *default_min_free_space = "3"; + + if (!ot_keyfile_get_value_with_default (self->config, "core", "min-free-space-percent", + default_min_free_space, + &min_free_space_percent_str, error)) + return FALSE; + + self->min_free_space_percent = g_ascii_strtoull (min_free_space_percent_str, NULL, 10); + if (self->min_free_space_percent > 99) + return glnx_throw (error, "Invalid min-free-space-percent '%s'", min_free_space_percent_str); + } } { diff --git a/tests/installed/nondestructive/itest-pull-space.sh b/tests/installed/nondestructive/itest-pull-space.sh index 925629b2..bb3f1546 100755 --- a/tests/installed/nondestructive/itest-pull-space.sh +++ b/tests/installed/nondestructive/itest-pull-space.sh @@ -16,12 +16,27 @@ blkdev=$(losetup --find --show $(pwd)/testblk.img) mkfs.xfs ${blkdev} mkdir mnt mount ${blkdev} mnt + +# first test min-free-space-percent ostree --repo=mnt/repo init --mode=bare-user echo 'fsync=false' >> mnt/repo/config if ostree --repo=mnt/repo pull-local /ostree/repo ${host_commit} 2>err.txt; then fatal "succeeded in doing a pull with no free space" fi assert_file_has_content err.txt "min-free-space-percent" +echo "ok min-free-space-percent" + +# now test min-free-space-size +rm -rf mnt/repo +ostree --repo=mnt/repo init --mode=bare-user +echo 'fsync=false' >> mnt/repo/config +echo 'min-free-space-size=10MB' >> mnt/repo/config +if ostree --repo=mnt/repo pull-local /ostree/repo ${host_commit} 2>err.txt; then + fatal "succeeded in doing a pull with no free space" +fi +assert_file_has_content err.txt "min-free-space-size" +echo "ok min-free-space-size" + umount mnt losetup -d ${blkdev} date From 2d2f218669e6230edaf6329913a2b2c1cda590ed Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Thu, 14 Jun 2018 16:47:43 +0100 Subject: [PATCH 03/12] lib/repo-commit: Delay propagation of errors from abort_transaction() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If there’s a problem while aborting a transaction, store the error but don’t report it until the end of the function — do a best effort at clearing the rest of the transaction state first (since most of it cannot fail). If cleanup_tmpdir() fails (which, arguably, should not be a showstopper), this allows a caller to recover and start a new transaction in future. Signed-off-by: Philip Withnall Closes: #1626 Approved by: jlebon --- src/libostree/ostree-repo-commit.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c index 06ade885..be5e55cd 100644 --- a/src/libostree/ostree-repo-commit.c +++ b/src/libostree/ostree-repo-commit.c @@ -2188,6 +2188,8 @@ ostree_repo_abort_transaction (OstreeRepo *self, GCancellable *cancellable, GError **error) { + g_autoptr(GError) cleanup_error = NULL; + /* Always ignore the cancellable to avoid the chance that, if it gets * canceled, the transaction may not be fully cleaned up. * See https://github.com/ostreedev/ostree/issues/1491 . @@ -2198,8 +2200,9 @@ ostree_repo_abort_transaction (OstreeRepo *self, if (!self->in_transaction) return TRUE; - if (!cleanup_tmpdir (self, cancellable, error)) - return FALSE; + /* Do not propagate failures from cleanup_tmpdir() immediately, as we want + * to clean up the rest of the internal transaction state first. */ + cleanup_tmpdir (self, cancellable, &cleanup_error); if (self->loose_object_devino_hash) g_hash_table_remove_all (self->loose_object_devino_hash); @@ -2219,6 +2222,13 @@ ostree_repo_abort_transaction (OstreeRepo *self, self->txn_locked = FALSE; } + /* Propagate cleanup_tmpdir() failure. */ + if (cleanup_error != NULL) + { + g_propagate_error (error, g_steal_pointer (&cleanup_error)); + return FALSE; + } + return TRUE; } From 677e1810254685a1ec34679c5b1f5324236b091d Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Wed, 13 Jun 2018 19:20:28 +0200 Subject: [PATCH 04/12] ostree_repo_resolve_rev: Resolve refs set in the transaction This allows you to get at the current commit for a ref pending in the transaction. Closes: #1624 Approved by: cgwalters --- src/libostree/ostree-repo-refs.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/libostree/ostree-repo-refs.c b/src/libostree/ostree-repo-refs.c index d10e302e..2600cb7c 100644 --- a/src/libostree/ostree-repo-refs.c +++ b/src/libostree/ostree-repo-refs.c @@ -245,7 +245,28 @@ resolve_refspec (OstreeRepo *self, { ret_rev = g_strdup (ref); } - else if (remote != NULL) + else if (self->in_transaction) + { + const char *refspec; + + if (remote != NULL) + refspec = glnx_strjoina (remote, ":", ref); + else + refspec = ref; + + g_mutex_lock (&self->txn_lock); + if (self->txn.refs) + ret_rev = g_strdup (g_hash_table_lookup (self->txn.refs, refspec)); + g_mutex_unlock (&self->txn_lock); + } + + if (ret_rev != NULL) + { + ot_transfer_out_value (out_rev, &ret_rev); + return TRUE; + } + + if (remote != NULL) { const char *remote_ref = glnx_strjoina ("refs/remotes/", remote, "/", ref); From 7dc3e45b3a2a0946182159121d2d3b7d7b938697 Mon Sep 17 00:00:00 2001 From: Matthew Leeds Date: Thu, 14 Jun 2018 14:33:10 -0700 Subject: [PATCH 05/12] lib/prune: Don't modify dirent->d_name in place Currently when I run `ostree prune` it hits a seg fault when the hash_func is used (in this case g_str_hash) from the call stack _ostree_repo_prune_tmp() -> g_hash_table_contains() -> g_hash_table_lookup_node(). So the key, in this case dent->d_name, must be corrupt in some way. glnx_dirfd_iterator_next_dent() uses readdir() to get the dirent struct. And according to the man page for readdir(3), "POSIX.1 explicitly notes that this field should not be used as an lvalue" (in reference to d_name). So this commit avoids modifying d_name in place and copies it instead. This seems to avoid the seg fault. Closes: #1627 Approved by: jlebon --- src/libostree/ostree-repo-prune.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/libostree/ostree-repo-prune.c b/src/libostree/ostree-repo-prune.c index b93d35ac..7ab9dc8d 100644 --- a/src/libostree/ostree-repo-prune.c +++ b/src/libostree/ostree-repo-prune.c @@ -153,26 +153,29 @@ _ostree_repo_prune_tmp (OstreeRepo *self, size_t len; gboolean has_sig_suffix = FALSE; struct dirent *dent; + g_autofree gchar *d_name = NULL; if (!glnx_dirfd_iterator_next_dent (&dfd_iter, &dent, cancellable, error)) return FALSE; if (dent == NULL) break; - len = strlen (dent->d_name); - if (len > 4 && g_strcmp0 (dent->d_name + len - 4, ".sig") == 0) + /* dirent->d_name can't be modified directly; see `man 3 readdir` */ + d_name = g_strdup (dent->d_name); + len = strlen (d_name); + if (len > 4 && g_strcmp0 (d_name + len - 4, ".sig") == 0) { has_sig_suffix = TRUE; - dent->d_name[len - 4] = '\0'; + d_name[len - 4] = '\0'; } - if (!g_hash_table_contains (self->remotes, dent->d_name)) + if (!g_hash_table_contains (self->remotes, d_name)) { /* Restore the previous value to get the file name. */ if (has_sig_suffix) - dent->d_name[len - 4] = '.'; + d_name[len - 4] = '.'; - if (!glnx_unlinkat (dfd_iter.fd, dent->d_name, 0, error)) + if (!glnx_unlinkat (dfd_iter.fd, d_name, 0, error)) return FALSE; } } From ce58307757c9e42b2d949d1566038174bccd4fe1 Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Sat, 25 Jul 2015 09:51:14 -0700 Subject: [PATCH 06/12] deploy: Delete .updated file from /etc and /var on new deployments Systemd units using ConditionNeedsUpdate run if the mtime of .updated in the specified directory is newer than /usr. Since /usr has an mtime of 0, there's no way to have an older .updated file. Systemd units typically specify ConditionNeedsUpdate=/etc or ConditionNeedsUpdate=/var to support stateless systems like ostree. Remove the file from the new deployment's /etc and the OS's /var regardless of where they came from to ensure that these systemd units run when booting new deployments. This will provide a method to run services only on upgrade. Closes: #1628 https://bugzilla.gnome.org/show_bug.cgi?id=752950 Closes: #1631 Approved by: cgwalters --- Makefile-tests.am | 1 + src/libostree/ostree-sysroot-deploy.c | 23 ++++++--- tests/test-admin-upgrade-systemd-update.sh | 58 ++++++++++++++++++++++ 3 files changed, 75 insertions(+), 7 deletions(-) create mode 100755 tests/test-admin-upgrade-systemd-update.sh diff --git a/Makefile-tests.am b/Makefile-tests.am index 97a71d0d..85995aa6 100644 --- a/Makefile-tests.am +++ b/Makefile-tests.am @@ -94,6 +94,7 @@ _installed_or_uninstalled_test_scripts = \ tests/test-gpg-signed-commit.sh \ tests/test-admin-upgrade-unconfigured.sh \ tests/test-admin-upgrade-endoflife.sh \ + tests/test-admin-upgrade-systemd-update.sh \ tests/test-admin-deploy-syslinux.sh \ tests/test-admin-deploy-2.sh \ tests/test-admin-deploy-karg.sh \ diff --git a/src/libostree/ostree-sysroot-deploy.c b/src/libostree/ostree-sysroot-deploy.c index 6f0f6efd..08bf4c0d 100644 --- a/src/libostree/ostree-sysroot-deploy.c +++ b/src/libostree/ostree-sysroot-deploy.c @@ -684,15 +684,10 @@ selinux_relabel_dir (OstreeSysroot *sysroot, static gboolean selinux_relabel_var_if_needed (OstreeSysroot *sysroot, OstreeSePolicy *sepolicy, - OstreeDeployment *deployment, + int os_deploy_dfd, GCancellable *cancellable, GError **error) { - const char *osdeploypath = glnx_strjoina ("ostree/deploy/", ostree_deployment_get_osname (deployment)); - glnx_autofd int os_deploy_dfd = -1; - if (!glnx_opendirat (sysroot->sysroot_fd, osdeploypath, TRUE, &os_deploy_dfd, error)) - return FALSE; - /* This is a bit of a hack; we should change the code at some * point in the distant future to only create (and label) /var * when doing a deployment. @@ -2529,11 +2524,25 @@ sysroot_finalize_deployment (OstreeSysroot *self, return FALSE; } + const char *osdeploypath = glnx_strjoina ("ostree/deploy/", ostree_deployment_get_osname (deployment)); + glnx_autofd int os_deploy_dfd = -1; + if (!glnx_opendirat (self->sysroot_fd, osdeploypath, TRUE, &os_deploy_dfd, error)) + return FALSE; + + /* Ensure that the new deployment does not have /etc/.updated or + * /var/.updated so that systemd ConditionNeedsUpdate=/etc|/var services run + * after rebooting. + */ + if (!ot_ensure_unlinked_at (deployment_dfd, "etc/.updated", error)) + return FALSE; + if (!ot_ensure_unlinked_at (os_deploy_dfd, "var/.updated", error)) + return FALSE; + g_autoptr(OstreeSePolicy) sepolicy = ostree_sepolicy_new_at (deployment_dfd, cancellable, error); if (!sepolicy) return FALSE; - if (!selinux_relabel_var_if_needed (self, sepolicy, deployment, cancellable, error)) + if (!selinux_relabel_var_if_needed (self, sepolicy, os_deploy_dfd, cancellable, error)) return FALSE; /* Rewrite the origin using the final merged selinux config, just to be diff --git a/tests/test-admin-upgrade-systemd-update.sh b/tests/test-admin-upgrade-systemd-update.sh new file mode 100755 index 00000000..94b750d7 --- /dev/null +++ b/tests/test-admin-upgrade-systemd-update.sh @@ -0,0 +1,58 @@ +#!/bin/bash +# +# Copyright (C) 2014 Colin Walters +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +set -euo pipefail + +. $(dirname $0)/libtest.sh + +# Exports OSTREE_SYSROOT so --sysroot not needed. +setup_os_repository "archive-z2" "syslinux" + +echo "1..2" + +# Setup a deployment +cd ${test_tmpdir} +${CMD_PREFIX} ostree --repo=sysroot/ostree/repo remote add --set=gpg-verify=false testos $(cat httpd-address)/ostree/testos-repo +${CMD_PREFIX} ostree --repo=sysroot/ostree/repo pull testos testos/buildmaster/x86_64-runtime +rev=$(${CMD_PREFIX} ostree --repo=sysroot/ostree/repo rev-parse testos/buildmaster/x86_64-runtime) +${CMD_PREFIX} ostree admin deploy --os=testos testos:testos/buildmaster/x86_64-runtime +assert_has_dir sysroot/ostree/deploy/testos/deploy/${rev}.0/usr +assert_has_dir sysroot/ostree/deploy/testos/deploy/${rev}.0/etc +assert_has_dir sysroot/ostree/deploy/testos/var +assert_not_has_file sysroot/ostree/deploy/testos/deploy/${rev}.0/etc/.updated +assert_not_has_file sysroot/ostree/deploy/testos/var/.updated + +echo "ok deploy" + +# Create the /etc/.updated and /var/.updated files with /usr modification time +usr=sysroot/ostree/deploy/testos/deploy/${rev}.0/usr +touch -r ${usr} sysroot/ostree/deploy/testos/deploy/${rev}.0/etc/.updated +touch -r ${usr} sysroot/ostree/deploy/testos/var/.updated + +# Make a new commit, upgrade and ensure .updated files are gone in the +# new deployment but /etc/.updated still exists in the previous +# (current) deployment +os_repository_new_commit +${CMD_PREFIX} ostree admin upgrade --os=testos +newrev=$(${CMD_PREFIX} ostree --repo=sysroot/ostree/repo rev-parse testos/buildmaster/x86_64-runtime) +assert_not_has_file sysroot/ostree/deploy/testos/deploy/${newrev}.0/etc/.updated +assert_not_has_file sysroot/ostree/deploy/testos/var/.updated +assert_has_file sysroot/ostree/deploy/testos/deploy/${rev}.0/etc/.updated + +echo "ok .updated files removed" From cc5254ac34219e187e6963314248308e4a396152 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Fri, 15 Jun 2018 21:10:14 +0000 Subject: [PATCH 07/12] lib/archive: Tell g-ir-scanner to ignore the private libarchive bits Squashes this warning: ``` src/libostree/ostree-libarchive-private.h:46: syntax error, unexpected typedef-name in ' g_autoptr(OtAutoArchiveRead) a = archive_read_new ();' at 'OtAutoArchiveRead' ``` Closes: #1629 Approved by: jlebon --- src/libostree/ostree-libarchive-private.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/libostree/ostree-libarchive-private.h b/src/libostree/ostree-libarchive-private.h index 7529f41e..4a98b6d1 100644 --- a/src/libostree/ostree-libarchive-private.h +++ b/src/libostree/ostree-libarchive-private.h @@ -23,6 +23,9 @@ #pragma once +/* Private, not for introspection */ +#ifndef __GI_SCANNER__ + #include "config.h" #include @@ -64,3 +67,5 @@ ot_open_archive_read (const char *path, GError **error) #endif G_END_DECLS + +#endif From a2b08f934267500d05bee87bb4388944cda0a700 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Mon, 18 Jun 2018 10:36:33 -0400 Subject: [PATCH 08/12] lib/repo: Fix double-set-error in min-free-space-size code We need to pass `NULL` as the error, we only care if the key exists; otherwise we'll try to set the error twice. Closes: #1632 Approved by: jlebon --- src/libostree/ostree-repo.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index fa5a9bf8..8e7e4ca0 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -2670,7 +2670,7 @@ min_free_space_size_validate_and_convert (OstreeRepo *self, g_autoptr(GMatchInfo) match = NULL; if (!g_regex_match (regex, min_free_space_size_str, 0, &match)) - return glnx_prefix_error (error, "Error parsing min-free-space-size parameter: '%s'", min_free_space_size_str); + return glnx_prefix_error (error, "Failed to parse min-free-space-size parameter: '%s'", min_free_space_size_str); g_autofree char *size_str = g_match_info_fetch (match, 1); g_autofree char *unit = g_match_info_fetch (match, 2); @@ -2814,12 +2814,12 @@ reload_core_config (OstreeRepo *self, } { - if (g_key_file_has_key (self->config, "core", "min-free-space-size", error) && - g_key_file_has_key (self->config, "core", "min-free-space-percent", error)) + if (g_key_file_has_key (self->config, "core", "min-free-space-size", NULL) && + g_key_file_has_key (self->config, "core", "min-free-space-percent", NULL)) { - return glnx_throw (error, "min-free-space-percent and min-free-space-size are mutually exclusive."); + return glnx_throw (error, "min-free-space-percent and min-free-space-size are mutually exclusive"); } - else if (g_key_file_has_key (self->config, "core", "min-free-space-size", error)) + else if (g_key_file_has_key (self->config, "core", "min-free-space-size", NULL)) { g_autofree char *min_free_space_size_str = NULL; From acab2c1ac6a6a30f0298feb2cbfcb3dc5e515d8a Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Mon, 18 Jun 2018 14:40:24 +0000 Subject: [PATCH 09/12] lib/repo: Rename free_space_size variable to free_space_mb I generally like having variables include their units where applicable; timer variables having `_secs` or `_ms`, etc. Closes: #1632 Approved by: jlebon --- src/libostree/ostree-repo-commit.c | 12 ++++++------ src/libostree/ostree-repo-private.h | 2 +- src/libostree/ostree-repo.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c index be5e55cd..0642828c 100644 --- a/src/libostree/ostree-repo-commit.c +++ b/src/libostree/ostree-repo-commit.c @@ -889,7 +889,7 @@ write_content_object (OstreeRepo *self, size = 0; /* Free space check; only applies during transactions */ - if ((self->min_free_space_percent > 0 || self->min_free_space_size > 0) && self->in_transaction) + if ((self->min_free_space_percent > 0 || self->min_free_space_mb > 0) && self->in_transaction) { g_mutex_lock (&self->txn_lock); g_assert_cmpint (self->txn.blocksize, >, 0); @@ -903,7 +903,7 @@ write_content_object (OstreeRepo *self, self->min_free_space_percent, formatted_required); else return glnx_throw (error, "min-free-space-size %luMB would be exceeded, %s more required", - self->min_free_space_size, formatted_required); + self->min_free_space_mb, formatted_required); } /* This is the main bit that needs mutex protection */ self->txn.max_blocks -= object_blocks; @@ -1500,9 +1500,9 @@ min_free_space_calculate_reserved_blocks (OstreeRepo *self, struct statvfs *stvf { guint64 reserved_blocks = 0; - if (self->min_free_space_size > 0) + if (self->min_free_space_mb > 0) { - reserved_blocks = (self->min_free_space_size << 20) / stvfsbuf->f_bsize; + reserved_blocks = (self->min_free_space_mb << 20) / stvfsbuf->f_bsize; } else if (self->min_free_space_percent > 0) { @@ -1595,7 +1595,7 @@ ostree_repo_prepare_transaction (OstreeRepo *self, return FALSE; self->in_transaction = TRUE; - if (self->min_free_space_percent >= 0 || self->min_free_space_size >= 0) + if (self->min_free_space_percent >= 0 || self->min_free_space_mb >= 0) { struct statvfs stvfsbuf; if (TEMP_FAILURE_RETRY (fstatvfs (self->repo_dir_fd, &stvfsbuf)) < 0) @@ -1616,7 +1616,7 @@ ostree_repo_prepare_transaction (OstreeRepo *self, self->min_free_space_percent, formatted_free); else return glnx_throw (error, "min-free-space-size %luMB would be exceeded, %s available", - self->min_free_space_size, formatted_free); + self->min_free_space_mb, formatted_free); } g_mutex_unlock (&self->txn_lock); } diff --git a/src/libostree/ostree-repo-private.h b/src/libostree/ostree-repo-private.h index eefb80e3..69f53921 100644 --- a/src/libostree/ostree-repo-private.h +++ b/src/libostree/ostree-repo-private.h @@ -151,7 +151,7 @@ struct OstreeRepo { uid_t target_owner_uid; /* Ensure files are chowned to this uid/gid */ gid_t target_owner_gid; guint min_free_space_percent; /* See the min-free-space-percent config option */ - guint64 min_free_space_size; /* See the min-free-space-size config option */ + guint64 min_free_space_mb; /* See the min-free-space-size config option */ guint test_error_flags; /* OstreeRepoTestErrorFlags */ diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index 8e7e4ca0..d64e4125 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -2691,7 +2691,7 @@ min_free_space_size_validate_and_convert (OstreeRepo *self, g_assert_not_reached (); } - self->min_free_space_size = g_ascii_strtoull (size_str, NULL, 10) << shifts; + self->min_free_space_mb = g_ascii_strtoull (size_str, NULL, 10) << shifts; return TRUE; } From 5e9d3828114d18340a93a30458cf8ac716f6f21e Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Mon, 18 Jun 2018 14:47:49 +0000 Subject: [PATCH 10/12] lib/repo: Do free space math under lock in error path We were referencing the txn bits outside of the lock in the error path. Generally shouldn't matter, but e.g. Rust wouldn't let us do this, and race detector tooling will warn about it. Closes: #1632 Approved by: jlebon --- src/libostree/ostree-repo-commit.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c index 0642828c..37be748b 100644 --- a/src/libostree/ostree-repo-commit.c +++ b/src/libostree/ostree-repo-commit.c @@ -896,8 +896,9 @@ write_content_object (OstreeRepo *self, const fsblkcnt_t object_blocks = (size / self->txn.blocksize) + 1; if (object_blocks > self->txn.max_blocks) { + guint64 bytes_required = (guint64)object_blocks * self->txn.blocksize; g_mutex_unlock (&self->txn_lock); - g_autofree char *formatted_required = g_format_size ((guint64)object_blocks * self->txn.blocksize); + g_autofree char *formatted_required = g_format_size (bytes_required); if (self->min_free_space_percent > 0) return glnx_throw (error, "min-free-space-percent '%u%%' would be exceeded, %s more required", self->min_free_space_percent, formatted_required); @@ -1609,8 +1610,9 @@ ostree_repo_prepare_transaction (OstreeRepo *self, self->txn.max_blocks = bfree - reserved_blocks; else { + guint64 bytes_required = bfree * self->txn.blocksize; g_mutex_unlock (&self->txn_lock); - g_autofree char *formatted_free = g_format_size (bfree * self->txn.blocksize); + g_autofree char *formatted_free = g_format_size (bytes_required); if (self->min_free_space_percent > 0) return glnx_throw (error, "min-free-space-percent '%u%%' would be exceeded, %s available", self->min_free_space_percent, formatted_free); From 0f88a2a72d55a949019675cd03e72c478f4f14db Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Mon, 18 Jun 2018 11:11:21 -0400 Subject: [PATCH 11/12] tests/installed: Add a free-space success path test We implicitly test the success percent path a lot, but not the absolute path. Closes: #1632 Approved by: jlebon --- tests/installed/nondestructive/itest-pull-space.sh | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/installed/nondestructive/itest-pull-space.sh b/tests/installed/nondestructive/itest-pull-space.sh index bb3f1546..8fcf1e8a 100755 --- a/tests/installed/nondestructive/itest-pull-space.sh +++ b/tests/installed/nondestructive/itest-pull-space.sh @@ -35,8 +35,17 @@ if ostree --repo=mnt/repo pull-local /ostree/repo ${host_commit} 2>err.txt; then fatal "succeeded in doing a pull with no free space" fi assert_file_has_content err.txt "min-free-space-size" -echo "ok min-free-space-size" +echo "ok min-free-space-size (error)" umount mnt losetup -d ${blkdev} +rm testblk.img + +# min-free-space-size success +ostree --repo=repo init --mode=bare-user +echo 'fsync=false' >> repo/config +echo 'min-free-space-size=1MB' >> repo/config +ostree --repo=repo pull-local /ostree/repo ${host_commit} +echo "ok min-free-space-size (success)" + date From 31a356dca9656fcc62b5af11502e20d2d9aa7e91 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Tue, 19 Jun 2018 14:10:27 +0000 Subject: [PATCH 12/12] Release 2018.6 --- configure.ac | 2 +- src/libostree/libostree-devel.sym | 53 --------------------------- src/libostree/libostree-released.sym | 54 ++++++++++++++++++++++++++++ tests/test-symbols.sh | 2 +- 4 files changed, 56 insertions(+), 55 deletions(-) diff --git a/configure.ac b/configure.ac index 1f6ea34c..e3b15262 100644 --- a/configure.ac +++ b/configure.ac @@ -7,7 +7,7 @@ m4_define([year_version], [2018]) m4_define([release_version], [6]) m4_define([package_version], [year_version.release_version]) AC_INIT([libostree], [package_version], [walters@verbum.org]) -is_release_build=no +is_release_build=yes AC_CONFIG_HEADER([config.h]) AC_CONFIG_MACRO_DIR([buildutil]) AC_CONFIG_AUX_DIR([build-aux]) diff --git a/src/libostree/libostree-devel.sym b/src/libostree/libostree-devel.sym index 832ab84c..a4040ba6 100644 --- a/src/libostree/libostree-devel.sym +++ b/src/libostree/libostree-devel.sym @@ -18,59 +18,6 @@ ***/ /* Add new symbols here. Release commits should copy this section into -released.sym. */ -LIBOSTREE_2018.6 { -global: - ostree_collection_ref_dup; - ostree_collection_ref_dupv; - ostree_collection_ref_equal; - ostree_collection_ref_free; - ostree_collection_ref_freev; - ostree_collection_ref_get_type; - ostree_collection_ref_hash; - ostree_collection_ref_new; - ostree_remote_get_name; - ostree_remote_get_type; - ostree_remote_get_url; - ostree_remote_ref; - ostree_remote_unref; - ostree_repo_find_remotes_async; - ostree_repo_find_remotes_finish; - ostree_repo_finder_avahi_get_type; - ostree_repo_finder_avahi_new; - ostree_repo_finder_avahi_start; - ostree_repo_finder_avahi_stop; - ostree_repo_finder_config_get_type; - ostree_repo_finder_config_new; - ostree_repo_finder_get_type; - ostree_repo_finder_mount_get_type; - ostree_repo_finder_mount_new; - ostree_repo_finder_override_add_uri; - ostree_repo_finder_override_get_type; - ostree_repo_finder_override_new; - ostree_repo_finder_resolve_all_async; - ostree_repo_finder_resolve_all_finish; - ostree_repo_finder_resolve_async; - ostree_repo_finder_resolve_finish; - ostree_repo_finder_result_compare; - ostree_repo_finder_result_dup; - ostree_repo_finder_result_free; - ostree_repo_finder_result_freev; - ostree_repo_finder_result_get_type; - ostree_repo_finder_result_new; - ostree_repo_get_collection_id; - ostree_repo_list_collection_refs; - ostree_repo_pull_from_remotes_async; - ostree_repo_pull_from_remotes_finish; - ostree_repo_remote_list_collection_refs; - ostree_repo_resolve_collection_ref; - ostree_repo_resolve_keyring_for_collection; - ostree_repo_set_collection_id; - ostree_repo_set_collection_ref_immediate; - ostree_repo_transaction_set_collection_ref; - ostree_repo_traverse_reachable_refs; - ostree_sysroot_cleanup_prune_repo; - ostree_validate_collection_id; -} LIBOSTREE_2018.5; /* Stub section for the stable release *after* this development one; don't * edit this other than to update the last number. This is just a copy/paste diff --git a/src/libostree/libostree-released.sym b/src/libostree/libostree-released.sym index 533bc5c2..c3c1d502 100644 --- a/src/libostree/libostree-released.sym +++ b/src/libostree/libostree-released.sym @@ -473,6 +473,60 @@ LIBOSTREE_2018.5 { ostree_repo_traverse_commit_union_with_parents; } LIBOSTREE_2018.3; +LIBOSTREE_2018.6 { +global: + ostree_collection_ref_dup; + ostree_collection_ref_dupv; + ostree_collection_ref_equal; + ostree_collection_ref_free; + ostree_collection_ref_freev; + ostree_collection_ref_get_type; + ostree_collection_ref_hash; + ostree_collection_ref_new; + ostree_remote_get_name; + ostree_remote_get_type; + ostree_remote_get_url; + ostree_remote_ref; + ostree_remote_unref; + ostree_repo_find_remotes_async; + ostree_repo_find_remotes_finish; + ostree_repo_finder_avahi_get_type; + ostree_repo_finder_avahi_new; + ostree_repo_finder_avahi_start; + ostree_repo_finder_avahi_stop; + ostree_repo_finder_config_get_type; + ostree_repo_finder_config_new; + ostree_repo_finder_get_type; + ostree_repo_finder_mount_get_type; + ostree_repo_finder_mount_new; + ostree_repo_finder_override_add_uri; + ostree_repo_finder_override_get_type; + ostree_repo_finder_override_new; + ostree_repo_finder_resolve_all_async; + ostree_repo_finder_resolve_all_finish; + ostree_repo_finder_resolve_async; + ostree_repo_finder_resolve_finish; + ostree_repo_finder_result_compare; + ostree_repo_finder_result_dup; + ostree_repo_finder_result_free; + ostree_repo_finder_result_freev; + ostree_repo_finder_result_get_type; + ostree_repo_finder_result_new; + ostree_repo_get_collection_id; + ostree_repo_list_collection_refs; + ostree_repo_pull_from_remotes_async; + ostree_repo_pull_from_remotes_finish; + ostree_repo_remote_list_collection_refs; + ostree_repo_resolve_collection_ref; + ostree_repo_resolve_keyring_for_collection; + ostree_repo_set_collection_id; + ostree_repo_set_collection_ref_immediate; + ostree_repo_transaction_set_collection_ref; + ostree_repo_traverse_reachable_refs; + ostree_sysroot_cleanup_prune_repo; + ostree_validate_collection_id; +} LIBOSTREE_2018.5; + /* NOTE: Only add more content here in release commits! See the * comments at the top of this file. */ diff --git a/tests/test-symbols.sh b/tests/test-symbols.sh index 501bedeb..57e5f6e1 100755 --- a/tests/test-symbols.sh +++ b/tests/test-symbols.sh @@ -54,7 +54,7 @@ echo 'ok documented symbols' # ONLY update this checksum in release commits! cat > released-sha256.txt <