Skip to content
Snippets Groups Projects
Commit c35d84f6 authored by Simon McVittie's avatar Simon McVittie
Browse files

pv-tree-copy: Factor out link_or_copy_regular_file()

parent 5e8ce65e
No related branches found
No related tags found
1 merge request!582pv-runtime: Tolerate inability to chmod files if the permissions look OK
...@@ -72,6 +72,56 @@ static struct ...@@ -72,6 +72,56 @@ static struct
GError *error; GError *error;
} nftw_data; } nftw_data;
static gboolean
link_or_copy_regular_file (const char *fpath,
const struct stat *sb,
const char *dest,
GError **error)
{
int link_errno = 0;
/* Fast path: try to make a hard link. */
if (link (fpath, dest) == 0)
return TRUE;
link_errno = errno;
/* Slow path: fall back to copying.
*
* This does a FICLONE or copy_file_range to get btrfs reflinks
* if possible, making the copy as cheap as cp --reflink=auto.
*
* Rather than second-guessing which errno values would result
* in link() failing but a copy succeeding, we just try it
* unconditionally - the worst that can happen is that this
* fails too. */
if (!glnx_file_copy_at (AT_FDCWD, fpath, sb,
AT_FDCWD, dest,
(GLNX_FILE_COPY_OVERWRITE
| GLNX_FILE_COPY_NOCHOWN
| GLNX_FILE_COPY_NOXATTRS),
NULL, error))
return glnx_prefix_error (error, "Unable to copy \"%s\" to \"%s\"",
fpath, dest);
/* If link() failed but copying succeeded, then we might have
* a problem that we need to warn about. */
if ((nftw_data.flags & PV_COPY_FLAGS_EXPECT_HARD_LINKS) != 0)
{
g_warning ("Unable to create hard link \"%s\" to \"%s\": %s",
fpath, dest, g_strerror (link_errno));
g_warning ("Falling back to copying, but this will take more "
"time and disk space.");
g_warning ("For best results, \"%s\" and \"%s\" should both "
"be on the same fully-featured Linux filesystem.",
nftw_data.source_root, nftw_data.dest_root);
/* Only warn once per tree copied */
nftw_data.flags &= ~PV_COPY_FLAGS_EXPECT_HARD_LINKS;
}
return TRUE;
}
static int static int
copy_tree_helper (const char *fpath, copy_tree_helper (const char *fpath,
const struct stat *sb, const struct stat *sb,
...@@ -84,7 +134,6 @@ copy_tree_helper (const char *fpath, ...@@ -84,7 +134,6 @@ copy_tree_helper (const char *fpath,
g_autofree gchar *target = NULL; g_autofree gchar *target = NULL;
GError **error = &nftw_data.error; GError **error = &nftw_data.error;
gboolean usrmerge; gboolean usrmerge;
int link_errno = 0;
g_return_val_if_fail (g_str_has_prefix (fpath, nftw_data.source_root), 1); g_return_val_if_fail (g_str_has_prefix (fpath, nftw_data.source_root), 1);
...@@ -261,47 +310,9 @@ copy_tree_helper (const char *fpath, ...@@ -261,47 +310,9 @@ copy_tree_helper (const char *fpath,
case FTW_F: case FTW_F:
trace ("Is a regular file"); trace ("Is a regular file");
/* Fast path: try to make a hard link. */ if (!link_or_copy_regular_file (fpath, sb, dest, error))
if (link (fpath, dest) == 0) return 1;
break;
link_errno = errno;
/* Slow path: fall back to copying.
*
* This does a FICLONE or copy_file_range to get btrfs reflinks
* if possible, making the copy as cheap as cp --reflink=auto.
*
* Rather than second-guessing which errno values would result
* in link() failing but a copy succeeding, we just try it
* unconditionally - the worst that can happen is that this
* fails too. */
if (!glnx_file_copy_at (AT_FDCWD, fpath, sb,
AT_FDCWD, dest,
(GLNX_FILE_COPY_OVERWRITE
| GLNX_FILE_COPY_NOCHOWN
| GLNX_FILE_COPY_NOXATTRS),
NULL, error))
{
glnx_prefix_error (error, "Unable to copy \"%s\" to \"%s\"",
fpath, dest);
return 1;
}
/* If link() failed but copying succeeded, then we might have
* a problem that we need to warn about. */
if ((nftw_data.flags & PV_COPY_FLAGS_EXPECT_HARD_LINKS) != 0)
{
g_warning ("Unable to create hard link \"%s\" to \"%s\": %s",
fpath, dest, g_strerror (link_errno));
g_warning ("Falling back to copying, but this will take more "
"time and disk space.");
g_warning ("For best results, \"%s\" and \"%s\" should both "
"be on the same fully-featured Linux filesystem.",
nftw_data.source_root, nftw_data.dest_root);
/* Only warn once per tree copied */
nftw_data.flags &= ~PV_COPY_FLAGS_EXPECT_HARD_LINKS;
}
break; break;
default: default:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment