mirror of
https://github.com/ceph/ceph
synced 2024-12-14 23:46:28 +00:00
mds: move Mutation + children out of MDCache.h
Uninline while we're at it. Signed-off-by: Sage Weil <sage@newdream.net>
This commit is contained in:
parent
c46430fb33
commit
c975bb8815
@ -889,6 +889,7 @@ libmds_a_SOURCES = \
|
||||
mds/locks.c \
|
||||
mds/journal.cc \
|
||||
mds/Server.cc \
|
||||
mds/Mutation.cc \
|
||||
mds/MDCache.cc \
|
||||
mds/Locker.cc \
|
||||
mds/Migrator.cc \
|
||||
@ -1145,6 +1146,7 @@ noinst_HEADERS = \
|
||||
mds/MDSTable.h\
|
||||
mds/MDSTableServer.h\
|
||||
mds/MDSTableClient.h\
|
||||
mds/Mutation.h\
|
||||
mds/Migrator.h\
|
||||
mds/Resetter.h\
|
||||
mds/ScatterLock.h\
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "CDir.h"
|
||||
#include "CDentry.h"
|
||||
#include "CInode.h"
|
||||
#include "Mutation.h"
|
||||
|
||||
#include "MDSMap.h"
|
||||
#include "MDS.h"
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "MDCache.h"
|
||||
#include "MDLog.h"
|
||||
#include "Locker.h"
|
||||
#include "Mutation.h"
|
||||
|
||||
#include "events/EUpdate.h"
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "CInode.h"
|
||||
#include "CDir.h"
|
||||
#include "CDentry.h"
|
||||
#include "Mutation.h"
|
||||
|
||||
#include "MDLog.h"
|
||||
#include "MDSMap.h"
|
||||
|
@ -30,6 +30,8 @@
|
||||
#include "CInode.h"
|
||||
#include "CDir.h"
|
||||
|
||||
#include "Mutation.h"
|
||||
|
||||
#include "include/ceph_fs.h"
|
||||
#include "include/filepath.h"
|
||||
|
||||
@ -10162,3 +10164,17 @@ void MDCache::dump_cache(const char *fn)
|
||||
|
||||
myfile.close();
|
||||
}
|
||||
|
||||
|
||||
|
||||
C_MDS_RetryRequest::C_MDS_RetryRequest(MDCache *c, MDRequest *r)
|
||||
: cache(c), mdr(r)
|
||||
{
|
||||
mdr->get();
|
||||
}
|
||||
|
||||
void C_MDS_RetryRequest::finish(int r)
|
||||
{
|
||||
cache->dispatch_request(mdr);
|
||||
mdr->put();
|
||||
}
|
||||
|
@ -63,368 +63,9 @@ class MMDSFragmentNotify;
|
||||
|
||||
class ESubtreeMap;
|
||||
|
||||
|
||||
// MDCache
|
||||
|
||||
struct Mutation {
|
||||
metareqid_t reqid;
|
||||
__u32 attempt; // which attempt for this request
|
||||
LogSegment *ls; // the log segment i'm committing to
|
||||
utime_t now;
|
||||
|
||||
// flag mutation as slave
|
||||
int slave_to_mds; // this is a slave request if >= 0.
|
||||
|
||||
// -- my pins and locks --
|
||||
// cache pins (so things don't expire)
|
||||
set< MDSCacheObject* > pins;
|
||||
set<CInode*> stickydirs;
|
||||
|
||||
// auth pins
|
||||
set< MDSCacheObject* > remote_auth_pins;
|
||||
set< MDSCacheObject* > auth_pins;
|
||||
|
||||
// held locks
|
||||
set< SimpleLock* > rdlocks; // always local.
|
||||
set< SimpleLock* > wrlocks; // always local.
|
||||
map< SimpleLock*, int > remote_wrlocks;
|
||||
set< SimpleLock* > xlocks; // local or remote.
|
||||
set< SimpleLock*, SimpleLock::ptr_lt > locks; // full ordering
|
||||
|
||||
// if this flag is set, do not attempt to acquire further locks.
|
||||
// (useful for wrlock, which may be a moving auth target)
|
||||
bool done_locking;
|
||||
bool committing;
|
||||
bool aborted;
|
||||
|
||||
// for applying projected inode changes
|
||||
list<CInode*> projected_inodes;
|
||||
list<CDir*> projected_fnodes;
|
||||
list<ScatterLock*> updated_locks;
|
||||
|
||||
list<CInode*> dirty_cow_inodes;
|
||||
list<pair<CDentry*,version_t> > dirty_cow_dentries;
|
||||
|
||||
Mutation() :
|
||||
attempt(0),
|
||||
ls(0),
|
||||
slave_to_mds(-1),
|
||||
done_locking(false), committing(false), aborted(false) { }
|
||||
Mutation(metareqid_t ri, __u32 att=0, int slave_to=-1) :
|
||||
reqid(ri), attempt(att),
|
||||
ls(0),
|
||||
slave_to_mds(slave_to),
|
||||
done_locking(false), committing(false), aborted(false) { }
|
||||
virtual ~Mutation() {
|
||||
assert(pins.empty());
|
||||
assert(auth_pins.empty());
|
||||
assert(xlocks.empty());
|
||||
assert(rdlocks.empty());
|
||||
assert(wrlocks.empty());
|
||||
assert(remote_wrlocks.empty());
|
||||
}
|
||||
|
||||
bool is_master() { return slave_to_mds < 0; }
|
||||
bool is_slave() { return slave_to_mds >= 0; }
|
||||
|
||||
client_t get_client() {
|
||||
if (reqid.name.is_client())
|
||||
return client_t(reqid.name.num());
|
||||
return -1;
|
||||
}
|
||||
|
||||
// pin items in cache
|
||||
void pin(MDSCacheObject *o) {
|
||||
if (pins.count(o) == 0) {
|
||||
o->get(MDSCacheObject::PIN_REQUEST);
|
||||
pins.insert(o);
|
||||
}
|
||||
}
|
||||
void set_stickydirs(CInode *in) {
|
||||
if (stickydirs.count(in) == 0) {
|
||||
in->get_stickydirs();
|
||||
stickydirs.insert(in);
|
||||
}
|
||||
}
|
||||
void drop_pins() {
|
||||
for (set<MDSCacheObject*>::iterator it = pins.begin();
|
||||
it != pins.end();
|
||||
it++)
|
||||
(*it)->put(MDSCacheObject::PIN_REQUEST);
|
||||
pins.clear();
|
||||
}
|
||||
|
||||
// auth pins
|
||||
bool is_auth_pinned(MDSCacheObject *object) {
|
||||
return auth_pins.count(object) || remote_auth_pins.count(object);
|
||||
}
|
||||
void auth_pin(MDSCacheObject *object) {
|
||||
if (!is_auth_pinned(object)) {
|
||||
object->auth_pin(this);
|
||||
auth_pins.insert(object);
|
||||
}
|
||||
}
|
||||
void auth_unpin(MDSCacheObject *object) {
|
||||
assert(auth_pins.count(object));
|
||||
object->auth_unpin(this);
|
||||
auth_pins.erase(object);
|
||||
}
|
||||
void drop_local_auth_pins() {
|
||||
for (set<MDSCacheObject*>::iterator it = auth_pins.begin();
|
||||
it != auth_pins.end();
|
||||
it++) {
|
||||
assert((*it)->is_auth());
|
||||
(*it)->auth_unpin(this);
|
||||
}
|
||||
auth_pins.clear();
|
||||
}
|
||||
|
||||
void add_projected_inode(CInode *in) {
|
||||
projected_inodes.push_back(in);
|
||||
}
|
||||
void pop_and_dirty_projected_inodes() {
|
||||
while (!projected_inodes.empty()) {
|
||||
CInode *in = projected_inodes.front();
|
||||
projected_inodes.pop_front();
|
||||
in->pop_and_dirty_projected_inode(ls);
|
||||
}
|
||||
}
|
||||
|
||||
void add_projected_fnode(CDir *dir) {
|
||||
projected_fnodes.push_back(dir);
|
||||
}
|
||||
void pop_and_dirty_projected_fnodes() {
|
||||
while (!projected_fnodes.empty()) {
|
||||
CDir *dir = projected_fnodes.front();
|
||||
projected_fnodes.pop_front();
|
||||
dir->pop_and_dirty_projected_fnode(ls);
|
||||
}
|
||||
}
|
||||
|
||||
void add_updated_lock(ScatterLock *lock) {
|
||||
updated_locks.push_back(lock);
|
||||
}
|
||||
|
||||
void add_cow_inode(CInode *in) {
|
||||
pin(in);
|
||||
dirty_cow_inodes.push_back(in);
|
||||
}
|
||||
void add_cow_dentry(CDentry *dn) {
|
||||
pin(dn);
|
||||
dirty_cow_dentries.push_back(pair<CDentry*,version_t>(dn, dn->get_projected_version()));
|
||||
}
|
||||
|
||||
void apply() {
|
||||
pop_and_dirty_projected_inodes();
|
||||
pop_and_dirty_projected_fnodes();
|
||||
|
||||
for (list<CInode*>::iterator p = dirty_cow_inodes.begin();
|
||||
p != dirty_cow_inodes.end();
|
||||
p++)
|
||||
(*p)->_mark_dirty(ls);
|
||||
for (list<pair<CDentry*,version_t> >::iterator p = dirty_cow_dentries.begin();
|
||||
p != dirty_cow_dentries.end();
|
||||
p++)
|
||||
p->first->mark_dirty(p->second, ls);
|
||||
|
||||
for (list<ScatterLock*>::iterator p = updated_locks.begin();
|
||||
p != updated_locks.end();
|
||||
p++)
|
||||
(*p)->mark_dirty();
|
||||
}
|
||||
|
||||
void cleanup() {
|
||||
drop_local_auth_pins();
|
||||
drop_pins();
|
||||
}
|
||||
|
||||
virtual void print(ostream &out) {
|
||||
out << "mutation(" << this << ")";
|
||||
}
|
||||
};
|
||||
|
||||
inline ostream& operator<<(ostream& out, Mutation &mut)
|
||||
{
|
||||
mut.print(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
/** active_request_t
|
||||
* state we track for requests we are currently processing.
|
||||
* mostly information about locks held, so that we can drop them all
|
||||
* the request is finished or forwarded. see request_*().
|
||||
*/
|
||||
struct MDRequest : public Mutation {
|
||||
int ref;
|
||||
Session *session;
|
||||
elist<MDRequest*>::item item_session_request; // if not on list, op is aborted.
|
||||
|
||||
// -- i am a client (master) request
|
||||
MClientRequest *client_request; // client request (if any)
|
||||
|
||||
// store up to two sets of dn vectors, inode pointers, for request path1 and path2.
|
||||
vector<CDentry*> dn[2];
|
||||
CDentry *straydn;
|
||||
CInode *in[2];
|
||||
snapid_t snapid;
|
||||
|
||||
CInode *tracei;
|
||||
CDentry *tracedn;
|
||||
|
||||
inodeno_t alloc_ino, used_prealloc_ino;
|
||||
interval_set<inodeno_t> prealloc_inos;
|
||||
|
||||
int snap_caps;
|
||||
bool did_early_reply;
|
||||
|
||||
// inos we did a embedded cap release on, and may need to eval if we haven't since reissued
|
||||
map<vinodeno_t, ceph_seq_t> cap_releases;
|
||||
|
||||
// -- i am a slave request
|
||||
MMDSSlaveRequest *slave_request; // slave request (if one is pending; implies slave == true)
|
||||
|
||||
// -- i am an internal op
|
||||
int internal_op;
|
||||
|
||||
// break rarely-used fields into a separately allocated structure
|
||||
// to save memory for most ops
|
||||
struct More {
|
||||
set<int> slaves; // mds nodes that have slave requests to me (implies client_request)
|
||||
set<int> waiting_on_slave; // peers i'm waiting for slavereq replies from.
|
||||
|
||||
// for rename/link/unlink
|
||||
set<int> witnessed; // nodes who have journaled a RenamePrepare
|
||||
map<MDSCacheObject*,version_t> pvmap;
|
||||
|
||||
// for rename
|
||||
set<int> extra_witnesses; // replica list from srcdn auth (rename)
|
||||
version_t src_reanchor_atid; // src->dst
|
||||
version_t dst_reanchor_atid; // dst->stray
|
||||
bufferlist inode_import;
|
||||
version_t inode_import_v;
|
||||
CInode* destdn_was_remote_inode;
|
||||
bool was_link_merge;
|
||||
|
||||
map<client_t,entity_inst_t> imported_client_map;
|
||||
map<client_t,uint64_t> sseq_map;
|
||||
map<CInode*, map<client_t,Capability::Export> > cap_imports;
|
||||
|
||||
// for lock/flock
|
||||
bool flock_was_waiting;
|
||||
|
||||
// for snaps
|
||||
version_t stid;
|
||||
bufferlist snapidbl;
|
||||
|
||||
// called when slave commits or aborts
|
||||
Context *slave_commit;
|
||||
bufferlist rollback_bl;
|
||||
|
||||
More() :
|
||||
src_reanchor_atid(0), dst_reanchor_atid(0), inode_import_v(0),
|
||||
destdn_was_remote_inode(0), was_link_merge(false),
|
||||
flock_was_waiting(false),
|
||||
stid(0),
|
||||
slave_commit(0) { }
|
||||
} *_more;
|
||||
|
||||
|
||||
// ---------------------------------------------------
|
||||
MDRequest() :
|
||||
ref(1),
|
||||
session(0), item_session_request(this),
|
||||
client_request(0), straydn(NULL), snapid(CEPH_NOSNAP), tracei(0), tracedn(0),
|
||||
alloc_ino(0), used_prealloc_ino(0), snap_caps(0), did_early_reply(false),
|
||||
slave_request(0),
|
||||
internal_op(-1),
|
||||
_more(0) {
|
||||
in[0] = in[1] = 0;
|
||||
}
|
||||
MDRequest(metareqid_t ri, __u32 attempt, MClientRequest *req) :
|
||||
Mutation(ri, attempt),
|
||||
ref(1),
|
||||
session(0), item_session_request(this),
|
||||
client_request(req), straydn(NULL), snapid(CEPH_NOSNAP), tracei(0), tracedn(0),
|
||||
alloc_ino(0), used_prealloc_ino(0), snap_caps(0), did_early_reply(false),
|
||||
slave_request(0),
|
||||
internal_op(-1),
|
||||
_more(0) {
|
||||
in[0] = in[1] = 0;
|
||||
}
|
||||
MDRequest(metareqid_t ri, __u32 attempt, int by) :
|
||||
Mutation(ri, attempt, by),
|
||||
ref(1),
|
||||
session(0), item_session_request(this),
|
||||
client_request(0), straydn(NULL), snapid(CEPH_NOSNAP), tracei(0), tracedn(0),
|
||||
alloc_ino(0), used_prealloc_ino(0), snap_caps(0), did_early_reply(false),
|
||||
slave_request(0),
|
||||
internal_op(-1),
|
||||
_more(0) {
|
||||
in[0] = in[1] = 0;
|
||||
}
|
||||
~MDRequest() {
|
||||
if (client_request)
|
||||
client_request->put();
|
||||
if (slave_request)
|
||||
slave_request->put();
|
||||
delete _more;
|
||||
}
|
||||
|
||||
MDRequest *get() {
|
||||
++ref;
|
||||
return this;
|
||||
}
|
||||
void put() {
|
||||
if (--ref == 0)
|
||||
delete this;
|
||||
}
|
||||
|
||||
More* more() {
|
||||
if (!_more) _more = new More();
|
||||
return _more;
|
||||
}
|
||||
|
||||
bool are_slaves() {
|
||||
return _more && !_more->slaves.empty();
|
||||
}
|
||||
|
||||
bool slave_did_prepare() { return more()->slave_commit; }
|
||||
|
||||
bool did_ino_allocation() {
|
||||
return alloc_ino || used_prealloc_ino || prealloc_inos.size();
|
||||
}
|
||||
|
||||
void print(ostream &out) {
|
||||
out << "request(" << reqid;
|
||||
//if (request) out << " " << *request;
|
||||
if (is_slave()) out << " slave_to mds" << slave_to_mds;
|
||||
if (client_request) out << " cr=" << client_request;
|
||||
if (slave_request) out << " sr=" << slave_request;
|
||||
out << ")";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct MDSlaveUpdate {
|
||||
int origop;
|
||||
bufferlist rollback;
|
||||
elist<MDSlaveUpdate*>::item item;
|
||||
Context *waiter;
|
||||
MDSlaveUpdate(int oo, bufferlist &rbl, elist<MDSlaveUpdate*> &list) :
|
||||
origop(oo),
|
||||
item(this),
|
||||
waiter(0) {
|
||||
rollback.claim(rbl);
|
||||
list.push_back(&item);
|
||||
}
|
||||
~MDSlaveUpdate() {
|
||||
item.remove_myself();
|
||||
if (waiter)
|
||||
waiter->finish(0);
|
||||
delete waiter;
|
||||
}
|
||||
};
|
||||
class Mutation;
|
||||
class MDRequest;
|
||||
class MDSlaveUpdate;
|
||||
|
||||
|
||||
// flags for predirty_journal_parents()
|
||||
@ -432,8 +73,6 @@ static const int PREDIRTY_PRIMARY = 1; // primary dn, adjust nested accounting
|
||||
static const int PREDIRTY_DIR = 2; // update parent dir mtime/size
|
||||
static const int PREDIRTY_SHALLOW = 4; // only go to immediate parent (for easier rollback)
|
||||
|
||||
|
||||
|
||||
class MDCache {
|
||||
public:
|
||||
// my master
|
||||
@ -1268,13 +907,8 @@ class C_MDS_RetryRequest : public Context {
|
||||
MDCache *cache;
|
||||
MDRequest *mdr;
|
||||
public:
|
||||
C_MDS_RetryRequest(MDCache *c, MDRequest *r) : cache(c), mdr(r) {
|
||||
mdr->get();
|
||||
}
|
||||
virtual void finish(int r) {
|
||||
cache->dispatch_request(mdr);
|
||||
mdr->put();
|
||||
}
|
||||
C_MDS_RetryRequest(MDCache *c, MDRequest *r);
|
||||
virtual void finish(int r);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
196
src/mds/Mutation.cc
Normal file
196
src/mds/Mutation.cc
Normal file
@ -0,0 +1,196 @@
|
||||
// -*- 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "Mutation.h"
|
||||
#include "ScatterLock.h"
|
||||
#include "CDir.h"
|
||||
|
||||
#include "messages/MClientRequest.h"
|
||||
#include "messages/MMDSSlaveRequest.h"
|
||||
|
||||
|
||||
// Mutation
|
||||
|
||||
void Mutation::pin(MDSCacheObject *o)
|
||||
{
|
||||
if (pins.count(o) == 0) {
|
||||
o->get(MDSCacheObject::PIN_REQUEST);
|
||||
pins.insert(o);
|
||||
}
|
||||
}
|
||||
|
||||
void Mutation::set_stickydirs(CInode *in)
|
||||
{
|
||||
if (stickydirs.count(in) == 0) {
|
||||
in->get_stickydirs();
|
||||
stickydirs.insert(in);
|
||||
}
|
||||
}
|
||||
|
||||
void Mutation::drop_pins()
|
||||
{
|
||||
for (set<MDSCacheObject*>::iterator it = pins.begin();
|
||||
it != pins.end();
|
||||
it++)
|
||||
(*it)->put(MDSCacheObject::PIN_REQUEST);
|
||||
pins.clear();
|
||||
}
|
||||
|
||||
// auth pins
|
||||
bool Mutation::is_auth_pinned(MDSCacheObject *object)
|
||||
{
|
||||
return auth_pins.count(object) || remote_auth_pins.count(object);
|
||||
}
|
||||
|
||||
void Mutation::auth_pin(MDSCacheObject *object)
|
||||
{
|
||||
if (!is_auth_pinned(object)) {
|
||||
object->auth_pin(this);
|
||||
auth_pins.insert(object);
|
||||
}
|
||||
}
|
||||
|
||||
void Mutation::auth_unpin(MDSCacheObject *object)
|
||||
{
|
||||
assert(auth_pins.count(object));
|
||||
object->auth_unpin(this);
|
||||
auth_pins.erase(object);
|
||||
}
|
||||
|
||||
void Mutation::drop_local_auth_pins()
|
||||
{
|
||||
for (set<MDSCacheObject*>::iterator it = auth_pins.begin();
|
||||
it != auth_pins.end();
|
||||
it++) {
|
||||
assert((*it)->is_auth());
|
||||
(*it)->auth_unpin(this);
|
||||
}
|
||||
auth_pins.clear();
|
||||
}
|
||||
|
||||
void Mutation::add_projected_inode(CInode *in)
|
||||
{
|
||||
projected_inodes.push_back(in);
|
||||
}
|
||||
|
||||
void Mutation::pop_and_dirty_projected_inodes()
|
||||
{
|
||||
while (!projected_inodes.empty()) {
|
||||
CInode *in = projected_inodes.front();
|
||||
projected_inodes.pop_front();
|
||||
in->pop_and_dirty_projected_inode(ls);
|
||||
}
|
||||
}
|
||||
|
||||
void Mutation::add_projected_fnode(CDir *dir)
|
||||
{
|
||||
projected_fnodes.push_back(dir);
|
||||
}
|
||||
|
||||
void Mutation::pop_and_dirty_projected_fnodes()
|
||||
{
|
||||
while (!projected_fnodes.empty()) {
|
||||
CDir *dir = projected_fnodes.front();
|
||||
projected_fnodes.pop_front();
|
||||
dir->pop_and_dirty_projected_fnode(ls);
|
||||
}
|
||||
}
|
||||
|
||||
void Mutation::add_updated_lock(ScatterLock *lock)
|
||||
{
|
||||
updated_locks.push_back(lock);
|
||||
}
|
||||
|
||||
void Mutation::add_cow_inode(CInode *in)
|
||||
{
|
||||
pin(in);
|
||||
dirty_cow_inodes.push_back(in);
|
||||
}
|
||||
|
||||
void Mutation::add_cow_dentry(CDentry *dn)
|
||||
{
|
||||
pin(dn);
|
||||
dirty_cow_dentries.push_back(pair<CDentry*,version_t>(dn, dn->get_projected_version()));
|
||||
}
|
||||
|
||||
void Mutation::apply()
|
||||
{
|
||||
pop_and_dirty_projected_inodes();
|
||||
pop_and_dirty_projected_fnodes();
|
||||
|
||||
for (list<CInode*>::iterator p = dirty_cow_inodes.begin();
|
||||
p != dirty_cow_inodes.end();
|
||||
p++)
|
||||
(*p)->_mark_dirty(ls);
|
||||
for (list<pair<CDentry*,version_t> >::iterator p = dirty_cow_dentries.begin();
|
||||
p != dirty_cow_dentries.end();
|
||||
p++)
|
||||
p->first->mark_dirty(p->second, ls);
|
||||
|
||||
for (list<ScatterLock*>::iterator p = updated_locks.begin();
|
||||
p != updated_locks.end();
|
||||
p++)
|
||||
(*p)->mark_dirty();
|
||||
}
|
||||
|
||||
void Mutation::cleanup()
|
||||
{
|
||||
drop_local_auth_pins();
|
||||
drop_pins();
|
||||
}
|
||||
|
||||
|
||||
// MDRequest
|
||||
|
||||
MDRequest::~MDRequest()
|
||||
{
|
||||
if (client_request)
|
||||
client_request->put();
|
||||
if (slave_request)
|
||||
slave_request->put();
|
||||
delete _more;
|
||||
}
|
||||
|
||||
MDRequest::More* MDRequest::more()
|
||||
{
|
||||
if (!_more)
|
||||
_more = new More();
|
||||
return _more;
|
||||
}
|
||||
|
||||
bool MDRequest::are_slaves()
|
||||
{
|
||||
return _more && !_more->slaves.empty();
|
||||
}
|
||||
|
||||
bool MDRequest::slave_did_prepare()
|
||||
{
|
||||
return more()->slave_commit;
|
||||
}
|
||||
|
||||
bool MDRequest::did_ino_allocation()
|
||||
{
|
||||
return alloc_ino || used_prealloc_ino || prealloc_inos.size();
|
||||
}
|
||||
|
||||
void MDRequest::print(ostream &out)
|
||||
{
|
||||
out << "request(" << reqid;
|
||||
//if (request) out << " " << *request;
|
||||
if (is_slave()) out << " slave_to mds" << slave_to_mds;
|
||||
if (client_request) out << " cr=" << client_request;
|
||||
if (slave_request) out << " sr=" << slave_request;
|
||||
out << ")";
|
||||
}
|
||||
|
292
src/mds/Mutation.h
Normal file
292
src/mds/Mutation.h
Normal file
@ -0,0 +1,292 @@
|
||||
// -*- 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_MDS_MUTATION_H
|
||||
#define CEPH_MDS_MUTATION_H
|
||||
|
||||
#include "include/interval_set.h"
|
||||
#include "include/elist.h"
|
||||
|
||||
#include "mdstypes.h"
|
||||
|
||||
#include "SimpleLock.h"
|
||||
#include "Capability.h"
|
||||
|
||||
class LogSegment;
|
||||
class Capability;
|
||||
class CInode;
|
||||
class CDir;
|
||||
class CDentry;
|
||||
class Session;
|
||||
class ScatterLock;
|
||||
class MClientRequest;
|
||||
class MMDSSlaveRequest;
|
||||
|
||||
struct Mutation {
|
||||
metareqid_t reqid;
|
||||
__u32 attempt; // which attempt for this request
|
||||
LogSegment *ls; // the log segment i'm committing to
|
||||
utime_t now;
|
||||
|
||||
// flag mutation as slave
|
||||
int slave_to_mds; // this is a slave request if >= 0.
|
||||
|
||||
// -- my pins and locks --
|
||||
// cache pins (so things don't expire)
|
||||
set< MDSCacheObject* > pins;
|
||||
set<CInode*> stickydirs;
|
||||
|
||||
// auth pins
|
||||
set< MDSCacheObject* > remote_auth_pins;
|
||||
set< MDSCacheObject* > auth_pins;
|
||||
|
||||
// held locks
|
||||
set< SimpleLock* > rdlocks; // always local.
|
||||
set< SimpleLock* > wrlocks; // always local.
|
||||
map< SimpleLock*, int > remote_wrlocks;
|
||||
set< SimpleLock* > xlocks; // local or remote.
|
||||
set< SimpleLock*, SimpleLock::ptr_lt > locks; // full ordering
|
||||
|
||||
// if this flag is set, do not attempt to acquire further locks.
|
||||
// (useful for wrlock, which may be a moving auth target)
|
||||
bool done_locking;
|
||||
bool committing;
|
||||
bool aborted;
|
||||
|
||||
// for applying projected inode changes
|
||||
list<CInode*> projected_inodes;
|
||||
list<CDir*> projected_fnodes;
|
||||
list<ScatterLock*> updated_locks;
|
||||
|
||||
list<CInode*> dirty_cow_inodes;
|
||||
list<pair<CDentry*,version_t> > dirty_cow_dentries;
|
||||
|
||||
Mutation() :
|
||||
attempt(0),
|
||||
ls(0),
|
||||
slave_to_mds(-1),
|
||||
done_locking(false), committing(false), aborted(false) { }
|
||||
Mutation(metareqid_t ri, __u32 att=0, int slave_to=-1) :
|
||||
reqid(ri), attempt(att),
|
||||
ls(0),
|
||||
slave_to_mds(slave_to),
|
||||
done_locking(false), committing(false), aborted(false) { }
|
||||
virtual ~Mutation() {
|
||||
assert(pins.empty());
|
||||
assert(auth_pins.empty());
|
||||
assert(xlocks.empty());
|
||||
assert(rdlocks.empty());
|
||||
assert(wrlocks.empty());
|
||||
assert(remote_wrlocks.empty());
|
||||
}
|
||||
|
||||
bool is_master() { return slave_to_mds < 0; }
|
||||
bool is_slave() { return slave_to_mds >= 0; }
|
||||
|
||||
client_t get_client() {
|
||||
if (reqid.name.is_client())
|
||||
return client_t(reqid.name.num());
|
||||
return -1;
|
||||
}
|
||||
|
||||
// pin items in cache
|
||||
void pin(MDSCacheObject *o);
|
||||
void set_stickydirs(CInode *in);
|
||||
void drop_pins();
|
||||
|
||||
// auth pins
|
||||
bool is_auth_pinned(MDSCacheObject *object);
|
||||
void auth_pin(MDSCacheObject *object);
|
||||
void auth_unpin(MDSCacheObject *object);
|
||||
void drop_local_auth_pins();
|
||||
void add_projected_inode(CInode *in);
|
||||
void pop_and_dirty_projected_inodes();
|
||||
void add_projected_fnode(CDir *dir);
|
||||
void pop_and_dirty_projected_fnodes();
|
||||
void add_updated_lock(ScatterLock *lock);
|
||||
void add_cow_inode(CInode *in);
|
||||
void add_cow_dentry(CDentry *dn);
|
||||
void apply();
|
||||
void cleanup();
|
||||
|
||||
virtual void print(ostream &out) {
|
||||
out << "mutation(" << this << ")";
|
||||
}
|
||||
};
|
||||
|
||||
inline ostream& operator<<(ostream& out, Mutation &mut)
|
||||
{
|
||||
mut.print(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/** active_request_t
|
||||
* state we track for requests we are currently processing.
|
||||
* mostly information about locks held, so that we can drop them all
|
||||
* the request is finished or forwarded. see request_*().
|
||||
*/
|
||||
struct MDRequest : public Mutation {
|
||||
int ref;
|
||||
Session *session;
|
||||
elist<MDRequest*>::item item_session_request; // if not on list, op is aborted.
|
||||
|
||||
// -- i am a client (master) request
|
||||
MClientRequest *client_request; // client request (if any)
|
||||
|
||||
// store up to two sets of dn vectors, inode pointers, for request path1 and path2.
|
||||
vector<CDentry*> dn[2];
|
||||
CDentry *straydn;
|
||||
CInode *in[2];
|
||||
snapid_t snapid;
|
||||
|
||||
CInode *tracei;
|
||||
CDentry *tracedn;
|
||||
|
||||
inodeno_t alloc_ino, used_prealloc_ino;
|
||||
interval_set<inodeno_t> prealloc_inos;
|
||||
|
||||
int snap_caps;
|
||||
bool did_early_reply;
|
||||
|
||||
// inos we did a embedded cap release on, and may need to eval if we haven't since reissued
|
||||
map<vinodeno_t, ceph_seq_t> cap_releases;
|
||||
|
||||
// -- i am a slave request
|
||||
MMDSSlaveRequest *slave_request; // slave request (if one is pending; implies slave == true)
|
||||
|
||||
// -- i am an internal op
|
||||
int internal_op;
|
||||
|
||||
// break rarely-used fields into a separately allocated structure
|
||||
// to save memory for most ops
|
||||
struct More {
|
||||
set<int> slaves; // mds nodes that have slave requests to me (implies client_request)
|
||||
set<int> waiting_on_slave; // peers i'm waiting for slavereq replies from.
|
||||
|
||||
// for rename/link/unlink
|
||||
set<int> witnessed; // nodes who have journaled a RenamePrepare
|
||||
map<MDSCacheObject*,version_t> pvmap;
|
||||
|
||||
// for rename
|
||||
set<int> extra_witnesses; // replica list from srcdn auth (rename)
|
||||
version_t src_reanchor_atid; // src->dst
|
||||
version_t dst_reanchor_atid; // dst->stray
|
||||
bufferlist inode_import;
|
||||
version_t inode_import_v;
|
||||
CInode* destdn_was_remote_inode;
|
||||
bool was_link_merge;
|
||||
|
||||
map<client_t,entity_inst_t> imported_client_map;
|
||||
map<client_t,uint64_t> sseq_map;
|
||||
map<CInode*, map<client_t,Capability::Export> > cap_imports;
|
||||
|
||||
// for lock/flock
|
||||
bool flock_was_waiting;
|
||||
|
||||
// for snaps
|
||||
version_t stid;
|
||||
bufferlist snapidbl;
|
||||
|
||||
// called when slave commits or aborts
|
||||
Context *slave_commit;
|
||||
bufferlist rollback_bl;
|
||||
|
||||
More() :
|
||||
src_reanchor_atid(0), dst_reanchor_atid(0), inode_import_v(0),
|
||||
destdn_was_remote_inode(0), was_link_merge(false),
|
||||
flock_was_waiting(false),
|
||||
stid(0),
|
||||
slave_commit(0) { }
|
||||
} *_more;
|
||||
|
||||
|
||||
// ---------------------------------------------------
|
||||
MDRequest() :
|
||||
ref(1),
|
||||
session(0), item_session_request(this),
|
||||
client_request(0), straydn(NULL), snapid(CEPH_NOSNAP), tracei(0), tracedn(0),
|
||||
alloc_ino(0), used_prealloc_ino(0), snap_caps(0), did_early_reply(false),
|
||||
slave_request(0),
|
||||
internal_op(-1),
|
||||
_more(0) {
|
||||
in[0] = in[1] = 0;
|
||||
}
|
||||
MDRequest(metareqid_t ri, __u32 attempt, MClientRequest *req) :
|
||||
Mutation(ri, attempt),
|
||||
ref(1),
|
||||
session(0), item_session_request(this),
|
||||
client_request(req), straydn(NULL), snapid(CEPH_NOSNAP), tracei(0), tracedn(0),
|
||||
alloc_ino(0), used_prealloc_ino(0), snap_caps(0), did_early_reply(false),
|
||||
slave_request(0),
|
||||
internal_op(-1),
|
||||
_more(0) {
|
||||
in[0] = in[1] = 0;
|
||||
}
|
||||
MDRequest(metareqid_t ri, __u32 attempt, int by) :
|
||||
Mutation(ri, attempt, by),
|
||||
ref(1),
|
||||
session(0), item_session_request(this),
|
||||
client_request(0), straydn(NULL), snapid(CEPH_NOSNAP), tracei(0), tracedn(0),
|
||||
alloc_ino(0), used_prealloc_ino(0), snap_caps(0), did_early_reply(false),
|
||||
slave_request(0),
|
||||
internal_op(-1),
|
||||
_more(0) {
|
||||
in[0] = in[1] = 0;
|
||||
}
|
||||
~MDRequest();
|
||||
|
||||
MDRequest *get() {
|
||||
++ref;
|
||||
return this;
|
||||
}
|
||||
void put() {
|
||||
if (--ref == 0)
|
||||
delete this;
|
||||
}
|
||||
|
||||
More* more();
|
||||
bool are_slaves();
|
||||
bool slave_did_prepare();
|
||||
bool did_ino_allocation();
|
||||
|
||||
void print(ostream &out);
|
||||
};
|
||||
|
||||
|
||||
struct MDSlaveUpdate {
|
||||
int origop;
|
||||
bufferlist rollback;
|
||||
elist<MDSlaveUpdate*>::item item;
|
||||
Context *waiter;
|
||||
MDSlaveUpdate(int oo, bufferlist &rbl, elist<MDSlaveUpdate*> &list) :
|
||||
origop(oo),
|
||||
item(this),
|
||||
waiter(0) {
|
||||
rollback.claim(rbl);
|
||||
list.push_back(&item);
|
||||
}
|
||||
~MDSlaveUpdate() {
|
||||
item.remove_myself();
|
||||
if (waiter)
|
||||
waiter->finish(0);
|
||||
delete waiter;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif
|
@ -22,6 +22,7 @@
|
||||
#include "AnchorClient.h"
|
||||
#include "InoTable.h"
|
||||
#include "SnapClient.h"
|
||||
#include "Mutation.h"
|
||||
|
||||
#include "msg/Messenger.h"
|
||||
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include "MDCache.h"
|
||||
#include "Server.h"
|
||||
#include "Migrator.h"
|
||||
#include "Mutation.h"
|
||||
|
||||
#include "InoTable.h"
|
||||
#include "MDSTableClient.h"
|
||||
|
Loading…
Reference in New Issue
Block a user