Skip to content

Commit

Permalink
XrdApps::JCache: add exclusive locking when journals are used to prev…
Browse files Browse the repository at this point in the history
…ent multi-client interference on shared filesystems
  • Loading branch information
apeters1971 committed Jun 11, 2024
1 parent d0e22c7 commit a5e5d38
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 2 deletions.
2 changes: 2 additions & 0 deletions src/XrdApps.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,8 @@ add_library(
XrdApps/XrdClJCachePlugin/cache/Journal.hh
XrdApps/XrdClJCachePlugin/cache/IntervalTree.hh
XrdApps/XrdClJCachePlugin/cache/RbTree.hh
XrdApps/XrdClJCachePlugin/cleaner/Cleaner.cc
XrdApps/XrdClJCachePlugin/cleaner/Cleaner.hh
)

target_include_directories( ${LIB_XRDCL_JCACHE_PLUGIN} PRIVATE "${CMAKE_SOURCE_DIR}/src/XrdApps/XrdClJCachePlugin/" )
Expand Down
35 changes: 35 additions & 0 deletions src/XrdApps/XrdClJCachePlugin/cache/Journal.cc
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <iostream>
#include <cstring>
#include <cerrno>
/*----------------------------------------------------------------------------*/

//------------------------------------------------------------------------------
Expand All @@ -53,6 +56,14 @@ Journal::Journal() : cachesize(0), max_offset(0), fd(-1) {
Journal::~Journal() {
std::lock_guard<std::mutex> guard(mtx);
if (fd > 0) {
struct flock lock;
std::memset(&lock, 0, sizeof(lock));

lock.l_type = F_UNLCK; // Unlock the file
if (fcntl(fd, F_SETLK, &lock) == -1) {
std::cerr << "error: failed to unlock journal: " << std::strerror(errno) << std::endl;
}

int rc = close(fd);

if (rc) {
Expand Down Expand Up @@ -171,6 +182,30 @@ int Journal::attach(const std::string &lpath, uint64_t mtime,
return -errno;
}

// get a POSIX lock on the file
struct flock lock;
std::memset(&lock, 0, sizeof(lock));
lock.l_type = F_WRLCK; // Request a write lock
lock.l_whence = SEEK_SET; // Lock from the beginning of the file
lock.l_start = 0; // Starting offset for lock
lock.l_len = 0; // 0 means to lock the entire file

if (fcntl(fd, F_SETLK, &lock) == -1) {
if (errno == EACCES || errno == EAGAIN) {
std::cerr << "error: journal file is already locked by another process."
<< std::endl;
close(fd);
fd = -1;
return -errno;
} else {
std::cerr << "error: failed to lock journal file: " << std::strerror(errno)
<< std::endl;
close(fd);
fd = -1;
return -errno;
}
}

break;
} while (1);

Expand Down
4 changes: 2 additions & 2 deletions src/XrdApps/XrdClJCachePlugin/file/XrdClJCacheFile.cc
Original file line number Diff line number Diff line change
Expand Up @@ -463,12 +463,12 @@ bool JCacheFile::AttachForRead() {
}
if (pJournal->attach(pJournalPath, sinfo->GetModTime(), 0,
sinfo->GetSize())) {
mLog->Error(1, "JCache : failed to attach to cache directory: %s",
mLog->Error(1, "JCache : failed to attach to cache file: %s",
pJournalPath.c_str());
mAttachedForRead = true;
return false;
} else {
mLog->Info(1, "JCache : attached to cache directory: %s",
mLog->Info(1, "JCache : attached to cache file: %s",
pJournalPath.c_str());
}
}
Expand Down

0 comments on commit a5e5d38

Please sign in to comment.