From a92e29ff7c101498d13c7d3c307945b59ab637dc Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Thu, 8 Jan 2009 15:38:28 -0800 Subject: [PATCH] move to generic ceph_seq_t 32-bit sequence number and comparator We want to behave when the seq # rolls over. We'll be fine as long as we don't differ by more than 1<<31. --- src/client/Client.h | 2 +- src/include/ceph_fs.h | 19 +++++++++++++++---- src/kernel/caps.c | 6 +++--- src/kernel/inode.c | 8 ++++---- src/mds/Capability.h | 32 ++++++++++++++------------------ src/mds/Locker.cc | 22 ++++++++++++---------- src/mds/Locker.h | 6 +++--- src/mds/mdstypes.h | 6 ++---- src/messages/MClientCaps.h | 8 ++++---- 9 files changed, 58 insertions(+), 51 deletions(-) diff --git a/src/client/Client.h b/src/client/Client.h index e359bd5e6b1c6..536c5fe7b9ee9 100644 --- a/src/client/Client.h +++ b/src/client/Client.h @@ -199,7 +199,7 @@ class Inode { int snap_caps, snap_cap_refs; unsigned exporting_issued; int exporting_mds; - capseq_t exporting_mseq; + ceph_seq_t exporting_mseq; utime_t hold_caps_until; xlist::item cap_item; diff --git a/src/include/ceph_fs.h b/src/include/ceph_fs.h index a79822a1a6b30..d06e7a57890db 100644 --- a/src/include/ceph_fs.h +++ b/src/include/ceph_fs.h @@ -100,6 +100,18 @@ struct ceph_timespec { } __attribute__ ((packed)); +/* + * Rollover-safe type and comparator for 32-bit sequence numbers. + * Comparator returns -1, 0, or 1. + */ +typedef __u32 ceph_seq_t; + +static inline __s32 ceph_seq_cmp(__u32 a, __u32 b) +{ + return ((__s32)a - (__s32)b); +} + + /* * "Frags" are a way to describe a subset of a 32-bit number space, * using a mask and a value to match against that mask. Any given frag @@ -833,7 +845,7 @@ struct ceph_mds_reply_inode { struct ceph_mds_reply_cap cap; struct ceph_file_layout layout; struct ceph_timespec ctime, mtime, atime; - __le64 time_warp_seq; + __le32 time_warp_seq; __le64 size, max_size, truncate_seq; __le32 mode, uid, gid; __le32 nlink; @@ -958,7 +970,6 @@ static inline int ceph_flags_to_mode(int flags) */ #define CEPH_CAP_EXPIREABLE (CEPH_CAP_PIN|CEPH_CAP_ANY_RDCACHE) - static inline int ceph_caps_for_mode(int mode) { switch (mode) { @@ -1041,10 +1052,10 @@ struct ceph_mds_caps { /* filelock */ __le64 size, max_size; - __le64 truncate_seq; + __le32 truncate_seq; struct ceph_timespec mtime, atime, ctime; struct ceph_file_layout layout; - __le64 time_warp_seq; + __le32 time_warp_seq; } __attribute__ ((packed)); diff --git a/src/kernel/caps.c b/src/kernel/caps.c index c29da0175eba4..3b2d0142191a8 100644 --- a/src/kernel/caps.c +++ b/src/kernel/caps.c @@ -1450,7 +1450,7 @@ static void handle_cap_export(struct inode *inode, struct ceph_mds_caps *ex, /* make sure we haven't seen a higher mseq */ for (p = rb_first(&ci->i_caps); p; p = rb_next(p)) { t = rb_entry(p, struct ceph_cap, ci_node); - if (t->mseq > mseq) { + if (ceph_seq_cmp(t->mseq, mseq) > 0) { dout(10, " higher mseq on cap from mds%d\n", t->session->s_mds); remember = 0; @@ -1498,7 +1498,7 @@ static void handle_cap_import(struct ceph_mds_client *mdsc, unsigned long ttl_ms = le32_to_cpu(im->ttl_ms); if (ci->i_cap_exporting_mds >= 0 && - ci->i_cap_exporting_mseq < mseq) { + ceph_seq_cmp(ci->i_cap_exporting_mseq, mseq) < 0) { dout(10, "handle_cap_import inode %p ci %p mds%d mseq %d" " - cleared exporting from mds%d\n", inode, ci, mds, mseq, @@ -1510,7 +1510,7 @@ static void handle_cap_import(struct ceph_mds_client *mdsc, dout(10, "handle_cap_import inode %p ci %p mds%d mseq %d\n", inode, ci, mds, mseq); } - + realm = ceph_update_snap_trace(mdsc, snaptrace, snaptrace+snaptrace_len, false); ceph_add_cap(inode, session, -1, issued, wanted, seq, mseq, realmino, diff --git a/src/kernel/inode.c b/src/kernel/inode.c index 0bcc32b381d81..5d6c8345370ac 100644 --- a/src/kernel/inode.c +++ b/src/kernel/inode.c @@ -330,7 +330,7 @@ void ceph_fill_file_bits(struct inode *inode, int issued, struct ceph_inode_info *ci = ceph_inode(inode); int warn = 0; - if (truncate_seq > ci->i_truncate_seq || + if (ceph_seq_cmp(truncate_seq, ci->i_truncate_seq) > 0 || (truncate_seq == ci->i_truncate_seq && size > inode->i_size)) { dout(10, "size %lld -> %llu\n", inode->i_size, size); inode->i_size = size; @@ -346,11 +346,11 @@ void ceph_fill_file_bits(struct inode *inode, int issued, */ if (timespec_compare(ctime, &inode->i_ctime) > 0) inode->i_ctime = *ctime; - if (time_warp_seq > ci->i_time_warp_seq) + if (ceph_seq_cmp(time_warp_seq, ci->i_time_warp_seq) > 0) derr(0, "WARNING: %p mds time_warp_seq %llu > %llu\n", inode, time_warp_seq, ci->i_time_warp_seq); } else if (issued & (CEPH_CAP_FILE_WR|CEPH_CAP_FILE_WRBUFFER)) { - if (time_warp_seq > ci->i_time_warp_seq) { + if (ceph_seq_cmp(time_warp_seq, ci->i_time_warp_seq) > 0) { /* the MDS did a utimes() */ inode->i_ctime = *ctime; inode->i_mtime = *mtime; @@ -368,7 +368,7 @@ void ceph_fill_file_bits(struct inode *inode, int issued, } } else { /* we have no write caps; whatever the MDS says is true */ - if (time_warp_seq >= ci->i_time_warp_seq) { + if (ceph_seq_cmp(time_warp_seq, ci->i_time_warp_seq) >= 0) { inode->i_ctime = *ctime; inode->i_mtime = *mtime; inode->i_atime = *atime; diff --git a/src/mds/Capability.h b/src/mds/Capability.h index 51e2145a31084..fb322db8b07a9 100644 --- a/src/mds/Capability.h +++ b/src/mds/Capability.h @@ -19,9 +19,6 @@ #include "include/buffer.h" #include "include/xlist.h" -#include -using namespace std; - #include "config.h" /* @@ -74,10 +71,10 @@ public: int32_t issued; int32_t pending; snapid_t client_follows; - capseq_t mseq; + ceph_seq_t mseq; utime_t last_issue_stamp; Export() {} - Export(int w, int i, int p, snapid_t cf, capseq_t s, utime_t lis) : + Export(int w, int i, int p, snapid_t cf, ceph_seq_t s, utime_t lis) : wanted(w), issued(i), pending(p), client_follows(cf), mseq(s), last_issue_stamp(lis) {} void encode(bufferlist &bl) const { ::encode(wanted, bl); @@ -102,7 +99,6 @@ private: int client; __u32 _wanted; // what the client wants (ideally) - //::decode(cap_history, bl); utime_t last_issue_stamp; @@ -119,14 +115,14 @@ public: int issued() { return _pending | _issued; } - capseq_t issue(int c) { + ceph_seq_t issue(int c) { _pending = c; _issued |= c; //last_issue = ++last_sent; return last_sent; } - void confirm_receipt(capseq_t seq, int caps) { + void confirm_receipt(ceph_seq_t seq, int caps) { if (seq == last_sent) _pending = _issued = caps; } @@ -139,7 +135,7 @@ public: static const int _max_revoke = 3; __u32 _pending, _issued; __u32 _revoke_before[_max_revoke]; // caps before this issue - capseq_t _revoke_seq[_max_revoke]; + ceph_seq_t _revoke_seq[_max_revoke]; int _num_revoke; public: @@ -150,7 +146,7 @@ public: c |= _revoke_before[i]; return c; } - capseq_t issue(int c) { + ceph_seq_t issue(int c) { if (_pending & ~c) { // note _revoked_ caps prior to this revocation if (_num_revoke < _max_revoke) { @@ -167,7 +163,7 @@ public: ++last_sent; return last_sent; } - void confirm_receipt(capseq_t seq, int caps) { + void confirm_receipt(ceph_seq_t seq, int caps) { _issued = caps; if (seq == last_sent) { _pending = caps; @@ -196,9 +192,9 @@ public: private: - capseq_t last_sent; - //capseq_t last_issue; - capseq_t mseq; + ceph_seq_t last_sent; + //ceph_seq_t last_issue; + ceph_seq_t mseq; int suppress; bool stale; @@ -224,9 +220,9 @@ public: client_follows(0), session_caps_item(this), rdcaps_list(rl), rdcaps_item(this), snaprealm_caps_item(this) { } - capseq_t get_mseq() { return mseq; } + ceph_seq_t get_mseq() { return mseq; } - capseq_t get_last_sent() { return last_sent; } + ceph_seq_t get_last_sent() { return last_sent; } utime_t get_last_issue_stamp() { return last_issue_stamp; } void touch() { if (rdcaps_item.is_on_xlist()) @@ -235,7 +231,7 @@ public: void set_last_issue_stamp(utime_t t) { last_issue_stamp = t; } - //capseq_t get_last_issue() { return last_issue; } + //ceph_seq_t get_last_issue() { return last_issue; } bool is_suppress() { return suppress > 0; } void inc_suppress() { suppress++; } @@ -254,7 +250,7 @@ public: _wanted = w; } - capseq_t get_last_seq() { return last_sent; } + ceph_seq_t get_last_seq() { return last_sent; } void check_rdcaps_list(int o, int n, int ow, int nw) diff --git a/src/mds/Locker.cc b/src/mds/Locker.cc index 8182b731d46e9..9b6123afaf4c9 100644 --- a/src/mds/Locker.cc +++ b/src/mds/Locker.cc @@ -490,9 +490,9 @@ struct C_Locker_FileUpdate_finish : public Context { bool share; int client; MClientCaps *ack; - capseq_t releasecap; + ceph_seq_t releasecap; C_Locker_FileUpdate_finish(Locker *l, CInode *i, Mutation *m, bool e=false, int c=-1, - MClientCaps *ac = 0, capseq_t rc=0) : + MClientCaps *ac = 0, ceph_seq_t rc=0) : locker(l), in(i), mut(m), share(e), client(c), ack(ac), releasecap(rc) { in->get(CInode::PIN_PTRWAITER); @@ -503,7 +503,7 @@ struct C_Locker_FileUpdate_finish : public Context { }; void Locker::file_update_finish(CInode *in, Mutation *mut, bool share, int client, - MClientCaps *ack, capseq_t releasecap) + MClientCaps *ack, ceph_seq_t releasecap) { dout(10) << "file_update_finish on " << *in << dendl; in->pop_and_dirty_projected_inode(mut->ls); @@ -1024,7 +1024,7 @@ void Locker::handle_client_caps(MClientCaps *m) in->add_waiter(CInode::WAIT_UNFREEZE, new C_MDS_RetryMessage(mds, m)); return; } - if (m->get_mseq() < cap->get_mseq()) { + if (ceph_seq_cmp(m->get_mseq(), cap->get_mseq()) < 0) { dout(7) << "handle_client_caps mseq " << m->get_mseq() << " < " << cap->get_mseq() << ", dropping" << dendl; delete m; @@ -1078,7 +1078,7 @@ void Locker::handle_client_caps(MClientCaps *m) << " on " << *in << dendl; MClientCaps *ack = 0; - capseq_t releasecap = 0; + ceph_seq_t releasecap = 0; if (m->get_dirty() && in->is_auth()) { dout(7) << " flush client" << client << " dirty " << ccap_string(m->get_dirty()) @@ -1087,7 +1087,8 @@ void Locker::handle_client_caps(MClientCaps *m) m->get_caps(), 0, m->get_dirty(), 0); } if (m->get_caps() == 0) { - assert(m->get_seq() <= cap->get_last_sent()); + + assert(ceph_seq_cmp(m->get_seq(), cap->get_last_sent()) <= 0); if (m->get_seq() == cap->get_last_sent()) { dout(7) << " releasing request client" << client << " seq " << m->get_seq() << " on " << *in << dendl; cap->releasing++; @@ -1129,7 +1130,7 @@ void Locker::handle_client_caps(MClientCaps *m) delete m; } -void Locker::_finish_release_cap(CInode *in, int client, capseq_t seq, MClientCaps *ack) +void Locker::_finish_release_cap(CInode *in, int client, ceph_seq_t seq, MClientCaps *ack) { dout(10) << "_finish_release_cap client" << client << " seq " << seq << " on " << *in << dendl; @@ -1144,7 +1145,7 @@ void Locker::_finish_release_cap(CInode *in, int client, capseq_t seq, MClientCa if (cap->releasing) { dout(10) << " another release attempt in flight, not releasing yet" << dendl; delete ack; - } else if (seq < cap->get_last_sent()) { + } else if (ceph_seq_cmp(seq, cap->get_last_sent()) < 0) { dout(10) << " NOT releasing cap client" << client << ", last_sent " << cap->get_last_sent() << " > " << seq << dendl; delete ack; @@ -1172,7 +1173,7 @@ void Locker::_finish_release_cap(CInode *in, int client, capseq_t seq, MClientCa * if we update, return true; otherwise, false (no updated needed). */ bool Locker::_do_cap_update(CInode *in, int dirty, int wanted, snapid_t follows, MClientCaps *m, - MClientCaps *ack, capseq_t releasecap) + MClientCaps *ack, ceph_seq_t releasecap) { dout(10) << "_do_cap_update dirty " << ccap_string(dirty) << " wanted " << ccap_string(wanted) @@ -1263,7 +1264,8 @@ bool Locker::_do_cap_update(CInode *in, int dirty, int wanted, snapid_t follows, << " for " << *in << dendl; pi->atime = atime; } - if ((dirty & CEPH_CAP_FILE_EXCL) && pi->time_warp_seq < m->get_time_warp_seq()) { + if ((dirty & CEPH_CAP_FILE_EXCL) && + ceph_seq_cmp(pi->time_warp_seq, m->get_time_warp_seq()) < 0) { dout(7) << " time_warp_seq " << pi->time_warp_seq << " -> " << m->get_time_warp_seq() << " for " << *in << dendl; pi->time_warp_seq = m->get_time_warp_seq(); diff --git a/src/mds/Locker.h b/src/mds/Locker.h index bc7cefca78b22..67fb6f66e110a 100644 --- a/src/mds/Locker.h +++ b/src/mds/Locker.h @@ -213,15 +213,15 @@ public: protected: void handle_client_caps(class MClientCaps *m); bool _do_cap_update(CInode *in, int had, int wanted, snapid_t follows, MClientCaps *m, - MClientCaps *ack=0, capseq_t releasecap=0); - void _finish_release_cap(CInode *in, int client, capseq_t seq, MClientCaps *ack); + MClientCaps *ack=0, ceph_seq_t releasecap=0); + void _finish_release_cap(CInode *in, int client, ceph_seq_t seq, MClientCaps *ack); void request_inode_file_caps(CInode *in); void handle_inode_file_caps(class MInodeFileCaps *m); void file_update_finish(CInode *in, Mutation *mut, bool share, int client, - MClientCaps *ack, capseq_t releasecap); + MClientCaps *ack, ceph_seq_t releasecap); public: bool check_inode_max_size(CInode *in, bool forceupdate=false, __u64 newsize=0); private: diff --git a/src/mds/mdstypes.h b/src/mds/mdstypes.h index 2f7ff45c51562..8cd8d4e12c34b 100644 --- a/src/mds/mdstypes.h +++ b/src/mds/mdstypes.h @@ -53,8 +53,6 @@ using namespace std; // CAPS -typedef __u32 capseq_t; - inline string gcap_string(int cap) { string s; @@ -296,10 +294,10 @@ struct inode_t { ceph_file_layout layout; uint64_t size; // on directory, # dentries uint64_t max_size; // client(s) are auth to write this much... - uint64_t truncate_seq; + uint32_t truncate_seq; utime_t mtime; // file data modify time. utime_t atime; // file data access time. - uint64_t time_warp_seq; // count of (potential) mtime/atime timewarps (i.e., utimes()) + uint32_t time_warp_seq; // count of (potential) mtime/atime timewarps (i.e., utimes()) // dirfrag, recursive accounting frag_info_t dirstat; diff --git a/src/messages/MClientCaps.h b/src/messages/MClientCaps.h index 2cf789a986121..4fe1f7f9dc8b6 100644 --- a/src/messages/MClientCaps.h +++ b/src/messages/MClientCaps.h @@ -27,19 +27,19 @@ class MClientCaps : public Message { int get_caps() { return head.caps; } int get_wanted() { return head.wanted; } int get_dirty() { return head.dirty; } - capseq_t get_seq() { return head.seq; } - capseq_t get_mseq() { return head.migrate_seq; } + ceph_seq_t get_seq() { return head.seq; } + ceph_seq_t get_mseq() { return head.migrate_seq; } inodeno_t get_ino() { return inodeno_t(head.ino); } inodeno_t get_realm() { return inodeno_t(head.realm); } __u64 get_size() { return head.size; } __u64 get_max_size() { return head.max_size; } - __u64 get_truncate_seq() { return head.truncate_seq; } + __u32 get_truncate_seq() { return head.truncate_seq; } utime_t get_ctime() { return utime_t(head.ctime); } utime_t get_mtime() { return utime_t(head.mtime); } utime_t get_atime() { return utime_t(head.atime); } - __u64 get_time_warp_seq() { return head.time_warp_seq; } + __u32 get_time_warp_seq() { return head.time_warp_seq; } ceph_file_layout& get_layout() { return head.layout; } -- 2.39.5