}
void Client::handle_osd_update(MOSDUpdate *m) {
- // check local cache
- MOSDUpdateReply *reply;
- gid_t my_group = m->get_group();
- cout << "Received a request to resolve group " << my_group << endl;
- // if we dont have it cached, ask mds, cache it
- //if (groups.count(my_group) == 0) {
- // MClientUpdate *update = new MClientUpdate(my_group);
- //}
- //reply = new MOSDUpdateReply(groups[my_group].get_list());
- reply = new MOSDUpdateReply(my_group);
- messenger->send_message(reply, m->get_source_inst());
+ hash_t my_hash = m->get_hash();
+ cout << "Client::handle_osd_request Received a request to resolve group " << my_hash << endl;
+
+ // if we dont have it cached, ask mds
+ // this will lose execution control
+ if (groups.count(my_hash) == 0) {
+ MClientUpdate *update = new MClientUpdate(my_hash);
+
+ // is anyone else already waiting for this hash?
+ if (update_waiter_osd.count(my_hash) == 0) {
+ dout(10) << "mds_group_update for " << my_hash << endl;
+ // FIXME choose mds (always choose 0)
+ messenger->send_message(update, mdsmap->get_inst(0), MDS_PORT_SERVER);
+ }
+ else
+ dout(10) << "mds_group_update for " << my_hash << endl;
+
+ update_waiter_osd[my_hash].insert(m->get_source().num());
+ }
+ // we have the group, hand it back
+ else {
+ MOSDUpdateReply *reply = new MOSDUpdateReply(my_hash,
+ groups[my_hash].get_list());
+ messenger->send_message(reply, m->get_source_inst());
+ }
+
+ // default test option (only for debug)
+ //reply = new MOSDUpdateReply(my_hash);
+ //messenger->send_message(reply, m->get_source_inst());
+
+}
+
+void Client::handle_client_update_reply(MClientUpdateReply *m) {
+
+ hash_t my_hash = m->get_user_hash();
+ cout << "Client::handle_client_update_reply for " << my_hash << endl;
+
+ // cache the list
+ groups[my_hash].set_list(m->get_user_list());
+
+ MOSDUpdateReply *reply = new MOSDUpdateReply(my_hash, groups[my_hash].get_list());
+
+ // wake the waiters and send them all a reply
+ for (set<int>::iterator oi = update_waiter_osd[my_hash].begin();
+ oi != update_waiter_osd[my_hash].end();
+ ++oi) {
+ messenger->send_message(reply, osdmap->get_inst(*oi));
+ }
+
}
// ------------------------
case MSG_OSD_UPDATE:
handle_osd_update((MOSDUpdate*)m);
break;
-
+ case MSG_CLIENT_UPDATE_REPLY:
+ handle_client_update_reply((MClientUpdateReply*)m);
+ break;
+
// client
case MSG_MDS_MAP:
handle_mds_map((MMDSMap*)m);
#include "messages/MOSDUpdate.h"
#include "messages/MOSDUpdateReply.h"
#include "messages/MClientUpdate.h"
+#include "messages/MClientUpdateReply.h"
//#include "msgthread.h"
#include "crypto/Ticket.h"
#include "crypto/CapGroup.h"
+#include "crypto/MerkleTree.h"
// stl
#include <set>
map<uid_t,esignPub*> user_pub_key;
map<uid_t,esignPriv*> user_priv_key;
- map<gid_t, CapGroup> groups;
+ map<hash_t, CapGroup> groups;
+ map<hash_t, set<int> > update_waiter_osd;
+ //map<hash_t, list<Cond*> > update_waiter_cond;
+
// user map
//map<uid_t, User*> user_identity;
void put_user_ticket(Ticket *tk);
void handle_osd_update(MOSDUpdate *m);
+ void handle_client_update_reply(MClientUpdateReply *m);
// friends
friend class SyntheticClient;
#include<iostream>
using namespace std;
-//#include "include/types.h"
#include "crypto/MerkleTree.h"
class CapGroup {
private:
- //gid_t group_id;
+ gid_t group_id;
hash_t root_hash;
+ MerkleTree mtree;
list<uid_t> users;
public:
friend class OSD;
friend class Locker;
CapGroup () { }
- //CapGroup (gid_t id) { group_id = id; }
+ CapGroup (gid_t id) { group_id = id; }
CapGroup (hash_t rhash, list<uid_t>& ulist) :
root_hash(rhash), users(ulist) { }
+ CapGroup (gid_t id, list<uid_t>& ulist) : group_id(id), users(ulist) {
+ // add users to MerkleTree
+ mtree = MerkleTree(users);
+ root_hash = mtree.get_root_hash();
+ }
- //gid_t get_gid() { return group_id; }
- //void set_gid(gid_t id) { group_id = id; }
+ gid_t get_gid() { return group_id; }
+ void set_gid(gid_t id) { group_id = id; }
hash_t get_root_hash() { return root_hash; }
void set_root_hash(hash_t nhash) { root_hash = nhash; }
void add_user(uid_t user) {
users.push_back(user);
+ // re-compute root-hash
+ mtree.add_user(user);
+ root_hash = mtree.get_root_hash();
}
void remove_user(uid_t user) {
users.remove(user);
+ //FIXME need to re-compute hash
}
bool contains(uid_t user) {
for (list<uid_t>::iterator ui = users.begin();
ui != users.end();
ui++) {
- //uid_t test& = *ui;
if (*ui == user)
return true;
}
#include "crypto/CryptoLib.h"
using namespace CryptoLib;
#include "crypto/MerkleTree.h"
+#include "crypto/CapGroup.h"
#define NO_GROUP 0
#define UNIX_GROUP 1
data.ino = n;
}
+ ExtCap(int m, uid_t u, CapGroup& cg, inodeno_t n)
+ {
+ data.id.cid = 0;
+ data.id.mds_id = 0;
+ data.t_s = g_clock.now();
+ data.t_e = data.t_s;
+ data.t_e += 3600;
+ data.mode = m;
+ data.uid = u;
+ data.gid = cg.get_gid();
+ data.user_group = cg.get_root_hash();
+ data.ino = n;
+ }
+
// capability for too many user, many named files
// capability for too many user, too many files
}
void set_type(__int8_t new_type) { data.type = new_type;}
- void set_user_hash(hash_t nhash) { user_group = nhash; }
- void set_file_hash(hash_t nhash) { file_group = nhash; }
+ void set_user_hash(hash_t nhash) { data.user_group = nhash; }
+ void set_file_hash(hash_t nhash) { data.file_group = nhash; }
- hash_t get_user_hash() { return user_group; }
- hash_t get_file_hash() { return file_group; }
+ hash_t get_user_hash() { return data.user_group; }
+ hash_t get_file_hash() { return data.file_group; }
const cap_data_t* get_data() const {
return (&data);
// get the uid
uid_t my_user = req->get_caller_uid();
gid_t my_group = req->get_caller_gid();
- gid_t file_group = req->get_gid();
+
int my_want = 0;
// issue most generic cap (RW)
my_want |= FILE_MODE_RW;
// make new cap
// unix grouping
if (g_conf.mds_group == 1) {
+
// configure group
if (mds->unix_groups.count(my_group) == 0)
mds->unix_groups[my_group].set_gid(my_group);
-
- // add user to group if not know already
- if (!(mds->unix_groups[my_group].contains(my_user)))
+
+ // add user to group if not in group
+ if (!(mds->unix_groups[my_group].contains(my_user))) {
mds->unix_groups[my_group].add_user(my_user);
+ hash_t temp_hash = mds->unix_groups[my_group].get_root_hash();
+ mds->unix_groups_byhash[temp_hash] = mds->unix_groups[my_group];
+ }
- ext_cap = new ExtCap(my_want, my_user, my_group, in->ino());
+ ext_cap = new ExtCap(my_want, my_user,
+ mds->unix_groups[my_group], in->ino());
ext_cap->set_type(1);
+
+ dout(3) << "Made new " << my_want << " capability for uid: "
+ << ext_cap->get_uid() << ", group: " << ext_cap->get_gid()
+ << ", for hash: " << ext_cap->get_user_hash()
+ << " for inode: " << ext_cap->get_ino()<< endl;
}
// default no grouping
else
ext_cap = new ExtCap(my_want, my_user, in->ino());
-
+
ext_cap->set_id(cap_id_count, mds->get_nodeid());
// increment capability count
cap_id_count++;
public:
map<int,version_t> peer_mdsmap_epoch;
- // user groups
+ // logical user group
map<gid_t, CapGroup> unix_groups;
- map<hash_t, CapGroup> user_groups;
+ // hash to group map
+ map<hash_t, CapGroup> unix_groups_byhash;
void queue_waitfor_active(Context *c) { waitfor_active.push_back(c); }
case MSG_CLIENT_REQUEST:
handle_client_request((MClientRequest*)m);
return;
+ case MSG_CLIENT_UPDATE:
+ handle_client_update((MClientUpdate*)m);
+ return;
case MSG_MDS_HASHREADDIR:
handle_hash_readdir((MHashReaddir*)m);
}
}
+// update group operations
+void Server::handle_client_update(MClientUpdate *m)
+{
+ hash_t my_hash = m->get_user_hash();
+ dout(3) << "handle_client_update for " << my_hash << endl;
+
+ MClientUpdateReply *reply = new MClientUpdateReply(my_hash, mds->unix_groups_byhash[my_hash].get_list());
+ messenger->send_message(reply, m->get_source_inst());
+}
/***
* process a client request
#define __MDS_SERVER_H
#include "MDS.h"
+#include "messages/MClientUpdate.h"
+#include "messages/MClientUpdateReply.h"
class LogEvent;
void handle_client_request_2(MClientRequest *req,
vector<CDentry*>& trace,
int r);
+
+ // group updates
+ void handle_client_update(MClientUpdate *m);
// fs ops
void handle_client_fstat(MClientRequest *req);
#include "msg/Message.h"
#include "osd/osd_types.h"
+#include "crypto/MerkleTree.h"
class MClientUpdate : public Message {
private:
struct {
+ hash_t user_hash;
gid_t group;
entity_inst_t asking_client;
} mds_update_st;
memset(&mds_update_st, 0, sizeof(mds_update_st));
this->mds_update_st.group = gid;
}
+ MClientUpdate (hash_t uhash) : Message(MSG_CLIENT_UPDATE) {
+ memset(&mds_update_st, 0, sizeof(mds_update_st));
+ this->mds_update_st.user_hash = uhash;
+ }
+ void set_group(gid_t ngroup) { mds_update_st.group = ngroup; }
gid_t get_group () { return mds_update_st.group; }
+ void set_user_hash(hash_t nhash) { mds_update_st.user_hash = nhash; }
+ hash_t get_user_hash() { return mds_update_st.user_hash; }
+ entity_inst_t& get_client_inst() { return mds_update_st.asking_client; }
virtual void encode_payload() {
payload.append((char*)&mds_update_st, sizeof(mds_update_st));
virtual char *get_type_name() { return "mds_update"; }
void print(ostream& out) {
out << "mds_update(" << mds_update_st.group
+ << ", " << mds_update_st.user_hash
<< ")";
}
};
#include "msg/Message.h"
#include "osd/osd_types.h"
+#include "crypto/MerkleTree.h"
class MOSDUpdate : public Message {
private:
struct {
gid_t group;
+ hash_t uhash;
entity_inst_t client;
entity_inst_t asker;
} update_st;
public:
gid_t get_group() { return update_st.group; }
+ hash_t get_hash() { return update_st.uhash; }
entity_inst_t get_client_inst() { return update_st.client; }
entity_inst_t get_asker() { return update_st.asker; }
this->update_st.group = upGr;
}
+ MOSDUpdate(hash_t h) : Message(MSG_OSD_UPDATE) {
+ memset(&update_st,0, sizeof(update_st));
+ this->update_st.uhash = h;
+ }
+
MOSDUpdate(entity_inst_t asking_osd, entity_inst_t target_client,
gid_t upGr) : Message(MSG_OSD_UPDATE) {
memset(&update_st,0, sizeof(update_st));
virtual char *get_type_name() { return "oop_update"; }
void print(ostream& out) {
out << "osd_update(" << update_st.group
+ << ", " << update_st.uhash
<< ")";
}
};
class MOSDUpdateReply : public Message {
private:
gid_t group;
+ hash_t user_hash;
list<uid_t> updated_users;
public:
MOSDUpdateReply () : Message(MSG_OSD_UPDATE_REPLY) { }
MOSDUpdateReply(gid_t gid) : Message(MSG_OSD_UPDATE_REPLY),
group(gid) { }
+ MOSDUpdateReply(hash_t uhash) : Message(MSG_OSD_UPDATE_REPLY),
+ user_hash(uhash) { }
MOSDUpdateReply (gid_t gid, list<uid_t> users) :
Message(MSG_OSD_UPDATE_REPLY), group(gid), updated_users(users) { }
+ MOSDUpdateReply(hash_t uhash, list<uid_t>& users) :
+ Message(MSG_OSD_UPDATE_REPLY), user_hash(uhash), updated_users(users) { }
gid_t get_group() { return group; }
+ hash_t get_user_hash() { return user_hash; }
list<uid_t>& get_list() { return updated_users; }
virtual void encode_payload() {
payload.append((char*)&group, sizeof(group));
+ payload.append((char*)&user_hash, sizeof(user_hash));
_encode(updated_users, payload);
}
virtual void decode_payload() {
int off = 0;
payload.copy(off, sizeof(group), (char*)&group);
off += sizeof(group);
+ payload.copy(off, sizeof(user_hash), (char*)&user_hash);
+ off += sizeof(user_hash);
_decode(updated_users, payload, off);
}
virtual char *get_type_name() { return "oop_update_reply"; }
void print(ostream& out) {
out << "osd_update_reply(" << group
+ << ", " << user_hash
<< ")";
}
};
#include "messages/MClientReply.h"
#include "messages/MClientFileCaps.h"
#include "messages/MClientUpdate.h"
+#include "messages/MClientUpdateReply.h"
#include "messages/MMDSGetMap.h"
#include "messages/MMDSMap.h"
case MSG_CLIENT_FILECAPS:
m = new MClientFileCaps();
break;
+ case MSG_CLIENT_UPDATE:
+ m = new MClientUpdate();
+ break;
+ case MSG_CLIENT_UPDATE_REPLY:
+ m = new MClientUpdateReply();
+ break;
// mds
case MSG_MDS_GETMAP:
#define MSG_CLIENT_FILECAPS 63
#define MSG_CLIENT_INODEAUTHUPDATE 64
#define MSG_CLIENT_UPDATE 65
+#define MSG_CLIENT_UPDATE_REPLY 66
#define MSG_CLIENT_BOOT 70
#define MSG_CLIENT_MOUNT 71
if (op_capability->get_type() == UNIX_GROUP) {
// check if user is in group
- gid_t my_group = op_capability->get_gid();
+ hash_t my_hash = op_capability->get_user_hash();
- // do we have group cached? if not, update group
- // this will block till we have the group!!
- if (unix_groups.count(my_group) == 0) {
- update_group(op->get_client_inst(), my_group);
- }
-
// now we should have the group, is the client in it?
- if (!(unix_groups[my_group].contains(op_capability->get_uid()))) {
+ if (!(user_groups[my_hash].contains(op_capability->get_uid()))) {
// do update to get new unix groups
cout << "User " << op_capability->get_uid() << " not in group "
- << my_group << endl;
+ << my_hash << endl;
return false;
}
+
}
// check users match
else if (op->get_user() != op_capability->get_uid()) {
}
// gets group information from client (will block!)
-void OSD::update_group(entity_inst_t client, gid_t group) {
- // set up reply
- MOSDUpdate *update = new MOSDUpdate(group);
+void OSD::update_group(entity_inst_t client, hash_t my_hash, MOSDOp *op) {
+ // set up reply
+ MOSDUpdate *update = new MOSDUpdate(my_hash);
Cond cond;
// if no one has already requested the ticket
- if (update_waiter_cond.count(group) == 0) {
- dout(10) << "update_group requesting update for gid " << group << endl;
+ if (update_waiter_op.count(my_hash) == 0) {
+ dout(10) << "update_group requesting update for hash " << my_hash << endl;
// send it
messenger->send_message(update, client);
} else {
// don't request, someone else already did. just wait!
- dout(10) << "update_group waiting for update for gid " << group << endl;
+ dout(10) << "update_group waiting for update for hash " << my_hash << endl;
}
// wait for reply
- update_waiter_cond[group].push_back( &cond );
+ update_waiter_op[my_hash].push_back( op );
// naively assume we'll get an update FIXME
- while (unix_groups.count(group) == 0) {
- cond.Wait(osd_lock);
- //cout << "Received a singal, going to check group " << group << endl;
- }
- cout << "Received updated group, returning" << endl;
+ //while (user_groups.count(my_hash) == 0) {
+ // cond.Wait(osd_lock);
+ //}
}
void OSD::handle_osd_update_reply(MOSDUpdateReply *m) {
// store the new list into group
- gid_t my_group = m->get_group();
+ hash_t my_hash = m->get_user_hash();
- cout << "hande_osd_update_reply for " << my_group << endl;
- dout(10) << "hande_osd_update_reply for " << my_group << endl;
+ cout << "hande_osd_update_reply for " << my_hash << endl;
+ dout(10) << "hande_osd_update_reply for " << my_hash << endl;
// add the new list to our cache
- unix_groups[my_group].set_list(m->get_list());
+ user_groups[my_hash].set_list(m->get_list());
// wait up the waiter(s)
// this signals all update waiters
- for (list<Cond*>::iterator p = update_waiter_cond[my_group].begin();
- p != update_waiter_cond[my_group].end();
- ++p) {
- (*p)->Signal();
- }
+ //for (list<Cond*>::iterator p = update_waiter_cond[my_hash].begin();
+ // p != update_waiter_cond[my_hash].end();
+ // ++p) {
+ //(*p)->Signal();
+ //}
+ take_waiters(update_waiter_op[my_hash]);
- update_waiter_cond.erase(my_group);
+ update_waiter_op.erase(my_hash);
}
// assumes the request and cap contents has already been checked
// i know, i know...not secure but they should all have caps
if (op->get_op() == OSD_OP_WRITE
&& op->get_source().is_client()) {
-
+
ExtCap *op_capability = op->get_capability();
assert(op_capability);
+ // if using groups...do we know group?
+ if (op_capability->get_type() == UNIX_GROUP) {
+ // check if user is in group
+ hash_t my_hash = op_capability->get_user_hash();
+
+ // do we have group cached? if not, update group
+ // we will lose execution control here! re-gain on reply
+ if (user_groups.count(my_hash) == 0) {
+ update_group(op->get_client_inst(), my_hash, op);
+ return;
+ }
+
+ }
+
// check accesses are right
if (check_request(op, op_capability)) {
cout << "Access permissions are correct" << endl;
assert(verify_cap(op_capability));
}
- //else
- //cout << "Received some write with no cap from " <<
- //op->get_source().type() << endl;
+
}
// locked by someone else?
hash_map<int, float> peer_qlen;
- // unix group cache
- //map<gid_t, CapGroup> unix_groups;
+ // user group cache
map<hash_t, CapGroup> user_groups;
- //map<gid_t, list<Cond*> > update_waiter_cond;
- map<hash_t, list<Cond*> > update_waiter_cond;
+ map<hash_t, list<Message*> >update_waiter_op;
void handle_osd_update_reply(MOSDUpdateReply *m);
// per-pg locking (serializing)
// security ops
bool check_request(class MOSDOp *op, ExtCap *op_capability);
- void update_group(entity_inst_t client, gid_t group);
+ void update_group(entity_inst_t client, hash_t group, MOSDOp *op);
bool verify_cap(ExtCap *cap);
// messages