deploy: Change large parts to be fd-relative, drop fsync

This is a continuation of earlier work to drop the individual fsync on
files/directories in favor of relying on `syncfs()` for speed.

As part of that cleanup, I'm porting it to be fd-relative.

I feel relatively confident about this change given that this area of
the code has notable test suite coverage, although that code runs as
non-root.
This commit is contained in:
Colin Walters 2015-04-20 15:51:24 -04:00
parent 3a4f90cf8e
commit 1810de2b51
1 changed files with 118 additions and 108 deletions

View File

@ -924,114 +924,110 @@ ostree_sysroot_write_origin_file (OstreeSysroot *sysroot,
}
static gboolean
get_kernel_from_tree (GFile *deployroot,
GFile **out_kernel,
GFile **out_initramfs,
GCancellable *cancellable,
GError **error)
get_kernel_from_tree (int deployment_dfd,
int *out_boot_dfd,
char **out_kernel_name,
char **out_initramfs_name,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
g_autoptr(GFile) ostree_bootdir
= g_file_resolve_relative_path (deployroot, "usr/lib/ostree-boot");
g_autoptr(GFile) bootdir = g_file_get_child (deployroot, "boot");
g_autoptr(GFileEnumerator) dir_enum = NULL;
g_autoptr(GFile) ret_kernel = NULL;
g_autoptr(GFile) ret_initramfs = NULL;
g_autofree char *kernel_checksum = NULL;
g_autofree char *initramfs_checksum = NULL;
glnx_fd_close int ret_boot_dfd = -1;
g_auto(GLnxDirFdIterator) dfditer = { 0, };
g_autofree char *ret_kernel_name = NULL;
g_autofree char *ret_initramfs_name = NULL;
gs_free char *kernel_checksum = NULL;
gs_free char *initramfs_checksum = NULL;
if (g_file_query_exists (ostree_bootdir, NULL))
ret_boot_dfd = glnx_opendirat_with_errno (deployment_dfd, "usr/lib/ostree-boot", TRUE);
if (ret_boot_dfd == -1)
{
dir_enum = g_file_enumerate_children (ostree_bootdir, OSTREE_GIO_FAST_QUERYINFO,
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
NULL, error);
if (!dir_enum)
goto out;
}
else
{
dir_enum = g_file_enumerate_children (bootdir, OSTREE_GIO_FAST_QUERYINFO,
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
NULL, error);
if (!dir_enum)
goto out;
if (errno != ENOENT)
{
glnx_set_prefix_error_from_errno (error, "%s", "openat");
goto out;
}
else
{
if (!glnx_opendirat (deployment_dfd, "boot", TRUE, &ret_boot_dfd, error))
goto out;
}
}
if (!glnx_dirfd_iterator_init_at (ret_boot_dfd, ".", FALSE, &dfditer, error))
goto out;
while (TRUE)
{
GFileInfo *file_info = NULL;
const char *name;
struct dirent *dent;
if (!gs_file_enumerator_iterate (dir_enum, &file_info, NULL,
cancellable, error))
if (!glnx_dirfd_iterator_next_dent (&dfditer, &dent, cancellable, error))
goto out;
if (file_info == NULL)
if (dent == NULL)
break;
name = g_file_info_get_name (file_info);
if (ret_kernel == NULL && g_str_has_prefix (name, "vmlinuz-"))
if (ret_kernel_name == NULL && g_str_has_prefix (dent->d_name, "vmlinuz-"))
{
const char *dash = strrchr (name, '-');
const char *dash = strrchr (dent->d_name, '-');
g_assert (dash);
if (ostree_validate_structureof_checksum_string (dash + 1, NULL))
{
kernel_checksum = g_strdup (dash + 1);
ret_kernel = g_file_enumerator_get_child (dir_enum, file_info);
ret_kernel_name = g_strdup (dent->d_name);
}
}
else if (ret_initramfs == NULL && g_str_has_prefix (name, "initramfs-"))
else if (ret_initramfs_name == NULL && g_str_has_prefix (dent->d_name, "initramfs-"))
{
const char *dash = strrchr (name, '-');
const char *dash = strrchr (dent->d_name, '-');
g_assert (dash);
if (ostree_validate_structureof_checksum_string (dash + 1, NULL))
{
initramfs_checksum = g_strdup (dash + 1);
ret_initramfs = g_file_enumerator_get_child (dir_enum, file_info);
ret_initramfs_name = g_strdup (dent->d_name);
}
}
if (ret_kernel && ret_initramfs)
if (ret_kernel_name != NULL && ret_initramfs_name != NULL)
break;
}
if (ret_kernel == NULL)
if (ret_kernel_name == NULL)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
"Failed to find boot/vmlinuz-<CHECKSUM> in %s",
gs_file_get_path_cached (deployroot));
"Failed to find boot/vmlinuz-<CHECKSUM> in tree");
goto out;
}
if (ret_initramfs != NULL)
if (ret_initramfs_name != NULL)
{
if (strcmp (kernel_checksum, initramfs_checksum) != 0)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
"Mismatched kernel %s checksum vs initrd %s",
gs_file_get_basename_cached (ret_initramfs),
gs_file_get_basename_cached (ret_initramfs));
"Mismatched kernel checksum vs initrd in tree");
goto out;
}
}
ot_transfer_out_value (out_kernel, &ret_kernel);
ot_transfer_out_value (out_initramfs, &ret_initramfs);
*out_boot_dfd = ret_boot_dfd;
ret_boot_dfd = -1;
*out_kernel_name = g_steal_pointer (&ret_kernel_name);
*out_initramfs_name = g_steal_pointer (&ret_initramfs_name);
ret = TRUE;
out:
return ret;
}
static gboolean
checksum_from_kernel_src (GFile *src,
checksum_from_kernel_src (const char *name,
char **out_checksum,
GError **error)
{
const char *last_dash = strrchr (gs_file_get_path_cached (src), '-');
const char *last_dash = strrchr (name, '-');
if (!last_dash)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Malformed initramfs name '%s', missing '-'", gs_file_get_basename_cached (src));
"Malformed kernel/initramfs name '%s', missing '-'", name);
return FALSE;
}
*out_checksum = g_strdup (last_dash + 1);
@ -1267,16 +1263,18 @@ install_deployment_kernel (OstreeSysroot *sysroot,
const char *osname = ostree_deployment_get_osname (deployment);
const char *bootcsum = ostree_deployment_get_bootcsum (deployment);
g_autoptr(GFile) bootdir = NULL;
g_autoptr(GFile) bootcsumdir = NULL;
g_autoptr(GFile) bootconfpath = NULL;
g_autoptr(GFile) bootconfpath_parent = NULL;
g_autofree char *bootcsumdir = NULL;
g_autofree char *bootconfdir = NULL;
g_autofree char *bootconf_name = NULL;
g_autofree char *dest_kernel_name = NULL;
g_autoptr(GFile) dest_kernel_path = NULL;
g_autoptr(GFile) dest_initramfs_path = NULL;
g_autoptr(GFile) tree_kernel_path = NULL;
g_autoptr(GFile) tree_initramfs_path = NULL;
g_autoptr(GFile) deployment_dir = NULL;
g_autofree char *dest_initramfs_name = NULL;
g_autofree char *tree_kernel_name = NULL;
g_autofree char *tree_initramfs_name = NULL;
g_autofree char *deployment_dirpath = NULL;
glnx_fd_close int deployment_dfd = -1;
glnx_fd_close int tree_boot_dfd = -1;
glnx_fd_close int boot_dfd = -1;
glnx_fd_close int bootcsum_dfd = -1;
g_autofree char *contents = NULL;
g_autofree char *deployment_version = NULL;
g_autoptr(GHashTable) osrelease_values = NULL;
@ -1293,50 +1291,62 @@ install_deployment_kernel (OstreeSysroot *sysroot,
OstreeBootconfigParser *bootconfig;
bootconfig = ostree_deployment_get_bootconfig (deployment);
deployment_dir = ostree_sysroot_get_deployment_directory (sysroot, deployment);
deployment_dirpath = ostree_sysroot_get_deployment_dirpath (sysroot, deployment);
if (!glnx_opendirat (AT_FDCWD, gs_file_get_path_cached (deployment_dir), FALSE,
if (!glnx_opendirat (sysroot->sysroot_fd, deployment_dirpath, FALSE,
&deployment_dfd, error))
goto out;
if (!get_kernel_from_tree (deployment_dir, &tree_kernel_path, &tree_initramfs_path,
if (!get_kernel_from_tree (deployment_dfd, &tree_boot_dfd,
&tree_kernel_name, &tree_initramfs_name,
cancellable, error))
goto out;
bootdir = g_file_get_child (ostree_sysroot_get_path (sysroot), "boot");
bootcsumdir = ot_gfile_resolve_path_printf (bootdir, "ostree/%s-%s",
osname,
bootcsum);
bootconfpath = ot_gfile_resolve_path_printf (bootdir, "loader.%d/entries/ostree-%s-%d.conf",
new_bootversion, osname,
ostree_deployment_get_index (deployment));
if (!ot_util_ensure_directory_and_fsync (bootcsumdir, cancellable, error))
goto out;
bootconfpath_parent = g_file_get_parent (bootconfpath);
if (!ot_util_ensure_directory_and_fsync (bootconfpath_parent, cancellable, error))
if (!glnx_opendirat (sysroot->sysroot_fd, "boot", TRUE, &boot_dfd, error))
goto out;
dest_kernel_name = remove_checksum_from_kernel_name (gs_file_get_basename_cached (tree_kernel_path),
bootcsum);
dest_kernel_path = g_file_get_child (bootcsumdir, dest_kernel_name);
if (!g_file_query_exists (dest_kernel_path, NULL))
bootcsumdir = g_strdup_printf ("ostree/%s-%s", osname, bootcsum);
bootconfdir = g_strdup_printf ("loader.%d/entries", new_bootversion);
bootconf_name = g_strdup_printf ("ostree-%s-%d.conf", osname,
ostree_deployment_get_index (deployment));
if (!glnx_shutil_mkdir_p_at (boot_dfd, bootcsumdir, 0775, cancellable, error))
goto out;
if (!glnx_opendirat (boot_dfd, bootcsumdir, TRUE, &bootcsum_dfd, error))
goto out;
if (!glnx_shutil_mkdir_p_at (boot_dfd, bootconfdir, 0775, cancellable, error))
goto out;
dest_kernel_name = remove_checksum_from_kernel_name (tree_kernel_name, bootcsum);
if (fstatat (bootcsum_dfd, dest_kernel_name, &stbuf, 0) != 0)
{
if (!gs_file_linkcopy_sync_data (tree_kernel_path, dest_kernel_path, G_FILE_COPY_OVERWRITE | G_FILE_COPY_NOFOLLOW_SYMLINKS | G_FILE_COPY_ALL_METADATA,
cancellable, error))
if (errno != ENOENT)
{
glnx_set_prefix_error_from_errno (error, "fstat %s", dest_kernel_name);
goto out;
}
if (!glnx_file_copy_at (tree_boot_dfd, tree_kernel_name, NULL,
bootcsum_dfd, dest_kernel_name, 0,
cancellable, error))
goto out;
}
if (tree_initramfs_path)
if (tree_initramfs_name)
{
g_autofree char *dest_initramfs_name = remove_checksum_from_kernel_name (gs_file_get_basename_cached (tree_initramfs_path),
bootcsum);
dest_initramfs_path = g_file_get_child (bootcsumdir, dest_initramfs_name);
dest_initramfs_name = remove_checksum_from_kernel_name (tree_initramfs_name, bootcsum);
if (!g_file_query_exists (dest_initramfs_path, NULL))
if (fstatat (bootcsum_dfd, dest_initramfs_name, &stbuf, 0) != 0)
{
if (!gs_file_linkcopy_sync_data (tree_initramfs_path, dest_initramfs_path, G_FILE_COPY_OVERWRITE | G_FILE_COPY_NOFOLLOW_SYMLINKS | G_FILE_COPY_ALL_METADATA,
cancellable, error))
if (errno != ENOENT)
{
glnx_set_prefix_error_from_errno (error, "fstat %s", dest_initramfs_name);
goto out;
}
if (!glnx_file_copy_at (tree_boot_dfd, tree_initramfs_name, NULL,
bootcsum_dfd, dest_initramfs_name, 0,
cancellable, error))
goto out;
}
}
@ -1428,15 +1438,14 @@ install_deployment_kernel (OstreeSysroot *sysroot,
version_key = g_strdup_printf ("%d", n_deployments - ostree_deployment_get_index (deployment));
ostree_bootconfig_parser_set (bootconfig, "version", version_key);
linux_relpath = g_file_get_relative_path (bootdir, dest_kernel_path);
linux_key = g_strconcat ("/", linux_relpath, NULL);
ostree_bootconfig_parser_set (bootconfig, "linux", linux_key);
{ g_autofree char * boot_relpath = g_strconcat ("/", bootcsumdir, "/", dest_kernel_name, NULL);
ostree_bootconfig_parser_set (bootconfig, "linux", boot_relpath);
}
if (dest_initramfs_path)
if (dest_initramfs_name)
{
initramfs_relpath = g_file_get_relative_path (bootdir, dest_initramfs_path);
initrd_key = g_strconcat ("/", initramfs_relpath, NULL);
ostree_bootconfig_parser_set (bootconfig, "initrd", initrd_key);
g_autofree char * boot_relpath = g_strconcat ("/", bootcsumdir, "/", dest_initramfs_name, NULL);
ostree_bootconfig_parser_set (bootconfig, "initrd", boot_relpath);
}
val = ostree_bootconfig_parser_get (bootconfig, "options");
@ -1450,15 +1459,16 @@ install_deployment_kernel (OstreeSysroot *sysroot,
options_key = _ostree_kernel_args_to_string (kargs);
ostree_bootconfig_parser_set (bootconfig, "options", options_key);
if (!ostree_bootconfig_parser_write (ostree_deployment_get_bootconfig (deployment), bootconfpath,
cancellable, error))
{ glnx_fd_close int bootconf_dfd = -1;
if (!glnx_opendirat (boot_dfd, bootconfdir, TRUE, &bootconf_dfd, error))
goto out;
/* Now sync out parent directories */
if (!ot_util_fsync_directory (bootcsumdir, cancellable, error))
goto out;
if (!ot_util_fsync_directory (bootconfpath_parent, cancellable, error))
goto out;
if (!ostree_bootconfig_parser_write_at (ostree_deployment_get_bootconfig (deployment),
bootconf_dfd, bootconf_name,
cancellable, error))
goto out;
}
ret = TRUE;
out:
@ -1935,8 +1945,9 @@ ostree_sysroot_deploy_tree (OstreeSysroot *self,
glnx_unref_object OstreeRepo *repo = NULL;
g_autoptr(GFile) osdeploydir = NULL;
g_autoptr(GFile) deployment_var = NULL;
g_autoptr(GFile) tree_kernel_path = NULL;
g_autoptr(GFile) tree_initramfs_path = NULL;
glnx_fd_close int tree_boot_dfd = -1;
g_autofree char *tree_kernel_path = NULL;
g_autofree char *tree_initramfs_path = NULL;
glnx_fd_close int deployment_dfd = -1;
glnx_unref_object OstreeSePolicy *sepolicy = NULL;
g_autofree char *new_bootcsum = NULL;
@ -1979,9 +1990,8 @@ ostree_sysroot_deploy_tree (OstreeSysroot *self,
goto out;
}
deployment_dir = ostree_sysroot_get_deployment_directory (self, new_deployment);
if (!get_kernel_from_tree (deployment_dir, &tree_kernel_path, &tree_initramfs_path,
if (!get_kernel_from_tree (deployment_dfd, &tree_boot_dfd,
&tree_kernel_path, &tree_initramfs_path,
cancellable, error))
goto out;