From 41a38d46a734d13c9a17c068ee9b7d6671d2bd1f Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Thu, 4 Jun 2009 21:03:41 -0700 Subject: [PATCH] rados: include pool_snap_info in pg_pools Include info about snaps global to each pg_pool in the pg_pool_t (and thus OSDMap). These snap contexts will be used when a snapc is not explicitly specified by the client. Note that the pool-wide snaps are (presently) mutually exclusive with client-controlls snaps (as used by ceph) because a mixture of @snaps and @removed_snaps doesn't clearly defined which snaps do not exist (they share the namespace). --- src/include/encoding.h | 18 +++++++++ src/include/interval_set.h | 11 +++++ src/include/rados.h | 7 ++++ src/include/types.h | 3 ++ src/osd/osd_types.h | 82 +++++++++++++++++++++++++++++++++----- 5 files changed, 111 insertions(+), 10 deletions(-) diff --git a/src/include/encoding.h b/src/include/encoding.h index 4115da802940f..5fbea1802a897 100644 --- a/src/include/encoding.h +++ b/src/include/encoding.h @@ -351,6 +351,24 @@ inline void decode(std::map& m, bufferlist::iterator& p) decode(m[k], p); } } +template +inline void encode_nohead(const std::map& m, bufferlist& bl) +{ + for (typename std::map::const_iterator p = m.begin(); p != m.end(); ++p) { + encode(p->first, bl); + encode(p->second, bl); + } +} +template +inline void decode_nohead(int n, std::map& m, bufferlist::iterator& p) +{ + m.clear(); + while (n--) { + T k; + decode(k, p); + decode(m[k], p); + } +} // multimap template diff --git a/src/include/interval_set.h b/src/include/interval_set.h index 65f18c948c705..8fd7f65bc7dad 100644 --- a/src/include/interval_set.h +++ b/src/include/interval_set.h @@ -96,6 +96,9 @@ class interval_set { void encode(bufferlist& bl) const { ::encode(m, bl); } + void encode_nohead(bufferlist& bl) const { + ::encode_nohead(m, bl); + } void decode(bufferlist::iterator& bl) { ::decode(m, bl); _size = 0; @@ -104,6 +107,14 @@ class interval_set { p++) _size += p->second; } + void decode_nohead(int n, bufferlist::iterator& bl) { + ::decode_nohead(n, m, bl); + _size = 0; + for (typename map::const_iterator p = m.begin(); + p != m.end(); + p++) + _size += p->second; + } void clear() { m.clear(); diff --git a/src/include/rados.h b/src/include/rados.h index 5b75b02e3a7ad..b01ef8bf06af7 100644 --- a/src/include/rados.h +++ b/src/include/rados.h @@ -1,3 +1,6 @@ +// -*- mode:C; tab-width:8; c-basic-offset:8; indent-tabs-mode:t -*- +// vim: ts=8 sw=8 smarttab + #ifndef __RADOS_H #define __RADOS_H @@ -91,6 +94,10 @@ struct ceph_pg_pool { __le32 pg_num, pgp_num; __le32 lpg_num, lpgp_num; __le32 last_change; /* most recent epoch changed */ + __le64 snap_seq; + __le32 snap_epoch; + __le32 num_snaps; + __le32 num_removed_snap_intervals; } __attribute__ ((packed)); /* diff --git a/src/include/types.h b/src/include/types.h index 47f816c2ddbb0..709668ee155f7 100644 --- a/src/include/types.h +++ b/src/include/types.h @@ -325,6 +325,9 @@ struct SnapContext { snapid_t seq; // 'time' stamp vector snaps; // existent snaps, in descending order + SnapContext() {} + SnapContext(snapid_t s, vector& v) : seq(s), snaps(v) {} + void clear() { seq = 0; snaps.clear(); diff --git a/src/osd/osd_types.h b/src/osd/osd_types.h index 69e457b9a83e6..fbf1f08366159 100644 --- a/src/osd/osd_types.h +++ b/src/osd/osd_types.h @@ -379,15 +379,65 @@ static inline std::string pg_state_string(int state) { } +/* + * pool_snap_info_t + * + * attributes for a single pool snapshot. + */ +struct pool_snap_info_t { + snapid_t snapid; + utime_t stamp; + nstring name; + + void encode(bufferlist& bl) const { + ::encode(snapid, bl); + ::encode(stamp, bl); + ::encode(name, bl); + } + void decode(bufferlist::iterator& bl) { + ::decode(snapid, bl); + ::decode(stamp, bl); + ::decode(name, bl); + } +}; +WRITE_CLASS_ENCODER(pool_snap_info_t) + +inline ostream& operator<<(ostream& out, const pool_snap_info_t& si) { + return out << si.snapid << '(' << si.name << ' ' << si.stamp << ')'; +} /* * pg_pool */ struct pg_pool_t { - ceph_pg_pool v; + mutable ceph_pg_pool v; int pg_num_mask, pgp_num_mask, lpg_num_mask, lpgp_num_mask; + /* + * Pool snaps (global to this pool). These define a SnapContext for + * the pool, unless the client manually specifies an alternate + * context. + */ + map snaps; + /* + * Alternatively, if we are definining non-pool snaps (e.g. via the + * Ceph MDS), we must track @removed_snaps (since @snaps is not + * used). Snaps and removed_snaps are to be used exclusive of each + * other! + */ + interval_set removed_snaps; + + unsigned get_type() const { return v.type; } + unsigned get_size() const { return v.size; } + int get_crush_ruleset() const { return v.crush_ruleset; } + epoch_t get_last_change() const { return v.last_change; } + epoch_t get_snap_epoch() const { return v.snap_epoch; } + snapid_t get_snap_seq() const { return snapid_t(v.snap_seq); } + + bool is_rep() const { return get_type() == CEPH_PG_TYPE_REP; } + bool is_raid4() const { return get_type() == CEPH_PG_TYPE_RAID4; } + int get_pg_num() const { return v.pg_num; } int get_pgp_num() const { return v.pgp_num; } int get_lpg_num() const { return v.lpg_num; } @@ -406,15 +456,6 @@ struct pg_pool_t { } return b; } - - unsigned get_type() const { return v.type; } - unsigned get_size() const { return v.size; } - int get_crush_ruleset() const { return v.crush_ruleset; } - epoch_t get_last_change() const { return v.last_change; } - - bool is_rep() const { return get_type() == CEPH_PG_TYPE_REP; } - bool is_raid4() const { return get_type() == CEPH_PG_TYPE_RAID4; } - void calc_pg_masks() { pg_num_mask = (1 << calc_bits_of(v.pg_num-1)) - 1; pgp_num_mask = (1 << calc_bits_of(v.pgp_num-1)) - 1; @@ -422,6 +463,21 @@ struct pg_pool_t { lpgp_num_mask = (1 << calc_bits_of(v.lpgp_num-1)) - 1; } + bool is_removed_snap(snapid_t s) { + if (snaps.size()) + return snaps.count(s) == 0; + return s <= get_snap_seq() && removed_snaps.contains(s); + } + SnapContext get_snap_context() const { + vector s(snaps.size()); + unsigned i = 0; + for (map::const_reverse_iterator p = snaps.rbegin(); + p != snaps.rend(); + p++) + s[i++] = p->first; + return SnapContext(get_snap_seq(), s); + } + /* * map a raw pg (with full precision ps) into an actual pg, for storage */ @@ -444,10 +500,16 @@ struct pg_pool_t { } void encode(bufferlist& bl) const { + v.num_snaps = snaps.size(); + v.num_removed_snap_intervals = removed_snaps.m.size(); ::encode(v, bl); + ::encode_nohead(snaps, bl); + removed_snaps.encode_nohead(bl); } void decode(bufferlist::iterator& bl) { ::decode(v, bl); + ::decode_nohead(v.num_snaps, snaps, bl); + removed_snaps.decode_nohead(v.num_removed_snap_intervals, bl); calc_pg_masks(); } }; -- 2.39.5