md_config_t g_conf;
bool g_daemon = false;
+
#include <stdlib.h>
#include <string.h>
OPTION(mds_early_reply, 0, OPT_BOOL, true),
OPTION(mds_short_reply_trace, 0, OPT_BOOL, true),
OPTION(mds_use_tmap, 0, OPT_BOOL, true), // use trivialmap for dir updates
+ OPTION(mds_default_dir_hash, 0, OPT_INT, CEPH_STR_HASH_RJENKINS),
OPTION(mds_log, 0, OPT_BOOL, true),
OPTION(mds_log_unsafe, 0, OPT_BOOL, false), // only wait for log sync, when it's mostly safe to do so
OPTION(mds_log_skip_corrupt_events, 0, OPT_BOOL, false),
bool mds_use_tmap;
+ int mds_default_dir_hash;
+
bool mds_log;
bool mds_log_unsafe;
bool mds_log_skip_corrupt_events;
__le32 fl_stripe_count; /* over this many objects */
__le32 fl_object_size; /* until objects are this big, then move to
new objects */
- __le32 fl_cas_hash; /* 0 = none; 1 = sha256 */
+ __le32 fl_cas_hash; /* UNUSED. 0 = none; 1 = sha256 */
/* pg -> disk layout */
- __le32 fl_object_stripe_unit; /* for per-object parity, if any */
+ __le32 fl_object_stripe_unit; /* UNUSED. for per-object parity, if any */
/* object -> pg layout */
__le32 fl_pg_preferred; /* preferred primary for pg (-1 for none) */
int ceph_file_layout_is_valid(const struct ceph_file_layout *layout);
+struct ceph_dir_layout {
+ __u8 dl_dir_hash; /* see ceph_hash.h for ids */
+ __u8 dl_unused1;
+ __u16 dl_unused2;
+ __u32 dl_unused3;
+} __attribute__ ((packed));
/* crypto algorithms */
#define CEPH_CRYPTO_NONE 0x0
WRITE_RAW_ENCODER(ceph_fsid)
WRITE_RAW_ENCODER(ceph_file_layout)
+WRITE_RAW_ENCODER(ceph_dir_layout)
WRITE_RAW_ENCODER(ceph_pg_pool)
WRITE_RAW_ENCODER(ceph_mds_session_head)
WRITE_RAW_ENCODER(ceph_mds_request_head)
Anchor() : dn_hash(0), nref(0), updated(0) {}
Anchor(inodeno_t i, inodeno_t di, __u32 hash, int nr, version_t u) :
ino(i), dirino(di), dn_hash(hash), nref(nr), updated(u) { }
- Anchor(inodeno_t i, inodeno_t di, const string &dname, int nr, version_t u) :
- ino(i), dirino(di),
- dn_hash(ceph_str_hash_linux(dname.data(), dname.length())),
- nref(nr), updated(u) { }
void encode(bufferlist &bl) const {
__u8 struct_v = 1;
dir->inode->make_anchor_trace(trace);
// add this inode (in my dirfrag) to the end
- trace.push_back(Anchor(in->ino(), dir->ino(), name, 0, 0));
+ trace.push_back(Anchor(in->ino(), dir->ino(), get_hash(), 0, 0));
dout(10) << "make_anchor_trace added " << trace.back() << dendl;
}
public:
string name;
+ __u32 hash;
snapid_t first, last;
dentry_key_t key() {
public:
// cons
- CDentry(const string& n,
+ CDentry(const string& n, __u32 h,
snapid_t f, snapid_t l) :
- name(n),
+ name(n), hash(h),
first(f), last(l),
dir(0),
version(0), projected_version(0),
g_num_dn++;
g_num_dna++;
}
- CDentry(const string& n, inodeno_t ino, unsigned char dt,
+ CDentry(const string& n, __u32 h, inodeno_t ino, unsigned char dt,
snapid_t f, snapid_t l) :
- name(n),
+ name(n), hash(h),
first(f), last(l),
dir(0),
version(0), projected_version(0),
CDir *get_dir() const { return dir; }
const string& get_name() const { return name; }
+ __u32 get_hash() const { return hash; }
+
/*
CInode *get_inode() const { return linkage.inode; }
inodeno_t get_remote_ino() { return linkage.remote_ino; }
assert(lookup_exact_snap(dname, last) == 0);
// create dentry
- CDentry* dn = new CDentry(dname, first, last);
+ CDentry* dn = new CDentry(dname, inode->hash_dentry_name(dname), first, last);
if (is_auth())
dn->state_set(CDentry::STATE_AUTH);
cache->lru.lru_insert_mid(dn);
assert(lookup_exact_snap(dname, last) == 0);
// create dentry
- CDentry* dn = new CDentry(dname, first, last);
+ CDentry* dn = new CDentry(dname, inode->hash_dentry_name(dname), first, last);
if (is_auth())
dn->state_set(CDentry::STATE_AUTH);
cache->lru.lru_insert_mid(dn);
{
// foreign
assert(lookup_exact_snap(dname, last) == 0);
-
+
// create dentry
- CDentry* dn = new CDentry(dname, ino, d_type, first, last);
+ CDentry* dn = new CDentry(dname, inode->hash_dentry_name(dname), ino, d_type, first, last);
if (is_auth())
dn->state_set(CDentry::STATE_AUTH);
cache->lru.lru_insert_mid(dn);
// dirfrags
+__u32 CInode::hash_dentry_name(const string &dn)
+{
+ int which = inode.dir_layout.dl_dir_hash;
+ if (!which)
+ which = CEPH_STR_HASH_LINUX;
+ return ceph_str_hash(which, dn.data(), dn.length());
+}
+
frag_t CInode::pick_dirfrag(const string& dn)
{
if (dirfragtree.empty())
return frag_t(); // avoid the string hash if we can.
- __u32 h = ceph_str_hash_linux(dn.data(), dn.length());
+ __u32 h = hash_dentry_name(dn);
return dirfragtree[h];
}
int stickydir_ref;
public:
+ __u32 hash_dentry_name(const string &dn);
frag_t pick_dirfrag(const string &dn);
bool has_dirfrags() { return !dirfrags.empty(); }
CDir* get_dirfrag(frag_t fg) {
in->make_anchor_trace(trace);
if (!trace.size()) {
assert(MDS_INO_IS_BASE(in->ino()));
- trace.push_back(Anchor(in->ino(), in->ino(), "", 0, 0));
+ trace.push_back(Anchor(in->ino(), in->ino(), 0, 0, 0));
}
// do it
in->inode.version = 1;
in->inode.nlink = 1; // FIXME
+
+ memset(&in->inode.dir_layout, 0, sizeof(in->inode.dir_layout));
+ if (in->inode.is_dir())
+ in->inode.dir_layout.dl_dir_hash = g_conf.mds_default_dir_hash;
+
if (layout)
in->inode.layout = *layout;
else if (in->inode.is_dir())
bool anchored; // auth only?
// file (data access)
+ ceph_dir_layout dir_layout; // [dir only]
ceph_file_layout layout;
uint64_t size; // on directory, # dentries
uint32_t truncate_seq;
}
void encode(bufferlist &bl) const {
- __u8 v = 3;
+ __u8 v = 4;
::encode(v, bl);
::encode(ino, bl);
::encode(nlink, bl);
::encode(anchored, bl);
+ ::encode(dir_layout, bl);
::encode(layout, bl);
::encode(size, bl);
::encode(truncate_seq, bl);
::decode(nlink, p);
::decode(anchored, p);
+ if (v >= 4)
+ ::decode(dir_layout, p);
+ else
+ memset(&dir_layout, 0, sizeof(dir_layout));
::decode(layout, p);
::decode(size, p);
::decode(truncate_seq, p);