From: Radoslaw Smigielski <rsmigiel@redhat.com>
LXC domains using a file-backed filesystem with the loop driver fail to
start when the backing image path is longer than LO_NAME_SIZE (64 bytes,
63 characters plus NUL). virFileLoopDeviceAssociate() treated a failed
virStrcpy() into loop_info64.lo_file_name as fatal and reported a
misleading virReportSystemError(errno, ...), so users saw errors such as
"Unable to set backing file ...: Success" or ENOENT even when the file
existed.
The kernel only stores a short name in lo_file_name for LOOP_SET_STATUS64
metadata. The backing file is opened by full path. Copy the path with
virStrcpy(), allow truncation into lo_file_name, and mark truncation with '*'
at LO_NAME_SIZE - 2 to match losetup behavior.
Log truncation at debug level only.
XML example that failed before this change:
<filesystem type='file' accessmode='passthrough'>
<driver type='loop' format='raw'/>
<source file='/root/demoaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.raw'/>
<target dir='/'/>
</filesystem>
Fixes: https://gitlab.com/libvirt/libvirt/-/work_items/63
Signed-off-by: Radoslaw Smigielski <rsmigiel@redhat.com>
---
src/util/virfile.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/src/util/virfile.c b/src/util/virfile.c
index a0c6cb804862..443d0ed9adab 100644
--- a/src/util/virfile.c
+++ b/src/util/virfile.c
@@ -995,11 +995,15 @@ int virFileLoopDeviceAssociate(const char *file,
lo.lo_flags = LO_FLAGS_AUTOCLEAR;
- /* Set backing file name for LOOP_GET_STATUS64 queries */
+ /* lo_file_name is loop device name, max length is LO_NAME_SIZE bytes.
+ * Truncate loop device name if file path is longer than LO_NAME_SIZE,
+ * and still use the full path to open backing file. */
if (virStrcpy((char *) lo.lo_file_name, file, LO_NAME_SIZE) < 0) {
- virReportSystemError(errno,
- _("Unable to set backing file %1$s"), file);
- goto cleanup;
+ /* virStrcpy() only returns -1 on truncation. Mark truncation with
+ * asterisk at position LO_NAME_SIZE-2 to match losetup behavior. */
+ lo.lo_file_name[LO_NAME_SIZE - 2] = '*';
+ VIR_DEBUG("lo_file_name for '%s' truncated to %d bytes in loop metadata",
+ file, LO_NAME_SIZE);
}
if ((fsfd = open(file, O_RDWR)) < 0) {
--
2.54.0