summaryrefslogtreecommitdiff
path: root/src/cstore
diff options
context:
space:
mode:
authorRageLtMan <rageltman [at] sempervictus>2022-08-13 11:34:08 -0400
committerRageLtMan <rageltman [at] sempervictus>2022-08-13 19:35:09 -0400
commit28cf6fee14d3bc5f6eda2099c7eb36e43297a8a8 (patch)
treec02cb3a288f67987cb200f95856258eebc7b313d /src/cstore
parentc8dad45c8afa4fd4a784ae6cdffb84a2e804084e (diff)
downloadvyatta-cfg-28cf6fee14d3bc5f6eda2099c7eb36e43297a8a8.tar.gz
vyatta-cfg-28cf6fee14d3bc5f6eda2099c7eb36e43297a8a8.zip
Fallthrough to binstream copy when copy_file fails
Kernel 5.15, and probably newer, present an EXEDEV error when the vyatta-cfg code tries to boost::filesystem::copy_file on UnionFS FUSE mounts. This completely breaks operation on newer kernels, and is therefore a blocker to the rest of the project moving on to new Linux LTS versions. Boost is complex and fraught, this code behaves inconsistently in verious operating environments, and can be a nightmare to debug. Handle the concerns above using binary streaming in C++ to copy the source to the destination if an exception occurs during the existing Boost copy_file operation. Testing: Built ISO (cloud target), packer install, booted in OpenStack on KVM, booted in AWS on Xen, verified configurations are committed in both cases and that error logs are being generated to inform users about the fall-through being utilized to write-out configurations. Notes: Logging may be dropped to avoid flooding storage on often-updated systems. It is left in-place to aid developers in debugging the root concern underpinning Boot breakage (which may impact other areas of the code).
Diffstat (limited to 'src/cstore')
-rw-r--r--src/cstore/unionfs/cstore-unionfs.cpp23
1 files changed, 20 insertions, 3 deletions
diff --git a/src/cstore/unionfs/cstore-unionfs.cpp b/src/cstore/unionfs/cstore-unionfs.cpp
index e713dbd..e9aa7b2 100644
--- a/src/cstore/unionfs/cstore-unionfs.cpp
+++ b/src/cstore/unionfs/cstore-unionfs.cpp
@@ -167,6 +167,14 @@ _unescape_path_name(const string& path)
return npath;
}
+// Fall-through for Boost's filesystem::copy_file "complexity"
+void stream_file( const char* srce_file, const char* dest_file )
+{
+ std::ifstream srce( srce_file, std::ios::binary ) ;
+ std::ofstream dest( dest_file, std::ios::binary ) ;
+ dest << srce.rdbuf() ;
+}
+
vector<int> getActiveCommits()
{
string process_name = "vbash";
@@ -322,7 +330,6 @@ UnionfsCstore::~UnionfsCstore()
{
}
-
////// public virtual functions declared in base class
bool
UnionfsCstore::markSessionUnsaved()
@@ -750,7 +757,12 @@ UnionfsCstore::sync_dir(const FsPath& src, const FsPath& dst,
try {
if (path_is_regular(s)) {
// it's file
- b_fs::copy_file(s.path_cstr(), d.path_cstr());
+ try {
+ b_fs::copy_file(s.path_cstr(), d.path_cstr());
+ } catch (const boost::filesystem::filesystem_error& e) {
+ output_internal("syncdir failed due to %s in copy_file. Falling back to internal stream_file\n", e.what());
+ stream_file(s.path_cstr(), d.path_cstr());
+ }
} else {
// dir
recursive_copy_dir(s, d, true);
@@ -1592,7 +1604,12 @@ UnionfsCstore::recursive_copy_dir(const FsPath& src, const FsPath& dst,
}
}
}
- b_fs::copy_file(di->path(), nname);
+ try {
+ b_fs::copy_file(di->path(), nname);
+ } catch (const b_fs::filesystem_error& e) {
+ output_internal("recursive_copy_dir failed due to %s in copy_file. Falling back to internal stream_file\n", e.what());
+ stream_file(di->path().string().c_str(), nname.c_str());
+ }
}
}
}