Implement syscall_mmap to validate and then map all file data into a user address in memory
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
#include "threads/synch.h"
|
||||
#include "userprog/process.h"
|
||||
#include "userprog/pagedir.h"
|
||||
#include "vm/page.h"
|
||||
#include "vm/mmap.h"
|
||||
#include <stdio.h>
|
||||
#include <syscall-nr.h>
|
||||
@@ -404,7 +405,56 @@ syscall_close (int fd)
|
||||
static mapid_t
|
||||
syscall_mmap (int fd, void *addr)
|
||||
{
|
||||
return MMAP_FAILURE;
|
||||
/* Ensure the FD is for a file in the filesystem (not STDIN or STDOUT). */
|
||||
if (fd == STDOUT_FILENO || fd == STDIN_FILENO)
|
||||
return MMAP_FAILURE;
|
||||
|
||||
/* Validate that there is a file associated with the given FD. */
|
||||
struct open_file *file_info = fd_get_file (fd);
|
||||
if (file_info == NULL)
|
||||
return MMAP_FAILURE;
|
||||
|
||||
/* Ensure that the address is page-aligned and it's neither NULL nor zero. */
|
||||
if (addr == 0 || addr == NULL || pg_ofs (addr) != 0)
|
||||
return MMAP_FAILURE;
|
||||
|
||||
/* Reopen the file to obtain a separate and independent reference to the file
|
||||
for the mapping. */
|
||||
struct file *file = file_reopen (file_info->file);
|
||||
if (file == NULL)
|
||||
return MMAP_FAILURE;
|
||||
|
||||
/* Get the size of the file. Mmap fails if the file is empty. */
|
||||
off_t file_size = file_length (file);
|
||||
if (file_size == 0)
|
||||
return MMAP_FAILURE;
|
||||
|
||||
/* Check and ensure that there is enough space in the user virtual memory to
|
||||
hold the entire file. */
|
||||
for (off_t ofs = 0; ofs < file_size; ofs += PGSIZE)
|
||||
{
|
||||
if (page_get (addr + ofs) != NULL)
|
||||
return MMAP_FAILURE;
|
||||
}
|
||||
|
||||
/* Map the file data into the user virtual memory starting from addr. */
|
||||
for (off_t ofs = 0; ofs < file_size; ofs += PGSIZE)
|
||||
{
|
||||
off_t read_bytes = file_size - ofs < PGSIZE ? file_size - ofs : PGSIZE;
|
||||
off_t zero_bytes = PGSIZE - read_bytes;
|
||||
|
||||
if (page_insert (file, ofs, addr + ofs, read_bytes, zero_bytes, true,
|
||||
PAGE_EXECUTABLE) == NULL)
|
||||
return MMAP_FAILURE;
|
||||
}
|
||||
|
||||
/* Create a new mapping for the file. */
|
||||
struct mmap_entry *mmap = mmap_insert (file, addr);
|
||||
if (mmap == NULL)
|
||||
return MMAP_FAILURE;
|
||||
|
||||
|
||||
return mmap->mapping;
|
||||
}
|
||||
|
||||
/* Handles the syscall for unmapping a memory mapped file. */
|
||||
|
||||
Reference in New Issue
Block a user