|
|
2f13d7 |
From fd8ffffced543e248847d63e9375fb95584f998d Mon Sep 17 00:00:00 2001
|
|
|
2f13d7 |
From: chantra <chantr4@gmail.com>
|
|
|
2f13d7 |
Date: Fri, 11 Feb 2022 18:09:47 -0800
|
|
|
2f13d7 |
Subject: [PATCH 22/30] [reflink] fix support for hardlinks
|
|
|
2f13d7 |
|
|
|
2f13d7 |
a `suffix` made of ";${tid}" is now used until the changes are commited. As such, when
|
|
|
2f13d7 |
linking the file, we should link to the suffixed file.
|
|
|
2f13d7 |
|
|
|
2f13d7 |
The `suffix` is currently internal only to rpmPackageFilesInstall and there is
|
|
|
2f13d7 |
no obvious way to use data from struct `filedata_s` without exposing it to
|
|
|
2f13d7 |
a bunch of other places such as rpmplugin*.
|
|
|
2f13d7 |
We already keep track of the first file index. We used to use this to fetch the
|
|
|
2f13d7 |
file name, but due to suffix, the file is not named correctly, e.g it
|
|
|
2f13d7 |
has the name we will want at the end, once the transaction is commited,
|
|
|
2f13d7 |
not the temporary name.
|
|
|
2f13d7 |
Instead of re-implementing a local suffix that may change over time as
|
|
|
2f13d7 |
the implementation evolves, we can store the name of the file we should link to
|
|
|
2f13d7 |
in the hash instead of the index, which we were then using to fetch the
|
|
|
2f13d7 |
file name.
|
|
|
2f13d7 |
When hardlinking, we can then retrieve the name of the target file
|
|
|
2f13d7 |
instead of the index, like we previously did, and hardlink to that
|
|
|
2f13d7 |
without any issues.
|
|
|
2f13d7 |
Add a test to validate that reflink can handle hardlinking.
|
|
|
2f13d7 |
|
|
|
2f13d7 |
Originally, the test added would fail with:
|
|
|
2f13d7 |
|
|
|
2f13d7 |
```
|
|
|
2f13d7 |
error: reflink: Unable to hard link /foo/hello -> /foo/hello-bar;6207219c due to No such file or directory
|
|
|
2f13d7 |
error: Plugin reflink: hook fsm_file_install failed
|
|
|
2f13d7 |
error: unpacking of archive failed on file /foo/hello-bar;6207219c:
|
|
|
2f13d7 |
cpio: (error 0x2)
|
|
|
2f13d7 |
error: hlinktest-1.0-1.noarch: install failed
|
|
|
2f13d7 |
./rpm2extents.at:114: exit code was 1, expected 0
|
|
|
2f13d7 |
499. rpm2extents.at:112: 499. reflink hardlink package
|
|
|
2f13d7 |
(rpm2extents.at:112): FAILED (rpm2extents.at:114)
|
|
|
2f13d7 |
```
|
|
|
2f13d7 |
|
|
|
2f13d7 |
After this change, the test passes.
|
|
|
2f13d7 |
---
|
|
|
2f13d7 |
plugins/reflink.c | 19 ++++++++-----------
|
|
|
2f13d7 |
tests/rpm2extents.at | 15 +++++++++++++++
|
|
|
2f13d7 |
2 files changed, 23 insertions(+), 11 deletions(-)
|
|
|
2f13d7 |
|
|
|
2f13d7 |
diff --git a/plugins/reflink.c b/plugins/reflink.c
|
|
|
2f13d7 |
index d5e6db27a..4fc1d74d1 100644
|
|
|
2f13d7 |
--- a/plugins/reflink.c
|
|
|
2f13d7 |
+++ b/plugins/reflink.c
|
|
|
2f13d7 |
@@ -29,7 +29,7 @@
|
|
|
2f13d7 |
#undef HTDATATYPE
|
|
|
2f13d7 |
#define HASHTYPE inodeIndexHash
|
|
|
2f13d7 |
#define HTKEYTYPE rpm_ino_t
|
|
|
2f13d7 |
-#define HTDATATYPE int
|
|
|
2f13d7 |
+#define HTDATATYPE const char *
|
|
|
2f13d7 |
#include "lib/rpmhash.H"
|
|
|
2f13d7 |
#include "lib/rpmhash.C"
|
|
|
2f13d7 |
|
|
|
2f13d7 |
@@ -163,7 +163,7 @@ static rpmRC reflink_psm_pre(rpmPlugin plugin, rpmte te) {
|
|
|
2f13d7 |
return RPMRC_FAIL;
|
|
|
2f13d7 |
}
|
|
|
2f13d7 |
state->inodeIndexes = inodeIndexHashCreate(
|
|
|
2f13d7 |
- state->keys, inodeId, inodeCmp, NULL, NULL
|
|
|
2f13d7 |
+ state->keys, inodeId, inodeCmp, NULL, (inodeIndexHashFreeData)rfree
|
|
|
2f13d7 |
);
|
|
|
2f13d7 |
}
|
|
|
2f13d7 |
|
|
|
2f13d7 |
@@ -226,7 +226,7 @@ static rpmRC reflink_fsm_file_install(rpmPlugin plugin, rpmfi fi, const char* pa
|
|
|
2f13d7 |
struct file_clone_range fcr;
|
|
|
2f13d7 |
rpm_loff_t size;
|
|
|
2f13d7 |
int dst, rc;
|
|
|
2f13d7 |
- int *hlix;
|
|
|
2f13d7 |
+ const char **hl_target = NULL;
|
|
|
2f13d7 |
|
|
|
2f13d7 |
reflink_state state = rpmPluginGetData(plugin);
|
|
|
2f13d7 |
if (state->table == NULL) {
|
|
|
2f13d7 |
@@ -243,18 +243,15 @@ static rpmRC reflink_fsm_file_install(rpmPlugin plugin, rpmfi fi, const char* pa
|
|
|
2f13d7 |
/* check for hard link entry in table. GetEntry overwrites hlix with
|
|
|
2f13d7 |
* the address of the first match.
|
|
|
2f13d7 |
*/
|
|
|
2f13d7 |
- if (inodeIndexHashGetEntry(state->inodeIndexes, inode, &hlix, NULL,
|
|
|
2f13d7 |
- NULL)) {
|
|
|
2f13d7 |
+ if (inodeIndexHashGetEntry(state->inodeIndexes, inode, &hl_target,
|
|
|
2f13d7 |
+ NULL, NULL)) {
|
|
|
2f13d7 |
/* entry is in table, use hard link */
|
|
|
2f13d7 |
- char *fn = rpmfilesFN(state->files, hlix[0]);
|
|
|
2f13d7 |
- if (link(fn, path) != 0) {
|
|
|
2f13d7 |
+ if (link(hl_target[0], path) != 0) {
|
|
|
2f13d7 |
rpmlog(RPMLOG_ERR,
|
|
|
2f13d7 |
_("reflink: Unable to hard link %s -> %s due to %s\n"),
|
|
|
2f13d7 |
- fn, path, strerror(errno));
|
|
|
2f13d7 |
- free(fn);
|
|
|
2f13d7 |
+ hl_target[0], path, strerror(errno));
|
|
|
2f13d7 |
return RPMRC_FAIL;
|
|
|
2f13d7 |
}
|
|
|
2f13d7 |
- free(fn);
|
|
|
2f13d7 |
return RPMRC_PLUGIN_CONTENTS;
|
|
|
2f13d7 |
}
|
|
|
2f13d7 |
/* if we didn't hard link, then we'll track this inode as being
|
|
|
2f13d7 |
@@ -262,7 +259,7 @@ static rpmRC reflink_fsm_file_install(rpmPlugin plugin, rpmfi fi, const char* pa
|
|
|
2f13d7 |
*/
|
|
|
2f13d7 |
if (rpmfiFNlink(fi) > 1) {
|
|
|
2f13d7 |
/* minor optimization: only store files with more than one link */
|
|
|
2f13d7 |
- inodeIndexHashAddEntry(state->inodeIndexes, inode, rpmfiFX(fi));
|
|
|
2f13d7 |
+ inodeIndexHashAddEntry(state->inodeIndexes, inode, rstrdup(path));
|
|
|
2f13d7 |
}
|
|
|
2f13d7 |
/* derived from wfd_open in fsm.c */
|
|
|
2f13d7 |
mode_t old_umask = umask(0577);
|
|
|
2f13d7 |
diff --git a/tests/rpm2extents.at b/tests/rpm2extents.at
|
|
|
2f13d7 |
index fa124ac03..5c66de7f6 100644
|
|
|
2f13d7 |
--- a/tests/rpm2extents.at
|
|
|
2f13d7 |
+++ b/tests/rpm2extents.at
|
|
|
2f13d7 |
@@ -123,3 +123,18 @@ test -f ${RPMTEST}/usr/bin/hello
|
|
|
2f13d7 |
[],
|
|
|
2f13d7 |
[])
|
|
|
2f13d7 |
AT_CLEANUP
|
|
|
2f13d7 |
+
|
|
|
2f13d7 |
+AT_SETUP([reflink hardlink package])
|
|
|
2f13d7 |
+AT_KEYWORDS([reflink hardlink])
|
|
|
2f13d7 |
+AT_SKIP_IF([$REFLINK_DISABLED])
|
|
|
2f13d7 |
+AT_CHECK([
|
|
|
2f13d7 |
+RPMDB_INIT
|
|
|
2f13d7 |
+
|
|
|
2f13d7 |
+PKG=hlinktest-1.0-1.noarch.rpm
|
|
|
2f13d7 |
+runroot_other cat /data/RPMS/${PKG} | runroot_other rpm2extents SHA256 > ${RPMTEST}/tmp/${PKG} 2> /dev/null
|
|
|
2f13d7 |
+runroot_plugins rpm -i --nodigest --nodeps --undefine=%__transaction_dbus_announce /tmp/${PKG}
|
|
|
2f13d7 |
+],
|
|
|
2f13d7 |
+[0],
|
|
|
2f13d7 |
+[],
|
|
|
2f13d7 |
+[])
|
|
|
2f13d7 |
+AT_CLEANUP
|
|
|
2f13d7 |
--
|
|
|
2f13d7 |
2.35.1
|
|
|
2f13d7 |
|