lib/commit: Use direct fd xattr operations again on regular files

A side effect of commit 8fe4536257 is that
we started listing all xattrs even for files with device/inode matches;
further, we did that using the dfd/name which means we went through
the `/proc` path, which is slower and uglier.

Noticed this in strace while looking at adoption code.

Closes: #1280
Approved by: jlebon
This commit is contained in:
Colin Walters 2017-10-16 16:08:26 -04:00 committed by Atomic Bot
parent eeabd4baf7
commit 3577b4a6c6
1 changed files with 40 additions and 13 deletions

View File

@ -2794,16 +2794,42 @@ write_directory_content_to_mtree_internal (OstreeRepo *self,
} }
else else
{ {
guint64 file_obj_length; glnx_autofd int file_input_fd = -1;
g_autoptr(GInputStream) file_input = NULL;
g_autoptr(GInputStream) file_object_input = NULL; /* Open the file now, since it's better for reading xattrs
* rather than using the /proc/self/fd links.
*
* TODO: Do this lazily, since for e.g. bare-user-only repos
* we don't have xattrs and don't need to open every file
* for things that have devino cache hits.
*/
if (file_type == G_FILE_TYPE_REGULAR && dfd_iter != NULL)
{
if (!glnx_openat_rdonly (dfd_iter->fd, name, FALSE, &file_input_fd, error))
return FALSE;
}
g_autoptr(GVariant) xattrs = NULL; g_autoptr(GVariant) xattrs = NULL;
gboolean xattrs_were_modified; gboolean xattrs_were_modified;
if (!get_final_xattrs (self, modifier, child_relpath, child_info, child, if (dir_enum != NULL)
dir_enum != NULL ? -1 : dfd_iter->fd, name, &xattrs, {
&xattrs_were_modified, cancellable, error)) if (!get_final_xattrs (self, modifier, child_relpath, child_info, child,
return FALSE; -1, name, &xattrs, &xattrs_were_modified,
cancellable, error))
return FALSE;
}
else
{
/* These contortions are basically so we use glnx_fd_get_all_xattrs()
* for regfiles, and glnx_dfd_name_get_all_xattrs() for symlinks.
*/
int xattr_fd_arg = (file_input_fd != -1) ? file_input_fd : dfd_iter->fd;
const char *xattr_path_arg = (file_input_fd != -1) ? NULL : name;
if (!get_final_xattrs (self, modifier, child_relpath, child_info, child,
xattr_fd_arg, xattr_path_arg, &xattrs, &xattrs_were_modified,
cancellable, error))
return FALSE;
}
/* only check the devino cache if the file info & xattrs were not modified */ /* only check the devino cache if the file info & xattrs were not modified */
const gboolean modified_file_meta = child_info_was_modified || xattrs_were_modified; const gboolean modified_file_meta = child_info_was_modified || xattrs_were_modified;
@ -2862,8 +2888,9 @@ write_directory_content_to_mtree_internal (OstreeRepo *self,
} }
else else
{ {
/* Generic path - convert to object stream, commit that */ g_autoptr(GInputStream) file_input = NULL;
if (g_file_info_get_file_type (modified_info) == G_FILE_TYPE_REGULAR)
if (file_type == G_FILE_TYPE_REGULAR)
{ {
if (dir_enum != NULL) if (dir_enum != NULL)
{ {
@ -2874,13 +2901,13 @@ write_directory_content_to_mtree_internal (OstreeRepo *self,
} }
else else
{ {
g_assert (dfd_iter != NULL); /* We already opened the fd above */
if (!ot_openat_read_stream (dfd_iter->fd, name, FALSE, file_input = g_unix_input_stream_new (file_input_fd, FALSE);
&file_input, cancellable, error))
return FALSE;
} }
} }
g_autoptr(GInputStream) file_object_input = NULL;
guint64 file_obj_length;
if (!ostree_raw_file_to_content_stream (file_input, if (!ostree_raw_file_to_content_stream (file_input,
modified_info, xattrs, modified_info, xattrs,
&file_object_input, &file_obj_length, &file_object_input, &file_obj_length,