execve working from vfs executable file along with clone/fork/exit

This commit is contained in:
Bahadir Balban
2008-12-02 18:29:40 +02:00
parent 32b3dfe91d
commit 9123eb49a8
10 changed files with 64 additions and 33 deletions

View File

@@ -123,10 +123,7 @@ int do_execve(struct tcb *sender, char *filename, struct args_struct *args,
/* Find the thread group leader of sender */
BUG_ON(!(tgleader = find_task(sender->tgid)));
/*
* Destroy all children threads.
* TODO: Set up parents for children's children
*/
/* Destroy all children threads. */
list_for_each_entry(thread, &tgleader->children, child_ref)
do_exit(thread, 0);
} else {
@@ -134,18 +131,12 @@ int do_execve(struct tcb *sender, char *filename, struct args_struct *args,
tgleader = sender;
}
/* Copy data to new task that is to be retained from exec'ing task */
new_task->tid = tgleader->tid;
new_task->spid = tgleader->spid;
new_task->tgid = tgleader->tgid;
new_task->pagerid = tgleader->pagerid;
new_task->utcb = tgleader->utcb;
/*
* Copy data to be retained from exec'ing task to new one.
* Release all task resources, do everything done in
* exit() except destroying the actual thread.
*/
if ((err = execve_recycle_task(tgleader)) < 0) {
if ((err = execve_recycle_task(new_task, tgleader)) < 0) {
vm_file_put(vmfile);
kfree(new_task);
return err;

View File

@@ -69,17 +69,36 @@ int task_close_files(struct tcb *task)
}
/* Prepare old task's environment for new task */
int execve_recycle_task(struct tcb *task)
int execve_recycle_task(struct tcb *new, struct tcb *orig)
{
int err;
struct task_ids ids = {
.tid = task->tid,
.spid = task->spid,
.tgid = task->tgid,
.tid = orig->tid,
.spid = orig->spid,
.tgid = orig->tgid,
};
/*
* Copy data to new task that is
* to be retained from original
*/
/* Copy ids */
new->tid = orig->tid;
new->spid = orig->spid;
new->tgid = orig->tgid;
new->pagerid = orig->pagerid;
/* Copy utcb */
new->utcb = orig->utcb;
/* Copy parent relationship */
BUG_ON(new->parent);
new->parent = orig->parent;
list_add(&new->child_ref, &orig->parent->children);
/* Flush all IO on task's files and close fds */
task_close_files(task);
task_close_files(orig);
/* Vfs still knows the thread */
@@ -88,12 +107,12 @@ int execve_recycle_task(struct tcb *task)
/* Ask the kernel to recycle the thread */
if ((err = l4_thread_control(THREAD_RECYCLE, &ids)) < 0) {
printf("%s: Suspending thread %d failed with %d.\n",
__FUNCTION__, task->tid, err);
__FUNCTION__, orig->tid, err);
return err;
}
/* Destroy the locally known tcb */
tcb_destroy(task);
tcb_destroy(orig);
return 0;
}

View File

@@ -22,9 +22,14 @@
/* Given a page and the vma it is in, returns that page's virtual address */
unsigned long vma_page_to_virtual(struct vm_area *vma, struct page *p)
unsigned long vma_page_to_virtual(struct vm_area *vma, struct page *page)
{
return __pfn_to_addr(vma->pfn_start + p->offset);
unsigned long virtual_pfn = vma->pfn_start + page->offset - vma->file_offset;
/* Page must be contained in vma's pages */
BUG_ON(vma->file_offset > page->offset);
return __pfn_to_addr(virtual_pfn);
}
unsigned long fault_to_file_offset(struct fault_data *fault)

View File

@@ -97,14 +97,23 @@ int task_insert_vma(struct vm_area *this, struct list_head *vma_list)
BUG();
}
/* Search an empty space in the task's mmapable address region. */
/*
* Search an empty space in the task's mmapable address region.
*
* This does a less than O(n) algorithm by starting the estimated region
* and vma comparison from the beginning, once a vma is not intersected
* that means it is an available slot. However if vma's and estimated
* region does not go head-to-head for comparison, individual intersection
* checks would be meaningless since any other vma could be intersecting.
* Therefore head-to-head comparison is essential here.
*/
unsigned long find_unmapped_area(unsigned long npages, struct tcb *task)
{
unsigned long pfn_start = __pfn(task->map_start);
unsigned long pfn_start = __pfn(task->start);
unsigned long pfn_end = pfn_start + npages;
struct vm_area *vma;
if (npages > __pfn(task->map_end - task->map_start))
if (npages > __pfn(task->end - task->start))
return 0;
/* If no vmas, first map slot is available. */

View File

@@ -497,6 +497,12 @@ int task_mmap_segments(struct tcb *task, struct vm_file *file, struct exec_file_
//struct vm_file *shm;
int err;
/* Set up task's user boundary regions */
task->start = USER_AREA_START;
task->end = USER_AREA_END;
task->map_start = task->start;
task->map_end = task->end;
/* mmap task's text to task's address space. */
if (IS_ERR(mapped = do_mmap(file, efd->text_offset, task, task->text_start,
VM_READ | VM_WRITE | VM_EXEC | VMA_PRIVATE,