#include <numeric>
+#include "include/ceph_assert.h"
#include "include/types.h"
#include "include/xlist.h"
+#include "mds/flock.h"
#include "mds/mdstypes.h" // hrm
#include "osdc/ObjectCacher.h"
-#include "include/assert.h"
#include "InodeRef.h"
+#include "MetaSession.h"
#include "UserPerm.h"
#include "Delegation.h"
class Client;
-struct MetaSession;
class Dentry;
class Dir;
struct SnapRealm;
struct Inode;
-class ceph_lock_state_t;
class MetaRequest;
class filepath;
class Fh;
-struct Cap {
+class Cap {
+public:
+ Cap() = delete;
+ Cap(Inode &i, MetaSession *s) : inode(i),
+ session(s),
+ gen(s->cap_gen),
+ cap_item(this)
+ {
+ s->caps.push_back(&cap_item);
+ }
+ ~Cap() {
+ cap_item.remove_myself();
+ }
+
+ void touch(void) {
+ // move to back of LRU
+ session->caps.push_back(&cap_item);
+ }
+
+ void dump(Formatter *f) const;
+
+ Inode &inode;
MetaSession *session;
- Inode *inode;
- xlist<Cap*>::item cap_item;
-
- uint64_t cap_id;
- unsigned issued;
- unsigned implemented;
- unsigned wanted; // as known to mds.
- uint64_t seq, issue_seq;
- __u32 mseq; // migration seq
+ uint64_t cap_id = 0;
+ unsigned issued = 0;
+ unsigned implemented = 0;
+ unsigned wanted = 0; // as known to mds.
+ uint64_t seq = 0;
+ uint64_t issue_seq = 0;
+ __u32 mseq = 0; // migration seq
__u32 gen;
UserPerm latest_perms;
- Cap() : session(NULL), inode(NULL), cap_item(this), cap_id(0), issued(0),
- implemented(0), wanted(0), seq(0), issue_seq(0), mseq(0), gen(0),
- latest_perms() {}
-
- void dump(Formatter *f) const;
+private:
+ /* Note that this Cap will not move (see Inode::caps):
+ *
+ * Section 23.1.2#8
+ * The insert members shall not affect the validity of iterators and
+ * references to the container, and the erase members shall invalidate only
+ * iterators and references to the erased elements.
+ */
+ xlist<Cap *>::item cap_item;
};
struct CapSnap {
bool writing, dirty_data;
uint64_t flush_tid;
+ int64_t cap_dirtier_uid;
+ int64_t cap_dirtier_gid;
+
explicit CapSnap(Inode *i)
: in(i), issued(0), dirty(0), size(0), time_warp_seq(0), change_attr(0),
mode(0), uid(0), gid(0), xattr_version(0), inline_version(0),
- writing(false), dirty_data(false), flush_tid(0)
+ writing(false), dirty_data(false), flush_tid(0), cap_dirtier_uid(-1),
+ cap_dirtier_gid(-1)
{}
void dump(Formatter *f) const;
};
// inode flags
-#define I_COMPLETE 1
-#define I_DIR_ORDERED 2
-#define I_CAP_DROPPED 4
-#define I_SNAPDIR_OPEN 8
+#define I_COMPLETE (1 << 0)
+#define I_DIR_ORDERED (1 << 1)
+#define I_SNAPDIR_OPEN (1 << 2)
+#define I_KICK_FLUSH (1 << 3)
+#define I_CAP_DROPPED (1 << 4)
+#define I_ERROR_FILELOCK (1 << 5)
struct Inode {
Client *client;
// special stuff
version_t version; // auth only
version_t xattr_version;
+ utime_t snap_btime; // snapshot creation (birth) time
// inline data
version_t inline_version;
bufferlist inline_data;
- bool is_root() const { return ino == MDS_INO_ROOT; }
+ bool is_root() const { return ino == CEPH_INO_ROOT; }
bool is_symlink() const { return (mode & S_IFMT) == S_IFLNK; }
bool is_dir() const { return (mode & S_IFMT) == S_IFDIR; }
bool is_file() const { return (mode & S_IFMT) == S_IFREG; }
int which = dir_layout.dl_dir_hash;
if (!which)
which = CEPH_STR_HASH_LINUX;
- assert(ceph_str_hash_valid(which));
+ ceph_assert(ceph_str_hash_valid(which));
return ceph_str_hash(which, dn.data(), dn.length());
}
// about the dir (if this is one!)
Dir *dir; // if i'm a dir.
fragtree_t dirfragtree;
- set<int> dir_contacts;
uint64_t dir_release_count, dir_ordered_count;
bool dir_hashed, dir_replicated;
// per-mds caps
- map<mds_rank_t, Cap*> caps; // mds -> Cap
+ std::map<mds_rank_t, Cap> caps; // mds -> Cap
Cap *auth_cap;
int64_t cap_dirtier_uid;
int64_t cap_dirtier_gid;
uint64_t reported_size, wanted_max_size, requested_max_size;
int _ref; // ref count. 1 for each dentry, fh that links to me.
- int ll_ref; // separate ref count for ll client
- set<Dentry*> dn_set; // if i'm linked to a dentry.
+ uint64_t ll_ref; // separate ref count for ll client
+ xlist<Dentry *> dentries; // if i'm linked to a dentry.
string symlink; // symlink content, if it's a symlink
map<string,bufferptr> xattrs;
map<frag_t,int> fragmap; // known frag -> mds mappings
- list<Cond*> waitfor_caps;
- list<Cond*> waitfor_commit;
- list<Cond*> waitfor_deleg;
+ std::list<ceph::condition_variable*> waitfor_caps;
+ std::list<ceph::condition_variable*> waitfor_commit;
+ std::list<ceph::condition_variable*> waitfor_deleg;
Dentry *get_first_parent() {
- assert(!dn_set.empty());
- return *dn_set.begin();
+ ceph_assert(!dentries.empty());
+ return *dentries.begin();
}
void make_long_path(filepath& p);
+ void make_short_path(filepath& p);
void make_nosnap_relative_path(filepath& p);
void get();
void ll_get() {
ll_ref++;
}
- void ll_put(int n=1) {
- assert(ll_ref >= n);
+ void ll_put(uint64_t n=1) {
+ ceph_assert(ll_ref >= n);
ll_ref -= n;
}
// file locks
- ceph_lock_state_t *fcntl_locks;
- ceph_lock_state_t *flock_locks;
+ std::unique_ptr<ceph_lock_state_t> fcntl_locks;
+ std::unique_ptr<ceph_lock_state_t> flock_locks;
+
+ bool has_any_filelocks() {
+ return
+ (fcntl_locks && !fcntl_locks->empty()) ||
+ (flock_locks && !flock_locks->empty());
+ }
list<Delegation> delegations;
std::set<Fh*> fhs;
+ mds_rank_t dir_pin;
+
Inode(Client *c, vinodeno_t vino, file_layout_t *newlayout)
: client(c), ino(vino.ino), snapid(vino.snapid), faked_ino(0),
rdev(0), mode(0), uid(0), gid(0), nlink(0),
snaprealm(0), snaprealm_item(this),
oset((void *)this, newlayout->pool_id, this->ino),
reported_size(0), wanted_max_size(0), requested_max_size(0),
- _ref(0), ll_ref(0), dn_set(),
- fcntl_locks(NULL), flock_locks(NULL)
+ _ref(0), ll_ref(0), dir_pin(MDS_RANK_NONE)
{
memset(&dir_layout, 0, sizeof(dir_layout));
}
void get_cap_ref(int cap);
int put_cap_ref(int cap);
bool is_any_caps();
- bool cap_is_valid(Cap* cap) const;
+ bool cap_is_valid(const Cap &cap) const;
int caps_issued(int *implemented = 0) const;
- void touch_cap(Cap *cap);
void try_touch_cap(mds_rank_t mds);
bool caps_issued_mask(unsigned mask, bool allow_impl=false);
int caps_used();