mds mustfix
- rollback vs accounting is just broken! can we avoid it.
- even with _just_ parent dir mtime, the rollback metablob isn't sufficient during replay.. we need special handling regardless.
-- when renaming a dir, how do we know if we need to update the anchor table?
-- anchor records need to include the dentry hash
- - adjust conditional guard on anchor table updates accordingly (i.e., update table even if in same dir)
+
- anchor_destroy needs to xlock linklock.. which means it needs a Mutation wrapper?
+ - ... when it gets a caller.. someday..
- fix rm -r vs mds exports
- use new dir size values in dirstat
/* Compute the hash for a name string. */
static inline unsigned int
-ceph_full_name_hash(const unsigned char *name, unsigned int len)
+ceph_full_name_hash(const char *name, unsigned int len)
{
unsigned long hash = ceph_init_name_hash();
while (len--)
.release = ceph_socket_destroy,
};
-struct ceph_socket *ceph_socket_create()
+static struct ceph_socket *ceph_socket_create(void)
{
struct ceph_socket *s;
int err;
int ceph_workqueue_init(void);
void ceph_workqueue_shutdown(void);
-extern struct ceph_socket *ceph_socket_create(void);
extern void ceph_socket_get(struct ceph_socket *s);
extern void ceph_socket_put(struct ceph_socket *s, int die);
class Anchor {
public:
inodeno_t ino; // anchored ino
- dirfrag_t dirfrag; // containing dirfrag
- //string ref_dn; // referring dentry
+ inodeno_t dirino;
+ __u32 dn_hash;
int nref; // reference count
- Anchor() : nref(0) {}
- Anchor(inodeno_t i, dirfrag_t df,
- //string& rd,
- int nr=0) :
- ino(i), dirfrag(df),
- //ref_dn(rd),
+ Anchor() : dn_hash(0), nref(0) {}
+ Anchor(inodeno_t i, inodeno_t di, __u32 hash, int nr=0) :
+ ino(i), dirino(di), dn_hash(hash), nref(nr) { }
+ Anchor(inodeno_t i, inodeno_t di, const string &dname, int nr=0) :
+ ino(i), dirino(di),
+ dn_hash(ceph_full_name_hash(dname.data(), dname.length())),
nref(nr) { }
void encode(bufferlist &bl) const {
::encode(ino, bl);
- ::encode(dirfrag, bl);
+ ::encode(dirino, bl);
+ ::encode(dn_hash, bl);
::encode(nref, bl);
}
void decode(bufferlist::iterator &bl) {
::decode(ino, bl);
- ::decode(dirfrag, bl);
+ ::decode(dirino, bl);
+ ::decode(dn_hash, bl);
::decode(nref, bl);
}
};
WRITE_CLASS_ENCODER(Anchor)
-inline ostream& operator<<(ostream& out, Anchor& a)
+inline ostream& operator<<(ostream& out, const Anchor &a)
{
- return out << "a(" << a.ino << " " << a.dirfrag << " " << a.nref << ")";
+ return out << "a(" << a.ino << " " << a.dirino << "/" << a.dn_hash << " " << a.nref << ")";
}
#endif
* basic updates
*/
-bool AnchorTable::add(inodeno_t ino, dirfrag_t dirfrag)
+bool AnchorTable::add(inodeno_t ino, inodeno_t dirino, __u32 dn_hash)
{
//dout(17) << "add " << ino << " dirfrag " << dirfrag << dendl;
// parent should be there
- assert(dirfrag.ino < MDS_INO_BASE || // system dirino
- anchor_map.count(dirfrag.ino)); // have
+ assert(dirino < MDS_INO_BASE || // base case,
+ anchor_map.count(dirino)); // or have it
if (anchor_map.count(ino) == 0) {
// new item
- anchor_map[ino] = Anchor(ino, dirfrag);
+ anchor_map[ino] = Anchor(ino, dirino, dn_hash);
dout(7) << "add added " << anchor_map[ino] << dendl;
return true;
} else {
anchor.nref++;
dout(10) << "inc now " << anchor << dendl;
- ino = anchor.dirfrag.ino;
+ ino = anchor.dirino;
if (ino == 0) break;
if (anchor_map.count(ino) == 0) break;
if (anchor.nref == 0) {
dout(10) << "dec removing " << anchor << dendl;
- dirfrag_t dirfrag = anchor.dirfrag;
+ inodeno_t dirino = anchor.dirino;
anchor_map.erase(ino);
- ino = dirfrag.ino;
+ ino = dirino;
} else {
dout(10) << "dec now " << anchor << dendl;
- ino = anchor.dirfrag.ino;
+ ino = anchor.dirino;
}
if (ino == 0) break;
dout(10) << "handle_lookup adding " << anchor << dendl;
trace.insert(trace.begin(), anchor); // lame FIXME
- if (anchor.dirfrag.ino < MDS_INO_BASE) break;
- curino = anchor.dirfrag.ino;
+ if (anchor.dirino < MDS_INO_BASE) break;
+ curino = anchor.dirino;
}
// reply
{
// make sure trace is in table
for (unsigned i=0; i<trace.size(); i++)
- add(trace[i].ino, trace[i].dirfrag);
+ add(trace[i].ino, trace[i].dirino, trace[i].dn_hash);
inc(ino);
version++;
// add new
for (unsigned i=0; i<trace.size(); i++)
- add(trace[i].ino, trace[i].dirfrag);
+ add(trace[i].ino, trace[i].dirino, trace[i].dn_hash);
inc(ino);
} else {
dout(7) << "commit " << atid << " update " << ino << " -- DNE" << dendl;
protected:
// basic updates
- bool add(inodeno_t ino, dirfrag_t dirfrag);
+ bool add(inodeno_t ino, inodeno_t dirino, __u32 dn_hash);
void inc(inodeno_t ino);
void dec(inodeno_t ino);
dir->inode->make_anchor_trace(trace);
// add this inode (in my dirfrag) to the end
- trace.push_back(Anchor(in->ino(), dir->dirfrag()));
+ trace.push_back(Anchor(in->ino(), dir->ino(), name));
dout(10) << "make_anchor_trace added " << trace.back() << dendl;
}
if (dirfragtree.empty())
return frag_t(); // avoid the string hash if we can.
- __u32 h = ceph_full_name_hash((const unsigned char *)dn.data(), dn.length());
+ __u32 h = ceph_full_name_hash(dn.data(), dn.length());
return dirfragtree[h*h];
}
void CInode::make_anchor_trace(vector<Anchor>& trace)
{
- if (parent) {
- parent->dir->inode->make_anchor_trace(trace);
- trace.push_back(Anchor(ino(), parent->dir->dirfrag()));
- dout(10) << "make_anchor_trace added " << trace.back() << dendl;
- }
+ if (parent)
+ parent->make_anchor_trace(trace, this);
else
assert(is_root() || is_stray());
}
if (in) break;
i--;
if (!i) {
- in = get_inode(anchortrace[i].dirfrag.ino);
+ in = get_inode(anchortrace[i].dirino);
if (!in) {
- dout(0) << "open_remote_ino_2 don't have inode " << anchortrace[i].dirfrag.ino << dendl;
- if (anchortrace[i].dirfrag.ino == MDS_INO_ROOT) {
+ dout(0) << "open_remote_ino_2 don't have dir inode " << anchortrace[i].dirino << dendl;
+ if (anchortrace[i].dirino == MDS_INO_ROOT) {
open_root(onfinish);
return;
}
- if (MDS_INO_IS_STRAY(anchortrace[i].dirfrag.ino)) {
- int mds = anchortrace[i].dirfrag.ino % MAX_MDS;
+ if (MDS_INO_IS_STRAY(anchortrace[i].dirino)) {
+ int mds = anchortrace[i].dirino % MAX_MDS;
open_foreign_stray(mds, onfinish);
return;
}
}
// open dirfrag beneath *in
- frag_t frag = anchortrace[i].dirfrag.frag;
+ frag_t frag = in->dirfragtree[anchortrace[i].dn_hash];
if (!in->dirfragtree.contains(frag)) {
dout(10) << "frag " << frag << " not valid, requerying anchortable" << dendl;
if (!dir && !in->is_auth()) {
dout(10) << "opening remote dirfrag " << frag << " under " << *in << dendl;
- /* FIXME: we re-query the anchortable just to avoid a fragtree update race */
+ /* we re-query the anchortable just to avoid a fragtree update race */
open_remote_dirfrag(in, frag,
new C_MDC_RetryOpenRemoteIno(this, ino, mdr, onfinish));
return;