o.back()->prior_parent_snaps.push_back(5);
}
+// -- "new" SnapRealmInfo --
+
+void SnapRealmInfoNew::encode(ceph::buffer::list& bl) const
+{
+ using ceph::encode;
+ ENCODE_START(1, 1, bl);
+ encode(info, bl);
+ encode(last_modified, bl);
+ encode(change_attr, bl);
+ ENCODE_FINISH(bl);
+}
+
+void SnapRealmInfoNew::decode(ceph::buffer::list::const_iterator& bl)
+{
+ using ceph::decode;
+ DECODE_START(1, bl);
+ decode(info, bl);
+ decode(last_modified, bl);
+ decode(change_attr, bl);
+ DECODE_FINISH(bl);
+}
+
+void SnapRealmInfoNew::dump(ceph::Formatter *f) const
+{
+ info.dump(f);
+ f->dump_stream("last_modified") << last_modified;
+ f->dump_unsigned("change_attr", change_attr);
+}
+
+void SnapRealmInfoNew::generate_test_instances(std::list<SnapRealmInfoNew*>& o)
+{
+ o.push_back(new SnapRealmInfoNew);
+ o.push_back(new SnapRealmInfoNew(SnapRealmInfo(1, 10, 10, 0), utime_t(), 0));
+ o.push_back(new SnapRealmInfoNew(SnapRealmInfo(1, 10, 10, 0), utime_t(), 1));
+ o.back()->info.my_snaps.push_back(10);
+ o.push_back(new SnapRealmInfoNew(SnapRealmInfo(1, 10, 10, 5), utime_t(), 2));
+ o.back()->info.my_snaps.push_back(10);
+ o.back()->info.prior_parent_snaps.push_back(3);
+ o.back()->info.prior_parent_snaps.push_back(5);
+}
// -----
#define __CEPH_SNAP_TYPES_H
#include "include/types.h"
+#include "include/utime.h"
#include "include/fs_types.h"
namespace ceph {
};
WRITE_CLASS_ENCODER(SnapRealmInfo)
+// "new* snap realm info - carries additional metadata (last modified,
+// change_attr) and is version encoded.
+struct SnapRealmInfoNew {
+ SnapRealmInfo info;
+ utime_t last_modified;
+ uint64_t change_attr;
+
+ SnapRealmInfoNew() {
+ }
+
+ SnapRealmInfoNew(const SnapRealmInfo &info_, utime_t last_modified_, uint64_t change_attr_) {
+ // FIPS zeroization audit 20191115: this memset is not security related.
+ info = info_;
+ last_modified = last_modified_;
+ change_attr = change_attr_;
+ }
+
+ inodeno_t ino() const { return inodeno_t(info.h.ino); }
+ inodeno_t parent() const { return inodeno_t(info.h.parent); }
+ snapid_t seq() const { return snapid_t(info.h.seq); }
+ snapid_t parent_since() const { return snapid_t(info.h.parent_since); }
+ snapid_t created() const { return snapid_t(info.h.created); }
+
+ void encode(ceph::buffer::list& bl) const;
+ void decode(ceph::buffer::list::const_iterator& bl);
+ void dump(ceph::Formatter *f) const;
+ static void generate_test_instances(std::list<SnapRealmInfoNew*>& o);
+};
+WRITE_CLASS_ENCODER(SnapRealmInfoNew)
struct SnapContext {
snapid_t seq; // 'time' stamp
snap = make_message<MClientSnap>(CEPH_SNAP_OP_SPLIT);
splits.emplace(std::piecewise_construct, std::forward_as_tuple(client), std::forward_as_tuple(snap));
snap->head.split = realm->inode->ino();
- snap->bl = realm->get_snap_trace();
+ snap->bl = mds->server->get_snap_trace(client, realm);
for (const auto& child : realm->open_children)
snap->split_realms.push_back(child->inode->ino());
update->head.split = parent_realm->inode->ino();
update->split_inos = split_inos;
update->split_realms = split_realms;
- update->bl = parent_realm->get_snap_trace();
+ update->bl = mds->server->get_snap_trace(p.first, parent_realm);
em.first->second = std::move(update);
}
}
cap->get_last_seq(), cap->pending(), cap->wanted(),
0, cap->get_mseq(), mds->get_osd_epoch_barrier());
in->encode_cap_message(reap, cap);
- reap->snapbl = realm->get_snap_trace();
+ reap->snapbl = mds->server->get_snap_trace(session, realm);
reap->set_cap_peer(p_cap_id, p_seq, p_mseq, peer, p_flags);
mds->send_message_client_counted(reap, session);
}
dout(10) << "finish_snaprealm_reconnect client." << client << " has old seq " << seq << " < "
<< realm->get_newest_seq() << " on " << *realm << dendl;
auto snap = make_message<MClientSnap>(CEPH_SNAP_OP_UPDATE);
- snap->bl = realm->get_snap_trace();
+ snap->bl = mds->server->get_snap_trace(client, realm);
updates.emplace(std::piecewise_construct, std::forward_as_tuple(client), std::forward_as_tuple(snap));
} else {
dout(10) << "finish_snaprealm_reconnect client." << client << " up to date"
update->head.split = in->ino();
update->split_inos = split_inos;
update->split_realms = split_realms;
- update->bl = in->snaprealm->get_snap_trace();
+ update->bl = mds->server->get_snap_trace(em.first->first, in->snaprealm);
em.first->second = std::move(update);
}
}
continue;
auto update = make_message<MClientSnap>(snap_op);
update->head.split = global_snaprealm->inode->ino();
- update->bl = global_snaprealm->get_snap_trace();
+ update->bl = mds->server->get_snap_trace(session, global_snaprealm);
mds->send_message_client_counted(update, session);
}
}
realm = in->find_snaprealm();
else
realm = dn->get_dir()->get_inode()->find_snaprealm();
- reply->snapbl = realm->get_snap_trace();
+ reply->snapbl = get_snap_trace(session, realm);
dout(10) << "set_trace_dist snaprealm " << *realm << " len=" << reply->snapbl.length() << dendl;
}
// this isn't perfect, but we should capture the main variable/unbounded size items!
int front_bytes = dirbl.length() + sizeof(__u32) + sizeof(__u8)*2;
int bytes_left = max_bytes - front_bytes;
- bytes_left -= realm->get_snap_trace().length();
+ bytes_left -= get_snap_trace(session, realm).length();
// build dir contents
bufferlist dnbl;
f->dump_stream("client_reconnect_gather") << client_reconnect_gather;
f->close_section();
}
+
+const bufferlist& Server::get_snap_trace(Session *session, SnapRealm *realm) const {
+ ceph_assert(session);
+ ceph_assert(realm);
+ if (session->info.has_feature(CEPHFS_FEATURE_NEW_SNAPREALM_INFO)) {
+ return realm->get_snap_trace_new();
+ } else {
+ return realm->get_snap_trace();
+ }
+}
+
+const bufferlist& Server::get_snap_trace(client_t client, SnapRealm *realm) const {
+ Session *session = mds->sessionmap.get_session(entity_name_t::CLIENT(client.v));
+ return get_snap_trace(session, realm);
+}
laggy_clients.clear();
}
+ const bufferlist& get_snap_trace(Session *session, SnapRealm *realm) const;
+ const bufferlist& get_snap_trace(client_t client, SnapRealm *realm) const;
+
private:
friend class MDSContinuation;
friend class ServerContext;
return cached_snap_trace;
}
+const bufferlist& SnapRealm::get_snap_trace_new() const
+{
+ check_cache();
+ return cached_snap_trace_new;
+}
+
void SnapRealm::build_snap_trace() const
{
cached_snap_trace.clear();
+ cached_snap_trace_new.clear();
if (global) {
SnapRealmInfo info(inode->ino(), 0, cached_seq, 0);
info.my_snaps.push_back(*p);
dout(10) << "build_snap_trace my_snaps " << info.my_snaps << dendl;
+
+ SnapRealmInfoNew ninfo(info, srnode.last_modified, srnode.change_attr);
encode(info, cached_snap_trace);
+ encode(ninfo, cached_snap_trace_new);
return;
}
info.my_snaps.push_back(p->first);
dout(10) << "build_snap_trace my_snaps " << info.my_snaps << dendl;
+ SnapRealmInfoNew ninfo(info, srnode.last_modified, srnode.change_attr);
+
encode(info, cached_snap_trace);
+ encode(ninfo, cached_snap_trace_new);
- if (parent)
+ if (parent) {
cached_snap_trace.append(parent->get_snap_trace());
+ cached_snap_trace_new.append(parent->get_snap_trace_new());
+ }
}
void SnapRealm::prune_past_parent_snaps()
void get_snap_info(std::map<snapid_t, const SnapInfo*>& infomap, snapid_t first=0, snapid_t last=CEPH_NOSNAP);
const ceph::buffer::list& get_snap_trace() const;
+ const ceph::buffer::list& get_snap_trace_new() const;
void build_snap_trace() const;
std::string_view get_snapname(snapid_t snapid, inodeno_t atino);
mutable std::set<snapid_t> cached_snaps;
mutable SnapContext cached_snap_context;
mutable ceph::buffer::list cached_snap_trace;
+ mutable ceph::buffer::list cached_snap_trace_new;
mutable inodeno_t cached_subvolume_ino = 0;
};
CEPHFS_FEATURE_NOTIFY_SESSION_STATE, \
CEPHFS_FEATURE_OP_GETVXATTR, \
CEPHFS_FEATURE_32BITS_RETRY_FWD, \
+ CEPHFS_FEATURE_NEW_SNAPREALM_INFO, \
CEPHFS_FEATURE_HAS_OWNER_UIDGID, \
}