diff options
author | Colin Walters <walters@verbum.org> | 2023-04-14 14:44:38 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-04-14 14:44:38 -0400 |
commit | 90f7c7bd9f98ebcdff81e0363a4d0117b876d5c3 (patch) | |
tree | 8089f5e13e9295171fe7ceb0a7bf33f525822e8c | |
parent | e509b24a01a949cab6cda18c39263d6ce88d62fe (diff) | |
parent | 462d413d2e8ef4e8196ac99c142dd165086f7b69 (diff) | |
download | ostree-90f7c7bd9f98ebcdff81e0363a4d0117b876d5c3.tar.gz |
Merge pull request #2848 from jlebon/pr/calculate-and-cleanup-prep
Prep patches for automatic early prune
-rw-r--r-- | src/libostree/ostree-sysroot-cleanup.c | 145 | ||||
-rw-r--r-- | src/libostree/ostree-sysroot-private.h | 14 | ||||
-rw-r--r-- | src/libotutil/ot-fs-utils.c | 44 | ||||
-rw-r--r-- | src/libotutil/ot-fs-utils.h | 7 |
4 files changed, 130 insertions, 80 deletions
diff --git a/src/libostree/ostree-sysroot-cleanup.c b/src/libostree/ostree-sysroot-cleanup.c index 181dbd16..533a4fdd 100644 --- a/src/libostree/ostree-sysroot-cleanup.c +++ b/src/libostree/ostree-sysroot-cleanup.c @@ -108,10 +108,10 @@ list_all_deployment_directories (OstreeSysroot *self, return TRUE; } -static gboolean -parse_bootdir_name (const char *name, - char **out_osname, - char **out_csum) +gboolean +_ostree_sysroot_parse_bootdir_name (const char *name, + char **out_osname, + char **out_csum) { const char *lastdash; @@ -136,69 +136,42 @@ parse_bootdir_name (const char *name, return TRUE; } -static gboolean -list_all_boot_directories (OstreeSysroot *self, - GPtrArray **out_bootdirs, - GCancellable *cancellable, - GError **error) +gboolean +_ostree_sysroot_list_all_boot_directories (OstreeSysroot *self, + char ***out_bootdirs, + GCancellable *cancellable, + GError **error) { - gboolean ret = FALSE; - g_autoptr(GFile) boot_ostree = NULL; - g_autoptr(GPtrArray) ret_bootdirs = NULL; - GError *temp_error = NULL; + g_autoptr(GPtrArray) ret_bootdirs = g_ptr_array_new_with_free_func (g_free); - boot_ostree = g_file_resolve_relative_path (self->path, "boot/ostree"); - - ret_bootdirs = g_ptr_array_new_with_free_func (g_object_unref); - - g_autoptr(GFileEnumerator) dir_enum = - g_file_enumerate_children (boot_ostree, OSTREE_GIO_FAST_QUERYINFO, - G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, - cancellable, &temp_error); - if (!dir_enum) - { - if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) - { - g_clear_error (&temp_error); - goto done; - } - else - { - g_propagate_error (error, temp_error); - goto out; - } - } + gboolean exists = FALSE; + g_auto(GLnxDirFdIterator) dfd_iter = { 0, }; + if (self->boot_fd >= 0 && !ot_dfd_iter_init_allow_noent (self->boot_fd, "ostree", &dfd_iter, &exists, error)) + return FALSE; - while (TRUE) + while (exists) { - GFileInfo *file_info = NULL; - GFile *child = NULL; - const char *name; - - if (!g_file_enumerator_iterate (dir_enum, &file_info, &child, - NULL, error)) - goto out; - if (file_info == NULL) + struct dirent *dent; + if (!glnx_dirfd_iterator_next_dent_ensure_dtype (&dfd_iter, &dent, cancellable, error)) + return FALSE; + if (dent == NULL) break; - if (g_file_info_get_file_type (file_info) != G_FILE_TYPE_DIRECTORY) + if (dent->d_type != DT_DIR) continue; /* Only look at directories ending in -CHECKSUM; nothing else * should be in here, but let's be conservative. */ - name = g_file_info_get_name (file_info); - if (!parse_bootdir_name (name, NULL, NULL)) + if (!_ostree_sysroot_parse_bootdir_name (dent->d_name, NULL, NULL)) continue; - g_ptr_array_add (ret_bootdirs, g_object_ref (child)); + g_ptr_array_add (ret_bootdirs, g_strdup (dent->d_name)); } - done: - ret = TRUE; - ot_transfer_out_value (out_bootdirs, &ret_bootdirs); - out: - return ret; + g_ptr_array_add (ret_bootdirs, NULL); + *out_bootdirs = (char**)g_ptr_array_free (g_steal_pointer (&ret_bootdirs), FALSE); + return TRUE; } /* A sysroot has at most one active "boot version" (pair of version,subversion) @@ -284,33 +257,15 @@ cleanup_old_deployments (OstreeSysroot *self, GCancellable *cancellable, GError **error) { - /* Gather the device/inode of the rootfs, so we can double - * check we won't delete it. - */ - struct stat root_stbuf; - if (!glnx_fstatat (AT_FDCWD, "/", &root_stbuf, 0, error)) - return FALSE; - /* Load all active deployments referenced by bootloader configuration. */ g_autoptr(GHashTable) active_deployment_dirs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); - g_autoptr(GHashTable) active_boot_checksums = - g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); - g_autoptr(GHashTable) active_overlay_initrds = - g_hash_table_new (g_str_hash, g_str_equal); /* borrows from deployment's bootconfig */ for (guint i = 0; i < self->deployments->len; i++) { OstreeDeployment *deployment = self->deployments->pdata[i]; char *deployment_path = ostree_sysroot_get_deployment_dirpath (self, deployment); - char *bootcsum = g_strdup (ostree_deployment_get_bootcsum (deployment)); /* Transfer ownership */ g_hash_table_replace (active_deployment_dirs, deployment_path, deployment_path); - g_hash_table_replace (active_boot_checksums, bootcsum, bootcsum); - - OstreeBootconfigParser *bootconfig = ostree_deployment_get_bootconfig (deployment); - char **initrds = ostree_bootconfig_parser_get_overlay_initrds (bootconfig); - for (char **it = initrds; it && *it; it++) - g_hash_table_add (active_overlay_initrds, (char*)glnx_basename (*it)); } /* Find all deployment directories, both active and inactive */ @@ -331,26 +286,53 @@ cleanup_old_deployments (OstreeSysroot *self, return FALSE; } + return TRUE; +} + +/* This function deletes any files in the bootfs unreferenced by the active + * bootloader configuration. + */ +gboolean +_ostree_sysroot_cleanup_bootfs (OstreeSysroot *self, + GCancellable *cancellable, + GError **error) +{ + /* Load all active bootcsums and overlays referenced by bootloader configuration. */ + g_autoptr(GHashTable) active_boot_checksums = + g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + g_autoptr(GHashTable) active_overlay_initrds = + g_hash_table_new (g_str_hash, g_str_equal); /* borrows from deployment's bootconfig */ + for (guint i = 0; i < self->deployments->len; i++) + { + OstreeDeployment *deployment = self->deployments->pdata[i]; + char *bootcsum = g_strdup (ostree_deployment_get_bootcsum (deployment)); + /* Transfer ownership */ + g_hash_table_replace (active_boot_checksums, bootcsum, bootcsum); + + OstreeBootconfigParser *bootconfig = ostree_deployment_get_bootconfig (deployment); + char **initrds = ostree_bootconfig_parser_get_overlay_initrds (bootconfig); + for (char **it = initrds; it && *it; it++) + g_hash_table_add (active_overlay_initrds, (char*)glnx_basename (*it)); + } + /* Clean up boot directories */ - g_autoptr(GPtrArray) all_boot_dirs = NULL; - if (!list_all_boot_directories (self, &all_boot_dirs, - cancellable, error)) + g_auto(GStrv) all_boot_dirs = NULL; + if (!_ostree_sysroot_list_all_boot_directories (self, &all_boot_dirs, cancellable, error)) return FALSE; - for (guint i = 0; i < all_boot_dirs->len; i++) + for (char **it = all_boot_dirs; it && *it; it++) { - GFile *bootdir = all_boot_dirs->pdata[i]; - g_autofree char *osname = NULL; + char *bootdir = *it; g_autofree char *bootcsum = NULL; - if (!parse_bootdir_name (glnx_basename (gs_file_get_path_cached (bootdir)), - &osname, &bootcsum)) - g_assert_not_reached (); + if (!_ostree_sysroot_parse_bootdir_name (bootdir, NULL, &bootcsum)) + g_assert_not_reached (); /* checked in _ostree_sysroot_list_all_boot_directories() */ if (g_hash_table_lookup (active_boot_checksums, bootcsum)) continue; - if (!glnx_shutil_rm_rf_at (AT_FDCWD, gs_file_get_path_cached (bootdir), cancellable, error)) + g_autofree char *subpath = g_build_filename ("ostree", bootdir, NULL); + if (!glnx_shutil_rm_rf_at (self->boot_fd, subpath, cancellable, error)) return FALSE; } @@ -590,6 +572,9 @@ _ostree_sysroot_cleanup_internal (OstreeSysroot *self, if (!cleanup_old_deployments (self, cancellable, error)) return glnx_prefix_error (error, "Cleaning deployments"); + if (!_ostree_sysroot_cleanup_bootfs (self, cancellable, error)) + return glnx_prefix_error (error, "Cleaning bootfs"); + OstreeRepo *repo = ostree_sysroot_repo (self); if (!generate_deployment_refs (self, repo, self->bootversion, diff --git a/src/libostree/ostree-sysroot-private.h b/src/libostree/ostree-sysroot-private.h index a49a406c..57ac6824 100644 --- a/src/libostree/ostree-sysroot-private.h +++ b/src/libostree/ostree-sysroot-private.h @@ -187,4 +187,18 @@ gboolean _ostree_sysroot_cleanup_internal (OstreeSysroot *sysroot, GCancellable *cancellable, GError **error); +gboolean +_ostree_sysroot_cleanup_bootfs (OstreeSysroot *self, + GCancellable *cancellable, + GError **error); + +gboolean _ostree_sysroot_parse_bootdir_name (const char *name, + char **out_osname, + char **out_csum); + +gboolean _ostree_sysroot_list_all_boot_directories (OstreeSysroot *self, + char ***out_bootdirs, + GCancellable *cancellable, + GError **error); + G_END_DECLS diff --git a/src/libotutil/ot-fs-utils.c b/src/libotutil/ot-fs-utils.c index 64ebc966..935b1bbc 100644 --- a/src/libotutil/ot-fs-utils.c +++ b/src/libotutil/ot-fs-utils.c @@ -245,3 +245,47 @@ ot_parse_file_by_line (const char *path, return TRUE; } + +/* Calculate the size of the files contained in a directory. Symlinks are not + * followed. */ +gboolean +ot_get_dir_size (int dfd, + const char *path, + guint64 *out_size, + GCancellable *cancellable, + GError **error) +{ + g_auto(GLnxDirFdIterator) dfd_iter = { 0, }; + if (!glnx_dirfd_iterator_init_at (dfd, path, FALSE, &dfd_iter, error)) + return FALSE; + + *out_size = 0; + while (TRUE) + { + struct dirent *dent; + if (!glnx_dirfd_iterator_next_dent_ensure_dtype (&dfd_iter, &dent, cancellable, error)) + return FALSE; + + if (dent == NULL) + break; + + if (dent->d_type == DT_REG) + { + struct stat stbuf; + if (!glnx_fstatat (dfd_iter.fd, dent->d_name, &stbuf, AT_SYMLINK_NOFOLLOW, error)) + return FALSE; + + *out_size += stbuf.st_size; + } + else if (dent->d_type == DT_DIR) + { + guint64 subdir_size; + if (!ot_get_dir_size (dfd_iter.fd, dent->d_name, &subdir_size, cancellable, error)) + return FALSE; + + *out_size += subdir_size; + } + } + + return TRUE; +} diff --git a/src/libotutil/ot-fs-utils.h b/src/libotutil/ot-fs-utils.h index fad4c53d..f719381d 100644 --- a/src/libotutil/ot-fs-utils.h +++ b/src/libotutil/ot-fs-utils.h @@ -95,4 +95,11 @@ ot_parse_file_by_line (const char *path, GCancellable *cancellable, GError **error); +gboolean +ot_get_dir_size (int dfd, + const char *path, + guint64 *out_size, + GCancellable *cancellable, + GError **error); + G_END_DECLS |