// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab #ifndef CEPH_CLIENT_INODE_H #define CEPH_CLIENT_INODE_H #include "include/types.h" #include "include/xlist.h" #include "mds/mdstypes.h" // hrm #include "osdc/ObjectCacher.h" #include "include/assert.h" #include "InodeRef.h" #include "UserPerm.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 { MetaSession *session; Inode *inode; xlist::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 __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; }; struct CapSnap { //snapid_t follows; // map key InodeRef in; SnapContext context; int issued, dirty; uint64_t size; utime_t ctime, btime, mtime, atime; version_t time_warp_seq; uint64_t change_attr; uint32_t mode; uid_t uid; gid_t gid; map xattrs; version_t xattr_version; bufferlist inline_data; version_t inline_version; bool writing, dirty_data; uint64_t flush_tid; 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) {} 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 struct Inode { Client *client; // -- the actual inode -- inodeno_t ino; // ORDER DEPENDENCY: oset snapid_t snapid; ino_t faked_ino; uint32_t rdev; // if special file // affected by any inode change... utime_t ctime; // inode change time utime_t btime; // birth time // perm (namespace permissions) uint32_t mode; uid_t uid; gid_t gid; // nlink int32_t nlink; // file (data access) ceph_dir_layout dir_layout; file_layout_t layout; uint64_t size; // on directory, # dentries uint32_t truncate_seq; uint64_t truncate_size; utime_t mtime; // file data modify time. utime_t atime; // file data access time. uint32_t time_warp_seq; // count of (potential) mtime/atime timewarps (i.e., utimes()) uint64_t change_attr; uint64_t max_size; // max size we can write to // dirfrag, recursive accountin frag_info_t dirstat; nest_info_t rstat; // special stuff version_t version; // auth only version_t xattr_version; // inline data version_t inline_version; bufferlist inline_data; bool is_root() const { return ino == MDS_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; } bool has_dir_layout() const { return layout != file_layout_t(); } __u32 hash_dentry_name(const string &dn) { int which = dir_layout.dl_dir_hash; if (!which) which = CEPH_STR_HASH_LINUX; assert(ceph_str_hash_valid(which)); return ceph_str_hash(which, dn.data(), dn.length()); } unsigned flags; quota_info_t quota; bool is_complete_and_ordered() { static const unsigned wants = I_COMPLETE | I_DIR_ORDERED; return (flags & wants) == wants; } // about the dir (if this is one!) Dir *dir; // if i'm a dir. fragtree_t dirfragtree; set dir_contacts; uint64_t dir_release_count, dir_ordered_count; bool dir_hashed, dir_replicated; // per-mds caps map caps; // mds -> Cap Cap *auth_cap; int64_t cap_dirtier_uid; int64_t cap_dirtier_gid; unsigned dirty_caps, flushing_caps; std::map flushing_cap_tids; int shared_gen, cache_gen; int snap_caps, snap_cap_refs; utime_t hold_caps_until; xlist::item cap_item, flushing_cap_item; SnapRealm *snaprealm; xlist::item snaprealm_item; InodeRef snapdir_parent; // only if we are a snapdir inode map cap_snaps; // pending flush to mds //int open_by_mode[CEPH_FILE_MODE_NUM]; map open_by_mode; map cap_refs; ObjectCacher::ObjectSet oset; // ORDER DEPENDENCY: ino 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 dn_set; // if i'm linked to a dentry. string symlink; // symlink content, if it's a symlink map xattrs; map fragmap; // known frag -> mds mappings list waitfor_caps; list waitfor_commit; Dentry *get_first_parent() { assert(!dn_set.empty()); return *dn_set.begin(); } void make_long_path(filepath& p); void make_nosnap_relative_path(filepath& p); void get(); int _put(int n=1); int get_num_ref() { return _ref; } void ll_get() { ll_ref++; } void ll_put(int n=1) { assert(ll_ref >= n); ll_ref -= n; } // file locks ceph_lock_state_t *fcntl_locks; ceph_lock_state_t *flock_locks; xlist unsafe_ops; std::set fhs; 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), size(0), truncate_seq(1), truncate_size(-1), time_warp_seq(0), change_attr(0), max_size(0), version(0), xattr_version(0), inline_version(0), flags(0), dir(0), dir_release_count(1), dir_ordered_count(1), dir_hashed(false), dir_replicated(false), auth_cap(NULL), cap_dirtier_uid(-1), cap_dirtier_gid(-1), dirty_caps(0), flushing_caps(0), shared_gen(0), cache_gen(0), snap_caps(0), snap_cap_refs(0), cap_item(this), flushing_cap_item(this), 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) { memset(&dir_layout, 0, sizeof(dir_layout)); memset("a, 0, sizeof(quota)); } ~Inode(); vinodeno_t vino() const { return vinodeno_t(ino, snapid); } struct Compare { bool operator() (Inode* const & left, Inode* const & right) { if (left->ino.val < right->ino.val) { return (left->snapid.val < right->snapid.val); } return false; } }; bool check_mode(const UserPerm& perms, unsigned want); // CAPS -------- void get_open_ref(int mode); bool put_open_ref(int mode); void get_cap_ref(int cap); int put_cap_ref(int cap); bool is_any_caps(); bool cap_is_valid(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); int caps_used(); int caps_file_wanted(); int caps_wanted(); int caps_mds_wanted(); int caps_dirty(); const UserPerm *get_best_perms(); bool have_valid_size(); Dir *open_dir(); void add_fh(Fh *f) {fhs.insert(f);} void rm_fh(Fh *f) {fhs.erase(f);} void set_async_err(int r); void dump(Formatter *f) const; }; ostream& operator<<(ostream &out, const Inode &in); #endif