Skip to content

Commit

Permalink
gfile: Eliminate a stat() call from the file copy code
Browse files Browse the repository at this point in the history
The start of the `g_file_copy()` implementation stats the source file to
find all the attributes to copy onto the destination file, so it makes
sense to get it to store the source file size at the same time.

This saves a subsequent `stat()` call on the source FD in the btrfs
reflink or splice code. Every little helps.

Signed-off-by: Philip Withnall <[email protected]>
  • Loading branch information
pwithnall committed May 9, 2023
1 parent 63e1e83 commit 0da948a
Showing 1 changed file with 13 additions and 10 deletions.
23 changes: 13 additions & 10 deletions gio/gfile.c
Original file line number Diff line number Diff line change
Expand Up @@ -2807,6 +2807,11 @@ g_file_build_attribute_list_for_copy (GFile *file,
first = TRUE;
s = g_string_new ("");

/* Always query the source file size, even though we can’t set that on the
* destination. This is useful for the copy functions. */
first = FALSE;
g_string_append (s, G_FILE_ATTRIBUTE_STANDARD_SIZE);

if (attributes)
{
for (i = 0; i < attributes->n_infos; i++)
Expand Down Expand Up @@ -3042,6 +3047,7 @@ do_splice (int fd_in,

static gboolean
splice_stream_with_progress (GInputStream *in,
GFileInfo *in_info,
GOutputStream *out,
GCancellable *cancellable,
GFileProgressCallback progress_callback,
Expand Down Expand Up @@ -3085,10 +3091,8 @@ splice_stream_with_progress (GInputStream *in,
/* avoid performance impact of querying total size when it's not needed */
if (progress_callback)
{
struct stat sbuf;

if (fstat (fd_in, &sbuf) == 0)
total_size = sbuf.st_size;
g_assert (g_file_info_has_attribute (in_info, G_FILE_ATTRIBUTE_STANDARD_SIZE));
total_size = g_file_info_get_size (in_info);
}

if (total_size == -1)
Expand Down Expand Up @@ -3151,6 +3155,7 @@ splice_stream_with_progress (GInputStream *in,
#ifdef __linux__
static gboolean
btrfs_reflink_with_progress (GInputStream *in,
GFileInfo *in_info,
GOutputStream *out,
GFileInfo *info,
GCancellable *cancellable,
Expand All @@ -3169,10 +3174,8 @@ btrfs_reflink_with_progress (GInputStream *in,
/* avoid performance impact of querying total size when it's not needed */
if (progress_callback)
{
struct stat sbuf;

if (fstat (fd_in, &sbuf) == 0)
total_size = sbuf.st_size;
g_assert (g_file_info_has_attribute (in_info, G_FILE_ATTRIBUTE_STANDARD_SIZE));
total_size = g_file_info_get_size (in_info);
}

if (total_size == -1)
Expand Down Expand Up @@ -3376,7 +3379,7 @@ file_copy_fallback (GFile *source,
{
GError *reflink_err = NULL;

if (!btrfs_reflink_with_progress (in, out, info, cancellable,
if (!btrfs_reflink_with_progress (in, info, out, info, cancellable,
progress_callback, progress_callback_data,
&reflink_err))
{
Expand All @@ -3403,7 +3406,7 @@ file_copy_fallback (GFile *source,
{
GError *splice_err = NULL;

if (!splice_stream_with_progress (in, out, cancellable,
if (!splice_stream_with_progress (in, info, out, cancellable,
progress_callback, progress_callback_data,
&splice_err))
{
Expand Down

0 comments on commit 0da948a

Please sign in to comment.