initial code repo
[stor4nfv.git] / src / ceph / src / mds / CDentry.h
diff --git a/src/ceph/src/mds/CDentry.h b/src/ceph/src/mds/CDentry.h
new file mode 100644 (file)
index 0000000..e941610
--- /dev/null
@@ -0,0 +1,382 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- 
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software 
+ * Foundation.  See file COPYING.
+ * 
+ */
+
+
+
+#ifndef CEPH_CDENTRY_H
+#define CEPH_CDENTRY_H
+
+#include <string>
+#include <set>
+
+#include "include/counter.h"
+#include "include/types.h"
+#include "include/buffer_fwd.h"
+#include "include/lru.h"
+#include "include/elist.h"
+#include "include/filepath.h"
+
+#include "MDSCacheObject.h"
+#include "SimpleLock.h"
+#include "LocalLock.h"
+#include "ScrubHeader.h"
+
+class CInode;
+class CDir;
+class Locker;
+class Message;
+class CDentry;
+class LogSegment;
+
+class Session;
+
+
+
+// define an ordering
+bool operator<(const CDentry& l, const CDentry& r);
+
+// dentry
+class CDentry : public MDSCacheObject, public LRUObject, public Counter<CDentry> {
+public:
+  MEMPOOL_CLASS_HELPERS();
+  friend class CDir;
+
+  struct linkage_t {
+    CInode *inode;
+    inodeno_t remote_ino;
+    unsigned char remote_d_type;
+    
+    linkage_t() : inode(0), remote_ino(0), remote_d_type(0) {}
+
+    // dentry type is primary || remote || null
+    // inode ptr is required for primary, optional for remote, undefined for null
+    bool is_primary() const { return remote_ino == 0 && inode != 0; }
+    bool is_remote() const { return remote_ino > 0; }
+    bool is_null() const { return remote_ino == 0 && inode == 0; }
+
+    CInode *get_inode() { return inode; }
+    const CInode *get_inode() const { return inode; }
+    inodeno_t get_remote_ino() const { return remote_ino; }
+    unsigned char get_remote_d_type() const { return remote_d_type; }
+    std::string get_remote_d_type_string() const;
+
+    void set_remote(inodeno_t ino, unsigned char d_type) { 
+      remote_ino = ino;
+      remote_d_type = d_type;
+      inode = 0;
+    }
+    void link_remote(CInode *in);
+  };
+
+
+  // -- state --
+  static const int STATE_NEW =          (1<<0);
+  static const int STATE_FRAGMENTING =  (1<<1);
+  static const int STATE_PURGING =      (1<<2);
+  static const int STATE_BADREMOTEINO = (1<<3);
+  static const int STATE_EVALUATINGSTRAY = (1<<4);
+  static const int STATE_PURGINGPINNED =  (1<<5);
+  static const int STATE_BOTTOMLRU =    (1<<6);
+  // stray dentry needs notification of releasing reference
+  static const int STATE_STRAY =       STATE_NOTIFYREF;
+  static const int MASK_STATE_IMPORT_KEPT = STATE_BOTTOMLRU;
+
+  // -- pins --
+  static const int PIN_INODEPIN =     1;  // linked inode is pinned
+  static const int PIN_FRAGMENTING = -2;  // containing dir is refragmenting
+  static const int PIN_PURGING =      3;
+  static const int PIN_SCRUBPARENT =  4;
+
+  static const unsigned EXPORT_NONCE = 1;
+
+
+  CDentry(const std::string& n, __u32 h,
+         snapid_t f, snapid_t l) :
+    name(n), hash(h),
+    first(f), last(l),
+    item_dirty(this),
+    lock(this, &lock_type),
+    versionlock(this, &versionlock_type),
+    dir(0),
+    version(0), projected_version(0) {
+  }
+  CDentry(const std::string& n, __u32 h, inodeno_t ino, unsigned char dt,
+         snapid_t f, snapid_t l) :
+    name(n), hash(h),
+    first(f), last(l),
+    item_dirty(this),
+    lock(this, &lock_type),
+    versionlock(this, &versionlock_type),
+    dir(0),
+    version(0), projected_version(0) {
+    linkage.remote_ino = ino;
+    linkage.remote_d_type = dt;
+  }
+
+  const char *pin_name(int p) const override {
+    switch (p) {
+    case PIN_INODEPIN: return "inodepin";
+    case PIN_FRAGMENTING: return "fragmenting";
+    case PIN_PURGING: return "purging";
+    case PIN_SCRUBPARENT: return "scrubparent";
+    default: return generic_pin_name(p);
+    }
+  }
+
+  // -- wait --
+  //static const int WAIT_LOCK_OFFSET = 8;
+
+  void add_waiter(uint64_t tag, MDSInternalContextBase *c) override;
+
+  bool is_lt(const MDSCacheObject *r) const override {
+    return *this < *static_cast<const CDentry*>(r);
+  }
+
+  dentry_key_t key() {
+    return dentry_key_t(last, name.c_str(), hash);
+  }
+
+  const CDir *get_dir() const { return dir; }
+  CDir *get_dir() { return dir; }
+  const std::string& get_name() const { return name; }
+
+  __u32 get_hash() const { return hash; }
+
+  // linkage
+  const linkage_t *get_linkage() const { return &linkage; }
+  linkage_t *get_linkage() { return &linkage; }
+
+  linkage_t *_project_linkage() {
+    projected.push_back(linkage_t());
+    return &projected.back();
+  }
+  void push_projected_linkage();
+  void push_projected_linkage(inodeno_t ino, char d_type) {
+    linkage_t *p = _project_linkage();
+    p->remote_ino = ino;
+    p->remote_d_type = d_type;
+  }
+  void push_projected_linkage(CInode *inode); 
+  linkage_t *pop_projected_linkage();
+
+  bool is_projected() const { return !projected.empty(); }
+
+  linkage_t *get_projected_linkage() {
+    if (!projected.empty())
+      return &projected.back();
+    return &linkage;
+  }
+
+  const linkage_t *get_projected_linkage() const {
+    if (!projected.empty())
+      return &projected.back();
+    return &linkage;
+  }
+
+  CInode *get_projected_inode() {
+    return get_projected_linkage()->inode;
+  }
+
+  bool use_projected(client_t client, const MutationRef& mut) const {
+    return lock.can_read_projected(client) || 
+      lock.get_xlock_by() == mut;
+  }
+  linkage_t *get_linkage(client_t client, const MutationRef& mut) {
+    return use_projected(client, mut) ? get_projected_linkage() : get_linkage();
+  }
+
+  // ref counts: pin ourselves in the LRU when we're pinned.
+  void first_get() override {
+    lru_pin();
+  }
+  void last_put() override {
+    lru_unpin();
+  }
+  void _put() override;
+
+  // auth pins
+  bool can_auth_pin() const override;
+  void auth_pin(void *by) override;
+  void auth_unpin(void *by) override;
+  void adjust_nested_auth_pins(int adjustment, int diradj, void *by);
+  bool is_frozen() const override;
+  bool is_freezing() const override;
+  int get_num_dir_auth_pins() const;
+  
+  // remote links
+  void link_remote(linkage_t *dnl, CInode *in);
+  void unlink_remote(linkage_t *dnl);
+  
+  // copy cons
+  CDentry(const CDentry& m);
+  const CDentry& operator= (const CDentry& right);
+
+  // misc
+  void make_path_string(std::string& s, bool projected=false) const;
+  void make_path(filepath& fp, bool projected=false) const;
+
+  // -- version --
+  version_t get_version() const { return version; }
+  void set_version(version_t v) { projected_version = version = v; }
+  version_t get_projected_version() const { return projected_version; }
+  void set_projected_version(version_t v) { projected_version = v; }
+  
+  mds_authority_t authority() const override;
+
+  version_t pre_dirty(version_t min=0);
+  void _mark_dirty(LogSegment *ls);
+  void mark_dirty(version_t projected_dirv, LogSegment *ls);
+  void mark_clean();
+
+  void mark_new();
+  bool is_new() const { return state_test(STATE_NEW); }
+  void clear_new() { state_clear(STATE_NEW); }
+  
+  // -- replication
+  void encode_replica(mds_rank_t mds, bufferlist& bl) {
+    if (!is_replicated())
+      lock.replicate_relax();
+
+    __u32 nonce = add_replica(mds);
+    ::encode(nonce, bl);
+    ::encode(first, bl);
+    ::encode(linkage.remote_ino, bl);
+    ::encode(linkage.remote_d_type, bl);
+    __s32 ls = lock.get_replica_state();
+    ::encode(ls, bl);
+  }
+  void decode_replica(bufferlist::iterator& p, bool is_new);
+
+  // -- exporting
+  // note: this assumes the dentry already exists.  
+  // i.e., the name is already extracted... so we just need the other state.
+  void encode_export(bufferlist& bl) {
+    ::encode(first, bl);
+    ::encode(state, bl);
+    ::encode(version, bl);
+    ::encode(projected_version, bl);
+    ::encode(lock, bl);
+    ::encode(get_replicas(), bl);
+    get(PIN_TEMPEXPORTING);
+  }
+  void finish_export() {
+    // twiddle
+    clear_replica_map();
+    replica_nonce = EXPORT_NONCE;
+    state_clear(CDentry::STATE_AUTH);
+    if (is_dirty())
+      mark_clean();
+    put(PIN_TEMPEXPORTING);
+  }
+  void abort_export() {
+    put(PIN_TEMPEXPORTING);
+  }
+  void decode_import(bufferlist::iterator& blp, LogSegment *ls) {
+    ::decode(first, blp);
+    __u32 nstate;
+    ::decode(nstate, blp);
+    ::decode(version, blp);
+    ::decode(projected_version, blp);
+    ::decode(lock, blp);
+    ::decode(get_replicas(), blp);
+
+    // twiddle
+    state &= MASK_STATE_IMPORT_KEPT;
+    state_set(CDentry::STATE_AUTH);
+    if (nstate & STATE_DIRTY)
+      _mark_dirty(ls);
+    if (is_replicated())
+      get(PIN_REPLICATED);
+    replica_nonce = 0;
+  }
+
+  // -- locking --
+  SimpleLock* get_lock(int type) override {
+    assert(type == CEPH_LOCK_DN);
+    return &lock;
+  }
+  void set_object_info(MDSCacheObjectInfo &info) override;
+  void encode_lock_state(int type, bufferlist& bl) override;
+  void decode_lock_state(int type, bufferlist& bl) override;
+
+  // ---------------------------------------------
+  // replicas (on clients)
+
+  bool is_any_leases() const {
+    return !client_lease_map.empty();
+  }
+  const ClientLease *get_client_lease(client_t c) const {
+    if (client_lease_map.count(c))
+      return client_lease_map.find(c)->second;
+    return 0;
+  }
+  ClientLease *get_client_lease(client_t c) {
+    if (client_lease_map.count(c))
+      return client_lease_map.find(c)->second;
+    return 0;
+  }
+  bool have_client_lease(client_t c) const {
+    const ClientLease *l = get_client_lease(c);
+    if (l) 
+      return true;
+    else
+      return false;
+  }
+
+  ClientLease *add_client_lease(client_t c, Session *session);
+  void remove_client_lease(ClientLease *r, Locker *locker);  // returns remaining mask (if any), and kicks locker eval_gathers
+  void remove_client_leases(Locker *locker);
+
+  ostream& print_db_line_prefix(ostream& out) override;
+  void print(ostream& out) override;
+  void dump(Formatter *f) const;
+
+
+  std::string name;
+  __u32 hash;
+  snapid_t first, last;
+
+  elist<CDentry*>::item item_dirty;
+  elist<CDentry*>::item item_stray;
+
+  // lock
+  static LockType lock_type;
+  static LockType versionlock_type;
+
+  SimpleLock lock;
+  LocalLock versionlock;
+
+  map<client_t,ClientLease*> client_lease_map;
+
+
+protected:
+  friend class Migrator;
+  friend class Locker;
+  friend class MDCache;
+  friend class StrayManager;
+  friend class CInode;
+  friend class C_MDC_XlockRequest;
+
+  CDir *dir;     // containing dirfrag
+  linkage_t linkage;
+  list<linkage_t> projected;
+
+  version_t version;  // dir version when last touched.
+  version_t projected_version;  // what it will be when i unlock/commit.
+};
+
+ostream& operator<<(ostream& out, const CDentry& dn);
+
+
+#endif