]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/client/Inode.h
import ceph 15.2.14
[ceph.git] / ceph / src / client / Inode.h
index 63a7f50aa517829e6aad6102945e5de857b3d6b5..faa2c894dc52fce39305306ceaf31f4b987dde29 100644 (file)
@@ -6,48 +6,71 @@
 
 #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 {
@@ -72,20 +95,26 @@ 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;
@@ -129,12 +158,13 @@ struct Inode {
   // 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; }
@@ -147,7 +177,7 @@ struct Inode {
     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());
   }
 
@@ -163,12 +193,11 @@ struct Inode {
   // 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;
@@ -193,22 +222,23 @@ struct Inode {
   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();
@@ -221,14 +251,20 @@ struct Inode {
   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;
 
@@ -236,6 +272,8 @@ struct Inode {
 
   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),
@@ -251,8 +289,7 @@ struct Inode {
       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));
   }
@@ -278,9 +315,8 @@ struct Inode {
   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();