}
void Client::handle_osd_update(MOSDUpdate *m) {
- cout << "Received a request to resolve group " << m->get_group() << endl;
// check local cache
- if (groups.count(m->get_group())) {
-
- }
- // else, ask mds, pass it, cache it
- assert(0);
+ 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());
}
// ------------------------
#include "messages/MClientRequest.h"
#include "messages/MClientReply.h"
#include "messages/MOSDUpdate.h"
+#include "messages/MOSDUpdateReply.h"
+#include "messages/MClientUpdate.h"
//#include "msgthread.h"
#include<iostream>
using namespace std;
-#include "include/types.h"
+//#include "include/types.h"
+#include "crypto/MerkleTree.h"
class CapGroup {
private:
- gid_t group_id;
+ //gid_t group_id;
+ hash_t root_hash;
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) { }
- 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);
}
return false;
}
+
+ void set_list(list<uid_t>& nlist) { users = nlist; }
+ list<uid_t>& get_list() { return users; }
};
#endif
#include "crypto/CryptoLib.h"
using namespace CryptoLib;
+#include "crypto/MerkleTree.h"
#define NO_GROUP 0
#define UNIX_GROUP 1
gid_t gid; // group id
bool world;
+ // hash based users and files
+ hash_t user_group;
+ hash_t file_group;
+
inodeno_t ino; // inode number
};
}
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; }
+
+ hash_t get_user_hash() { return user_group; }
+ hash_t get_file_hash() { return file_group; }
+
const cap_data_t* get_data() const {
return (&data);
}
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+/*
+ * 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 __MERKLETREE_H
+#define __MERKLETREE_H
+
+#include<iostream>
+#include<list>
+using namespace std;
+
+#include "crypto/CryptoLib.h"
+using namespace CryptoLib;
+
+struct hash_t{
+ byte val[SHA1DIGESTSIZE];
+};
+
+// comparison operators
+inline bool operator==(const hash_t& a, const hash_t& b)
+{
+ return (memcmp((void*)&a, (void*)&b, sizeof(hash_t)) == 0);
+}
+inline bool operator>(const hash_t& a, const hash_t& b)
+{
+ return (memcmp((void*)&a, (void*)&b, sizeof(hash_t)) > 0);
+}
+inline bool operator<(const hash_t& a, const hash_t& b)
+{
+ return (memcmp((void*)&a, (void*)&b, sizeof(hash_t)) < 0);
+}
+// ostream
+inline std::ostream& operator<<(std::ostream& out, const hash_t& c)
+{
+ byte hexArray[SHA1DIGESTSIZE];
+ memset(hexArray, 0x00, sizeof(hexArray));
+ toHex(c.val, hexArray, SHA1DIGESTSIZE, SHA1DIGESTSIZE);
+ out << string((const char*)hexArray);
+ return out;
+}
+
+class MerkleTree {
+ private:
+ // the root hash of the tree
+ hash_t root_hash;
+
+ public:
+ // default constructor
+ MerkleTree () { memset(&root_hash, 0x00, sizeof(root_hash)); }
+
+ // constructor from an initial list of users
+ MerkleTree (list< uid_t >& input) {
+ memset(&root_hash, 0x00, sizeof(root_hash));
+ uid_t uidArray[input.size()];
+ int counter = 0;
+
+ // FIXME just do a linear hash first for root hash
+ // copy list into buffer
+ for (list<uid_t>::iterator li = input.begin();
+ li != input.end();
+ li++) {
+ uidArray[counter] = *li;
+ counter++;
+ }
+ // zero the array
+ sha1((byte*)uidArray, (byte*)&root_hash, sizeof(uidArray));
+ }
+
+ void add_user(uid_t user) {
+ // hash the user
+ hash_t user_hash;
+ sha1((byte*)&user, (byte*)&user_hash, sizeof(user));
+ // join the user and root_hash
+ hash_t conjunction[2];
+ conjunction[0] = root_hash;
+ conjunction[1] = user_hash;
+ // hash em both
+ sha1((byte*)&conjunction, (byte*)&root_hash, sizeof(conjunction));
+ }
+
+ hash_t& get_root_hash() { return root_hash; }
+};
+
+// ostream
+inline std::ostream& operator<<(std::ostream& out, MerkleTree& c)
+{
+ return out << c.get_root_hash();
+}
+
+#endif
* Author: Andrew Leung Nov., 2006
******************************/
#include"CryptoLib.h"
+#include "MerkleTree.h"
#include<iostream>
using namespace std;
// message to hash
const byte* msg = (const byte*)"hash me";
+ // test merkle trees
+ MerkleTree mtree;
+ uid_t user1 = 1000;
+ mtree.add_user(user1);
+ cout << "My root hash: " << mtree << endl;
+ MerkleTree mtree2 = mtree;
+ uid_t user2 = 2000;
+ mtree2.add_user(user2);
+ cout << "My update root hash " << mtree2 << endl;
+ if (mtree2.get_root_hash() > mtree.get_root_hash())
+ cout << "mtree2 is bigger" << endl;
+ else
+ cout << "mtree is bigger" << endl;
+
// sha-1
byte digest[SHA1DIGESTSIZE];
byte digestHex[2*SHA1DIGESTSIZE];
* This function does nothing for synchronization
**********/
ExtCap* Locker::issue_new_extcaps(CInode *in, int mode, MClientRequest *req) {
- dout(3) << "issue_new_EXTcaps for mode " << mode << " on " << *in << endl;
+ dout(3) << "issue_new_extcaps for mode " << mode << " on " << *in << endl;
// 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) {
- ext_cap = new ExtCap(my_want, my_user, my_group, in->ino());
-
// 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)))
mds->unix_groups[my_group].add_user(my_user);
+ ext_cap = new ExtCap(my_want, my_user, my_group, in->ino());
+
ext_cap->set_type(1);
}
// default no grouping
#include "crypto/ExtCap.h"
#include "crypto/CapGroup.h"
+#include "crypto/MerkleTree.h"
#define MDS_PORT_MAIN 0
#define MDS_PORT_SERVER 1
// user groups
map<gid_t, CapGroup> unix_groups;
+ map<hash_t, CapGroup> user_groups;
void queue_waitfor_active(Context *c) { waitfor_active.push_back(c); }
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+/*
+ * 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 __MCLIENTUPDATE_H
+#define __MCLIENTUPDATE_H
+
+#include "msg/Message.h"
+#include "osd/osd_types.h"
+
+class MClientUpdate : public Message {
+private:
+ struct {
+ gid_t group;
+ entity_inst_t asking_client;
+ } mds_update_st;
+public:
+ MClientUpdate () : Message(MSG_CLIENT_UPDATE) { }
+ MClientUpdate (gid_t gid) : Message(MSG_CLIENT_UPDATE) {
+ memset(&mds_update_st, 0, sizeof(mds_update_st));
+ this->mds_update_st.group = gid;
+ }
+
+ gid_t get_group () { return mds_update_st.group; }
+
+ virtual void encode_payload() {
+ payload.append((char*)&mds_update_st, sizeof(mds_update_st));
+ }
+ virtual void decode_payload() {
+ int off = 0;
+ payload.copy(off, sizeof(mds_update_st), (char*)&mds_update_st);
+ off += sizeof(mds_update_st);
+ }
+ virtual char *get_type_name() { return "mds_update"; }
+ void print(ostream& out) {
+ out << "mds_update(" << mds_update_st.group
+ << ")";
+ }
+};
+
+#endif
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+/*
+ * 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 __MOSDUPDATE_H
+#define __MOSDUPDATE_H
+
+#include "msg/Message.h"
+#include "osd/osd_types.h"
+
+class MOSDUpdate : public Message {
+private:
+ struct {
+ gid_t group;
+ entity_inst_t client;
+ entity_inst_t asker;
+ } update_st;
+public:
+ gid_t get_group() { return update_st.group; }
+ entity_inst_t get_client_inst() { return update_st.client; }
+ entity_inst_t get_asker() { return update_st.asker; }
+
+ MOSDUpdate () { }
+
+ MOSDUpdate(gid_t upGr) : Message(MSG_OSD_UPDATE) {
+ memset(&update_st,0, sizeof(update_st));
+ this->update_st.group = upGr;
+ }
+
+ 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));
+ this->update_st.group = upGr;
+ this->update_st.client = target_client;
+ this->update_st.asker = asking_osd;
+ }
+
+ virtual void decode_payload() {
+ int off = 0;
+ payload.copy(off, sizeof(update_st), (char*)&update_st);
+ off += sizeof(update_st);
+ }
+ virtual void encode_payload() {
+ payload.append((char*)&update_st, sizeof(update_st));
+ }
+
+ virtual char *get_type_name() { return "oop_update"; }
+ void print(ostream& out) {
+ out << "osd_update(" << update_st.group
+ << ")";
+ }
+};
+
+#endif
+
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+/*
+ * 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 __MOSDUPDATEREPLY_H
+#define __MOSDUPDATEREPLY_H
+
+#include "msg/Message.h"
+#include "osd/osd_types.h"
+
+class MOSDUpdateReply : public Message {
+private:
+ gid_t group;
+ list<uid_t> updated_users;
+public:
+ MOSDUpdateReply () : Message(MSG_OSD_UPDATE_REPLY) { }
+ MOSDUpdateReply(gid_t gid) : Message(MSG_OSD_UPDATE_REPLY),
+ group(gid) { }
+ MOSDUpdateReply (gid_t gid, list<uid_t> users) :
+ Message(MSG_OSD_UPDATE_REPLY), group(gid), updated_users(users) { }
+
+ gid_t get_group() { return group; }
+ list<uid_t>& get_list() { return updated_users; }
+
+ virtual void encode_payload() {
+ payload.append((char*)&group, sizeof(group));
+ _encode(updated_users, payload);
+ }
+ virtual void decode_payload() {
+ int off = 0;
+ payload.copy(off, sizeof(group), (char*)&group);
+ off += sizeof(group);
+ _decode(updated_users, payload, off);
+ }
+ virtual char *get_type_name() { return "oop_update_reply"; }
+ void print(ostream& out) {
+ out << "osd_update_reply(" << group
+ << ")";
+ }
+};
+
+#endif
#include "messages/MOSDPGLog.h"
#include "messages/MOSDPGRemove.h"
#include "messages/MOSDUpdate.h"
+#include "messages/MOSDUpdateReply.h"
#include "messages/MClientBoot.h"
#include "messages/MClientMount.h"
#include "messages/MClientRequest.h"
#include "messages/MClientReply.h"
#include "messages/MClientFileCaps.h"
+#include "messages/MClientUpdate.h"
#include "messages/MMDSGetMap.h"
#include "messages/MMDSMap.h"
case MSG_OSD_UPDATE:
m = new MOSDUpdate();
break;
+ case MSG_OSD_UPDATE_REPLY:
+ m = new MOSDUpdateReply();
+ break;
// clients
case MSG_CLIENT_BOOT:
// osd group update
#define MSG_OSD_UPDATE 55
+#define MSG_OSD_UPDATE_REPLY 56
#define MSG_CLIENT_REQUEST 60
#define MSG_CLIENT_REPLY 61
//#define MSG_CLIENT_DONE 62
#define MSG_CLIENT_FILECAPS 63
#define MSG_CLIENT_INODEAUTHUPDATE 64
+#define MSG_CLIENT_UPDATE 65
#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();
+
+ // 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()))) {
// do update to get new unix groups
cout << "User " << op_capability->get_uid() << " not in group "
<< my_group << endl;
- update_group(op->get_client_inst(), my_group);
return false;
}
}
void OSD::update_group(entity_inst_t client, gid_t group) {
// set up reply
MOSDUpdate *update = new MOSDUpdate(group);
+ 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;
+ // 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;
+ }
+
+ // wait for reply
+ update_waiter_cond[group].push_back( &cond );
+
+ // 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;
+
+}
- // send it
- messenger->send_message(update, client);
+// gets reply for group and wakes up waiters
+void OSD::handle_osd_update_reply(MOSDUpdateReply *m) {
+
+ // store the new list into group
+ gid_t my_group = m->get_group();
+
+ cout << "hande_osd_update_reply for " << my_group << endl;
+ dout(10) << "hande_osd_update_reply for " << my_group << endl;
+
+ // add the new list to our cache
+ unix_groups[my_group].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();
+ }
+
+ update_waiter_cond.erase(my_group);
}
// assumes the request and cap contents has already been checked
case MSG_OSD_OPREPLY:
handle_op_reply((MOSDOpReply*)m);
break;
+ // for updating security groups
+ case MSG_OSD_UPDATE_REPLY:
+ handle_osd_update_reply((MOSDUpdateReply*)m);
+ break;
default:
#include "messages/MOSDOp.h"
#include "messages/MOSDUpdate.h"
+#include "messages/MOSDUpdateReply.h"
#include "crypto/CryptoLib.h"
using namespace CryptoLib;
#include "crypto/CapCache.h"
#include "crypto/CapGroup.h"
+#include "crypto/MerkleTree.h"
class Messenger;
class Message;
hash_map<int, float> peer_qlen;
// unix group cache
- map<gid_t, CapGroup> unix_groups;
+ //map<gid_t, CapGroup> unix_groups;
+ map<hash_t, CapGroup> user_groups;
+ //map<gid_t, list<Cond*> > update_waiter_cond;
+ map<hash_t, list<Cond*> > update_waiter_cond;
+ void handle_osd_update_reply(MOSDUpdateReply *m);
// per-pg locking (serializing)
hash_set<pg_t> pg_lock;