From edd01372bc4a4afb26273466843a7c63d95a92d1 Mon Sep 17 00:00:00 2001 From: Derek Weitzel Date: Fri, 13 Feb 2026 11:21:39 -0600 Subject: [PATCH 1/3] Handle non-sequential writes by disabling checksum calculation and updating offset correctly --- src/multiuser.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/multiuser.cpp b/src/multiuser.cpp index 522cff3..9fe0add 100644 --- a/src/multiuser.cpp +++ b/src/multiuser.cpp @@ -177,13 +177,14 @@ ssize_t MultiuserFile::Write(const void *buffer, off_t offset, size_t size) if ((offset != m_nextoff) && m_state) { std::stringstream ss; - ss << "Out-of-order writes not supported while running checksum. " << m_fname; + ss << "Non-sequential write detected; disabling checksum calculation for " << m_fname; m_log.Emsg("Write", ss.str().c_str()); - return -ENOTSUP; + delete m_state; + m_state = NULL; } auto result = m_wrapped->Write(buffer, offset, size); - if (result >= 0) {m_nextoff += result;} + if (result >= 0) {m_nextoff = offset + result;} if (m_state) { m_state->Update(static_cast(buffer), size); From 4c54712ceff6786d488db25a320a5cd6612cb7be Mon Sep 17 00:00:00 2001 From: Derek Weitzel Date: Fri, 15 May 2026 20:06:45 -0500 Subject: [PATCH 2/3] Update src/multiuser.cpp Co-authored-by: jthiltges --- src/multiuser.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/multiuser.cpp b/src/multiuser.cpp index 9fe0add..d8f11a7 100644 --- a/src/multiuser.cpp +++ b/src/multiuser.cpp @@ -184,9 +184,9 @@ ssize_t MultiuserFile::Write(const void *buffer, off_t offset, size_t size) } auto result = m_wrapped->Write(buffer, offset, size); - if (result >= 0) {m_nextoff = offset + result;} - if (m_state) + if (m_state && result >= 0) { + m_nextoff += result; m_state->Update(static_cast(buffer), size); } return result; From f78bdd07ee4892029b9ce8cf00b76c9ca04cccc9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 19 May 2026 02:27:40 +0000 Subject: [PATCH 3/3] Fix checksum invalidation and short-write accounting Agent-Logs-Url: https://github.com/opensciencegrid/xrootd-multiuser/sessions/8b48c00b-4671-4e36-809e-ce4ba10d7afd Co-authored-by: djw8605 <79268+djw8605@users.noreply.github.com> --- src/XrdChecksum.cc | 19 ++++++++++++++++++- src/XrdChecksum.hh | 3 ++- src/multiuser.cpp | 18 +++++++++++++++--- 3 files changed, 35 insertions(+), 5 deletions(-) diff --git a/src/XrdChecksum.cc b/src/XrdChecksum.cc index 6691393..94481cb 100644 --- a/src/XrdChecksum.cc +++ b/src/XrdChecksum.cc @@ -195,6 +195,24 @@ int ChecksumManager::Set(const char *lfn, const char *cksname, const char *chksv return XrdCksManager::Set(pfn.c_str(), cks); } +int ChecksumManager::Del(const char *lfn, unsigned digests) +{ + std::string pfn = this->LFN2PFN(lfn); + auto del_digest = [&](const char *digest_name) { + std::string checksum_name = ATTR_PREFIX; + checksum_name += digest_name; + XrdSysXAttrActive->Del(checksum_name.c_str(), pfn.c_str()); + }; + + if (digests & ChecksumManager::CKSUM) del_digest("CKSUM"); + if (digests & ChecksumManager::ADLER32) del_digest("ADLER32"); + if (digests & ChecksumManager::CRC32) del_digest("CRC32"); + if (digests & ChecksumManager::MD5) del_digest("MD5"); + if (digests & ChecksumManager::CVMFS) del_digest("CVMFS"); + + return 0; +} + int ChecksumManager::Ver( const char *lfn, XrdCksData &Cks) { return XrdCksManager::Ver(lfn, Cks); @@ -243,4 +261,3 @@ std::string ChecksumManager::LFN2PFN(const char* lfn) { pfn = pfn_cstr; return pfn; } - diff --git a/src/XrdChecksum.hh b/src/XrdChecksum.hh index 147be22..308b1f3 100644 --- a/src/XrdChecksum.hh +++ b/src/XrdChecksum.hh @@ -109,6 +109,7 @@ public: int Set(const char *pfn, const ChecksumState &state); int Set(const char *pfn, const char *cksname, const char *chksvalue); + int Del(const char *pfn, unsigned digests); virtual ~ChecksumManager() {} @@ -140,4 +141,4 @@ private: -#endif \ No newline at end of file +#endif diff --git a/src/multiuser.cpp b/src/multiuser.cpp index d8f11a7..39b75f7 100644 --- a/src/multiuser.cpp +++ b/src/multiuser.cpp @@ -173,6 +173,7 @@ int MultiuserFile::Open(const char *path, int Oflag, mode_t Mode, XrdOucEnv ssize_t MultiuserFile::Write(const void *buffer, off_t offset, size_t size) { + bool checksum_abandoned = false; if ((offset != m_nextoff) && m_state) { @@ -181,13 +182,24 @@ ssize_t MultiuserFile::Write(const void *buffer, off_t offset, size_t size) m_log.Emsg("Write", ss.str().c_str()); delete m_state; m_state = NULL; + checksum_abandoned = true; } auto result = m_wrapped->Write(buffer, offset, size); - if (m_state && result >= 0) + if (result >= 0) { - m_nextoff += result; - m_state->Update(static_cast(buffer), size); + m_nextoff = offset + result; + } + if (checksum_abandoned && result > 0 && g_checksum_manager) + { + UserSentry sentry(m_client, m_log); + if (sentry.IsValid()) { + g_checksum_manager->Del(m_fname.c_str(), m_digests); + } + } + if (m_state && result > 0) + { + m_state->Update(static_cast(buffer), static_cast(result)); } return result; }