#define CLUSTER_SNAP_ITEM "clustersnap_%s"
#define REPLAY_GUARD_XATTR "user.cephos.seq"
+#define GLOBAL_REPLAY_GUARD_XATTR "user.cephos.gseq"
/*
* long file names will have the following format:
return r;
}
+void FileStore::_set_global_replay_guard(coll_t cid,
+ const SequencerPosition &spos)
+{
+ if (btrfs_stable_commits)
+ return;
+
+ // sync all previous operations on this sequencer
+ sync_filesystem(basedir_fd);
+
+ char fn[PATH_MAX];
+ get_cdir(cid, fn, sizeof(fn));
+ int fd = ::open(fn, O_RDONLY);
+ if (fd < 0) {
+ int err = errno;
+ derr << __func__ << ": " << cid << " error " << cpp_strerror(err) << dendl;
+ assert(0 == "_set_global_replay_guard failed");
+ }
+
+ _inject_failure();
+
+ // then record that we did it
+ bufferlist v;
+ ::encode(spos, v);
+ int r = chain_fsetxattr(fd, GLOBAL_REPLAY_GUARD_XATTR, v.c_str(), v.length());
+ if (r < 0) {
+ derr << __func__ << ": fsetxattr " << GLOBAL_REPLAY_GUARD_XATTR
+ << " got " << cpp_strerror(r) << dendl;
+ assert(0 == "fsetxattr failed");
+ }
+
+ // and make sure our xattr is durable.
+ ::fsync(fd);
+
+ _inject_failure();
+
+ TEMP_FAILURE_RETRY(::close(fd));
+ dout(10) << __func__ << ": " << spos << " done" << dendl;
+}
+
+int FileStore::_check_global_replay_guard(coll_t cid,
+ const SequencerPosition& spos)
+{
+ if (!replaying || btrfs_stable_commits)
+ return 1;
+
+ char fn[PATH_MAX];
+ get_cdir(cid, fn, sizeof(fn));
+ int fd = ::open(fn, O_RDONLY);
+ if (fd < 0) {
+ dout(10) << __func__ << ": " << cid << " dne" << dendl;
+ return 1; // if collection does not exist, there is no guard, and we can replay.
+ }
+
+ char buf[100];
+ int r = chain_fgetxattr(fd, GLOBAL_REPLAY_GUARD_XATTR, buf, sizeof(buf));
+ if (r < 0) {
+ dout(20) << __func__ << " no xattr" << dendl;
+ assert(!m_filestore_fail_eio || r != -EIO);
+ return 1; // no xattr
+ }
+ bufferlist bl;
+ bl.append(buf, r);
+
+ SequencerPosition opos;
+ bufferlist::iterator p = bl.begin();
+ ::decode(opos, p);
+
+ TEMP_FAILURE_RETRY(::close(fd));
+ return spos >= opos ? 1 : -1;
+}
+
+
void FileStore::_set_replay_guard(coll_t cid,
const SequencerPosition &spos,
bool in_progress=false)
if (!replaying || btrfs_stable_commits)
return 1;
+ int r = _check_global_replay_guard(cid, spos);
+ if (r < 0)
+ return r;
+
FDRef fd;
- int r = lfn_open(cid, oid, false, &fd);
+ r = lfn_open(cid, oid, false, &fd);
if (r < 0) {
dout(10) << "_check_replay_guard " << cid << " " << oid << " dne" << dendl;
return 1; // if file does not exist, there is no guard, and we can replay.
get_cdir(cid, old_coll, sizeof(old_coll));
get_cdir(ncid, new_coll, sizeof(new_coll));
+ _set_global_replay_guard(cid, spos);
+ _set_replay_guard(cid, spos);
+
if (_check_replay_guard(cid, spos) < 0) {
return 0;
}
if (srccmp < 0)
return 0;
+ _set_global_replay_guard(cid, spos);
_set_replay_guard(cid, spos, true);
_set_replay_guard(dest, spos, true);
void _set_replay_guard(coll_t cid,
const SequencerPosition& spos,
bool in_progress);
+ void _set_global_replay_guard(coll_t cid,
+ const SequencerPosition &spos);
/// close a replay guard opened with in_progress=true
void _close_replay_guard(int fd, const SequencerPosition& spos);
int _check_replay_guard(int fd, const SequencerPosition& spos);
int _check_replay_guard(coll_t cid, const SequencerPosition& spos);
int _check_replay_guard(coll_t cid, hobject_t oid, const SequencerPosition& pos);
+ int _check_global_replay_guard(coll_t cid, const SequencerPosition& spos);
// ------------------
// objects