From 22c7655573f33389108cd9a49ce0395a3cbecf31 Mon Sep 17 00:00:00 2001 From: Beq Date: Wed, 7 Nov 2018 23:51:06 +0000 Subject: [PATCH] FIRE-21669 & FIRE-11276: Fix for cross volume rename failures on Linux/Mac --- indra/llcommon/llfile.cpp | 33 ++++++++++++++++ indra/llmessage/llxfer_file.cpp | 68 +++++++++++++++++---------------- 2 files changed, 69 insertions(+), 32 deletions(-) diff --git a/indra/llcommon/llfile.cpp b/indra/llcommon/llfile.cpp index b539a69ad6..ce0d87ae05 100644 --- a/indra/llcommon/llfile.cpp +++ b/indra/llcommon/llfile.cpp @@ -268,6 +268,39 @@ int LLFile::rename(const std::string& filename, const std::string& newname, int int rc = _wrename(utf16filename.c_str(),utf16newname.c_str()); #else int rc = ::rename(filename.c_str(),newname.c_str()); + // FIRE-21669 & FIRE-11276 cross volume link rename workaround. + // Note: This workaround generalises the solution previously applied in llxfer_file. + // In doing this we add more failure modes to the operation, the copy can fail, the unlink can fail, in fact the copy can fail for multiple reasons. + // "A common mistake that people make when trying to design something completely foolproof is to underestimate the ingenuity of complete fools." - Douglas Adams, Mostly harmless + if (rc) + { + S32 error_number = errno; + LL_INFOS("LLFile") << "Rename failure (" << error_number << ") - " << filename << " to " << newname << LL_ENDL; + if (EXDEV == error_number) + { + if (copy(filename, newname) == 0) + { + LL_INFOS("LLFile") << "Rename across mounts not supported; copying+unlinking the file instead." << LL_ENDL; + rc = LLFile::remove(filename); + if (rc) + { + LL_WARNS("LLFile") << "unlink failed during copy/unlink workaround. Please check for stray file: " << filename << LL_ENDL; + } + } + else + { + LL_WARNS("LLFile") << "Copy failure during rename workaround for rename " << filename << " to " << newname << " (check both filenames and maunally rectify)" << LL_ENDL; + } + rc=0; // We need to reset rc here to avoid the higher level function taking corrective action on what could be bad files. + } + else + { + LL_WARNS("LLFile") << "Rename fatally failed, no workaround attempted for errno=" + << errno << "." << LL_ENDL; + // rc will propogate alllowing corrective action above. Not entirely happy with this but it is what already happens so we're not making it worse. + } + } + // #endif return warnif(STRINGIZE("rename to '" << newname << "' from"), filename, rc, supress_error); } diff --git a/indra/llmessage/llxfer_file.cpp b/indra/llmessage/llxfer_file.cpp index 7fd4222fb7..2483be99c3 100644 --- a/indra/llmessage/llxfer_file.cpp +++ b/indra/llmessage/llxfer_file.cpp @@ -362,40 +362,44 @@ S32 LLXfer_File::processEOF() { if (LLFile::rename(mTempFilename,mLocalFilename)) { -#if !LL_WINDOWS - S32 error_number = errno; - LL_INFOS("Xfer") << "Rename failure (" << error_number << ") - " - << mTempFilename << " to " << mLocalFilename << LL_ENDL; - if(EXDEV == error_number) - { - if(copy_file(mTempFilename, mLocalFilename) == 0) - { - LL_INFOS("Xfer") << "Rename across mounts; copying+unlinking the file instead." << LL_ENDL; - unlink(mTempFilename.c_str()); - } - else - { - LL_WARNS("Xfer") << "Copy failure - " << mTempFilename << " to " - << mLocalFilename << LL_ENDL; - } - } - else - { - //LLFILE* fp = LLFile::fopen(mTempFilename, "r"); - //LL_WARNS() << "File " << mTempFilename << " does " - // << (!fp ? "not" : "" ) << " exit." << LL_ENDL; - //if(fp) fclose(fp); - //fp = LLFile::fopen(mLocalFilename, "r"); - //LL_WARNS() << "File " << mLocalFilename << " does " - // << (!fp ? "not" : "" ) << " exit." << LL_ENDL; - //if(fp) fclose(fp); - LL_WARNS("Xfer") << "Rename fatally failed, can only handle EXDEV (" - << EXDEV << ")" << LL_ENDL; - } -#else +// FIRE-21669/FIRE-11276 : move similar fucntionality down into LLFile +//#if !LL_WINDOWS +// S32 error_number = errno; +// LL_INFOS("Xfer") << "Rename failure (" << error_number << ") - " +// << mTempFilename << " to " << mLocalFilename << LL_ENDL; +// if(EXDEV == error_number) +// { +// if(copy_file(mTempFilename, mLocalFilename) == 0) +// { +// LL_INFOS("Xfer") << "Rename across mounts; copying+unlinking the file instead." << LL_ENDL; +// unlink(mTempFilename.c_str()); +// } +// else +// { +// LL_WARNS("Xfer") << "Copy failure - " << mTempFilename << " to " +// << mLocalFilename << LL_ENDL; +// } +// } +// else +// { +// //LLFILE* fp = LLFile::fopen(mTempFilename, "r"); +// //LL_WARNS() << "File " << mTempFilename << " does " +// // << (!fp ? "not" : "" ) << " exit." << LL_ENDL; +// //if(fp) fclose(fp); +// //fp = LLFile::fopen(mLocalFilename, "r"); +// //LL_WARNS() << "File " << mLocalFilename << " does " +// // << (!fp ? "not" : "" ) << " exit." << LL_ENDL; +// //if(fp) fclose(fp); +// LL_WARNS("Xfer") << "Rename fatally failed, can only handle EXDEV (" +// << EXDEV << ")" << LL_ENDL; +// } +//#else +// LL_WARNS("Xfer") << "Rename failure - " << mTempFilename << " to " +// << mLocalFilename << LL_ENDL; +//#endif +// LL_WARNS("Xfer") << "Rename failure - " << mTempFilename << " to " << mLocalFilename << LL_ENDL; -#endif } }