Commit 32ecf3ff authored by Muktesh Khole's avatar Muktesh Khole Committed by Vikram Narayanan

added revoke feature

parent e1045ef9
......@@ -84,6 +84,7 @@ struct cnode *lcd_cnode_lookup(struct cspace *cspace, capability_t cap, bool all
cnode = &(table->cnode[levelId]);
if (alloc) {
spin_lock_init(&cnode->lock);
cnode->cap = cap;
cnode->cspace = cspace;
}
} else {
......@@ -127,6 +128,7 @@ int lcd_cap_insert(struct cspace *cspace, capability_t cap,
cdt_node = kmem_cache_alloc(cspace->cdt_root_cache, 0);
spin_unlock_irqrestore(&cspace->lock, flags);
cnode->cap = cap;
cnode->cspace = cspace;
cnode->parent = NULL;
cnode->next = NULL;
......@@ -180,7 +182,7 @@ void lcd_cap_delete(struct cspace *cspace, capability_t cap) {
if (spin_trylock(&cnode->cdt_root->lock)) {
cdt_node = cnode->cdt_root;
last_node = _lcd_delete_node(cspace, cnode);
last_node = _lcd_delete_node(cnode);
if (last_node) {
cdt_node->state = ALLOCATION_MARKED_FOR_DELETE;
}
......@@ -207,7 +209,7 @@ void lcd_cap_delete(struct cspace *cspace, capability_t cap) {
} else {
// someone is using CDT root
// wait for him to finish
msleep(5);
msleep(1);
}
} while (!done);
};
......@@ -281,6 +283,7 @@ int lcd_cap_grant(struct cspace *cspacesrc, capability_t capsrc, struct cspace *
cnodedst->parent = cnodesrc;
cnodedst->type = cnodesrc->type;
cnodedst->object = cnodesrc->object;
cnodedst->cap = capdst;
cnodedst->cspace = cspacedst;
cnodedst->cdt_root = cnodesrc->cdt_root;
if (cnodesrc->child) {
......@@ -305,13 +308,135 @@ int lcd_cap_grant(struct cspace *cspacesrc, capability_t capsrc, struct cspace *
if (!done) {
// someone is using CDT root
// wait for him to finish
msleep(5);
msleep(1);
}
} while (!done);
return 0;
};
EXPORT_SYMBOL(lcd_cap_grant);
int lcd_cap_revoke(struct cspace *cspace, capability_t cap) {
struct cnode *cnode, *childnode;
unsigned long flags, flags_cnode_lock;
bool done = false, last_node;
struct cdt_root_node *cdt_node = NULL;
do {
spin_lock_irqsave(&cspace->lock, flags);
if (cspace->state != ALLOCATION_VALID) {
// TBD: not clear what needs to be done here - return with error or continue revoke operation down the hierarchy?
// AI: Anton, Muktesh
// current state: simply return if the root cspace is not valid.
printk(KERN_INFO "lcd_cap_revoke cspace allocation is not valid\n");
spin_unlock_irqrestore(&cspace->lock, flags);
return -EINVAL;
}
cnode = lcd_cnode_lookup(cspace, cap, false);
if(cnode == NULL)
{
printk(KERN_INFO "lcd_cap_delete cnode not found\n");
spin_unlock_irqrestore(&cspace->lock, flags);
return -EINVAL;
}
spin_lock_irqsave(&cnode->lock, flags_cnode_lock);
spin_unlock_irqrestore(&cspace->lock, flags);
if (cnode->type == LCD_CAP_TYPE_FREE) {
printk(KERN_INFO "lcd_cap_delete cnode is already free\n");
spin_unlock_irqrestore(&cnode->lock, flags_cnode_lock);
return -EINVAL;
}
if (spin_trylock(&cnode->cdt_root->lock)) {
cdt_node = cnode->cdt_root;
// get the subtree rooted at cnode out of CDT
if (cdt_node->cnode == cnode) {
if (cnode->next) {
// this is not possible untill we implement capability mint/duplicate feature
cdt_node->cnode = cnode->next;
cnode->next->prev = NULL;
cnode->next = NULL;
} else {
cdt_node->cnode = NULL;
}
} else {
if (cnode->parent) {
if (cnode->parent->child == cnode) {
if (cnode->next) {
cnode->parent->child = cnode->next;
cnode->next->prev = NULL;
cnode->next = NULL;
} else {
cnode->parent->child = NULL;
}
} else {
if (cnode->prev) {
cnode->prev->next = cnode->next;
}
if (cnode->next) {
cnode->next->prev = cnode->prev;
}
cnode->next = NULL;
cnode->prev = NULL;
}
cnode->parent = NULL;
}
}
// cnode is now isolated from CDT, before unlocking mark it invalid
cnode->type = LCD_CAP_TYPE_INVALID;
spin_unlock_irqrestore(&cnode->lock, flags_cnode_lock);
// no one else can modify the CDT relationships as long as we hold CDT lock
while (cnode->child) {
childnode = cnode->child;
spin_lock_irqsave(&childnode->lock, flags_cnode_lock);
cspace = childnode->cspace;
cap = childnode->cap;
_lcd_delete_node(childnode);
childnode->cdt_root = NULL;
spin_unlock_irqrestore(&childnode->lock, flags_cnode_lock);
lcd_free_cap(&(cspace->cap_cache), cap);
}
spin_lock_irqsave(&cnode->lock, flags_cnode_lock);
cspace = cnode->cspace;
cap = cnode->cap;
last_node = _lcd_delete_node(cnode);
if (last_node) {
cdt_node->state = ALLOCATION_MARKED_FOR_DELETE;
}
cnode->cdt_root = NULL;
spin_unlock(&(cdt_node->lock));
done = true;
}
spin_unlock_irqrestore(&cnode->lock, flags_cnode_lock);
if (done) {
lcd_free_cap(&(cspace->cap_cache), cap);
if (last_node) {
// at this point we are not holding any locks
// so its ok to request for cspace lock
spin_lock_irqsave(&cspace->lock, flags);
if (cspace->state != ALLOCATION_VALID) {
spin_unlock_irqrestore(&cspace->lock, flags);
return 0;
}
cdt_node->state = ALLOCATION_REMOVED;
kmem_cache_free(cspace->cdt_root_cache, cdt_node);
spin_unlock_irqrestore(&(cspace->lock), flags);
}
} else {
// someone is using CDT root
// wait for him to finish
msleep(1);
}
} while (!done);
return 0;
};
EXPORT_SYMBOL(lcd_cap_revoke);
int lcd_cnode_insert(struct cspace *cspace, capability_t cap, struct cnode *cnode) {
/* XXX: not clear */
......@@ -356,7 +481,7 @@ bool _get_level_bits(int table_level, capability_t cap, capability_t *levelId)
}
// assumes cnode and cdt root is locked (in that order)
bool _lcd_delete_node (struct cspace *cspace, struct cnode *cnode){
bool _lcd_delete_node (struct cnode *cnode){
bool last_node;
cnode->object = NULL;
......
......@@ -2,16 +2,18 @@
#define TEST_PASSED true
#define TEST_FAILED false
int test_cap_count = 0, test_cap_grant_count = 0;
struct cspace test_cspace, test_cspace_grant;
int test_cap_count = 0, test_cap_grant_count = 0, test_cap_grant_count2=0;
struct cspace test_cspace, test_cspace_grant, test_cspace_grant2;
int test_max_cap = 4 * MAX_CAP_SLOTS;
capability_t arr[4 * MAX_CAP_SLOTS] = {0};
capability_t arr_grant[4 * MAX_CAP_SLOTS] = {0};
capability_t arr_grant2[4 * MAX_CAP_SLOTS] = {0};
bool begintests(void) {
bool res;
lcd_init_cspace(&test_cspace);
lcd_init_cspace(&test_cspace_grant);
lcd_init_cspace(&test_cspace_grant2);
res = test_insert();
if (res == TEST_FAILED) {
printk(KERN_ERR "lcd_cap_test test_insert() failed\n");
......@@ -26,7 +28,14 @@ bool begintests(void) {
} else {
printk(KERN_INFO "lcd_cap_test test_grant() Succeeded\n");
}
test_delete();
// test_delete();
res = test_revoke();
if (res == TEST_FAILED) {
printk(KERN_ERR "lcd_cap_test test_revoke() failed\n");
return false;
} else {
printk(KERN_INFO "lcd_cap_test test_revoke() Succeeded\n");
}
return true;
}
......@@ -73,6 +82,23 @@ bool test_grant(void) {
return false;
}
}
for (i = 0; i < test_cap_count; i++) {
if (lcd_alloc_cap(&(test_cspace_grant2.cap_cache), &capdst) == 0) {
capsrc = arr[i];
res = lcd_cap_grant(&test_cspace, capsrc, &(test_cspace_grant2), capdst);
if (res == 0) {
arr_grant2[test_cap_grant_count2++] = capdst;
printk(KERN_INFO "lcd_cap_test grant2 capability # %llu to %llu succeeded\n", capsrc, capdst);
} else {
printk(KERN_ERR "lcd_cap_test grant2 capability # %llu to %llu failed\n", capsrc, capdst);
return false;
}
} else {
printk(KERN_ERR "lcd_cap_test grant2 failed to allcoate capability\n");
return false;
}
}
return true;
}
......@@ -89,4 +115,30 @@ void test_delete(void) {
printk(KERN_INFO "lcd_cap_test deleted granted capability # %llu\n", arr_grant[i]);
}
test_cap_grant_count = 0;
for (i = 0; i < test_cap_grant_count2; i++) {
lcd_cap_delete(&test_cspace_grant2, arr_grant2[i]);
printk(KERN_INFO "lcd_cap_test deleted granted2 capability # %llu\n", arr_grant2[i]);
}
test_cap_grant_count2 = 0;
}
bool test_revoke() {
// this inherently tests delete functionality
int i = 0;
int res;
bool ret = true;
for (; i < test_cap_count; i++) {
res = lcd_cap_revoke(&test_cspace, arr[i]);
ret = ret & (res == 0);
if (res == 0) {
printk(KERN_INFO "lcd_cap_test revoked capability # %llu\n", arr[i]);
} else {
printk(KERN_ERR "lcd_cap_test FAILED to revoke capability # %llu\n", arr[i]);
}
}
test_cap_count = 0;
test_cap_grant_count = 0;
test_cap_grant_count2 = 0;
return ret;
}
\ No newline at end of file
......@@ -7,5 +7,6 @@ extern void lcd_cap_delete(struct cspace *cspace, capability_t cap);
bool test_insert(void);
bool test_grant(void);
void test_delete(void);
bool test_revoke(void);
bool begintests(void);
\ No newline at end of file
......@@ -53,6 +53,7 @@ struct cnode {
spinlock_t lock;
struct cdt_root_node *cdt_root;
struct cnode *parent, *child, *prev, *next;
capability_t cap;
struct cspace *cspace;
};
......@@ -72,7 +73,7 @@ struct cspace {
};
bool _get_level_bits(int table_level, capability_t cap, capability_t *levelId);
bool _lcd_delete_node (struct cspace *cspace, struct cnode *cnode);
bool _lcd_delete_node (struct cnode *cnode);
int lcd_cap_init_cspace(struct cspace *cspace);
struct cnode *lcd_cnode_lookup(struct cspace *cspace, capability_t cap, bool alloc);
......@@ -80,5 +81,5 @@ int lcd_cap_insert(struct cspace *cspace, capability_t cap,
void *object, enum lcd_cap_type type);
void lcd_cap_delete(struct cspace *cspace, capability_t cap);
int lcd_cap_grant(struct cspace *cspacesrc, capability_t capsrc, struct cspace *cspacedst, capability_t capdst);
int lcd_cap_revoke(struct cspace *cspace, capability_t cap);
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment