Commit a9f7de98 authored by Léo Grange's avatar Léo Grange
Browse files

improve memory areas integration

parent 61093179
Loading
Loading
Loading
Loading
+22 −4
Original line number Diff line number Diff line
@@ -4,17 +4,21 @@
#include <fs/inode.h>
#include <interface/fixos/errno.h>
#include "smemfs_primitives_ng.h"
// used for memory areas...
#include <fs/vfs_file.h>


const struct file_operations smemfs_file_operations = {
	.release = smemfs_release,
	.read = smemfs_read,
	.lseek = smemfs_lseek
	.lseek = smemfs_lseek,
	.map_area = smemfs_map_area
};


const struct mem_area_ops smemfs_mem_ops = {
	.area_pagefault = smemfs_area_pagefault
	.area_pagefault = smemfs_area_pagefault,
	.area_release = smemfs_area_release
};


@@ -140,6 +144,17 @@ off_t smemfs_lseek (struct file *filep, off_t offset, int whence) {
}



int smemfs_map_area(struct file *filep, struct mem_area *area) {
	// not a lot of stuff to do for now...
	area->ops = &smemfs_mem_ops;
	area->file.filep = filep;
	// increase file usage count (mirrored in smemfs_area_release)
	filep->count++;
	return 0;
}


union pm_page smemfs_area_pagefault(struct mem_area *area, void *addr_fault) {
	size_t readsize;
	void *pmaddr;
@@ -179,10 +194,13 @@ union pm_page smemfs_area_pagefault(struct mem_area *area, void *addr_fault) {
	return pmpage;
}

int smemfs_area_resize(struct mem_area *area, const struct mem_area *new_area) {
/*
int smemfs_area_resize(struct mem_area *area, size_t new_size) {
	return -1;
}
*/

void smemfs_area_release(struct mem_area *area) {

	// release the file, by closing it at vfs level?
	vfs_close(area->file.filep);
}
+2 −0
Original line number Diff line number Diff line
@@ -24,6 +24,8 @@ off_t smemfs_lseek (struct file *filep, off_t offset, int whence);


// memory-mapped operations
int smemfs_map_area(struct file *filep, struct mem_area *area);

union pm_page smemfs_area_pagefault(struct mem_area *area, void *addr_fault);

int smemfs_area_resize(struct mem_area *area, const struct mem_area *new_area);
+20 −0
Original line number Diff line number Diff line
@@ -15,6 +15,8 @@

struct file;

struct mem_area;

struct file_operations {
	/**
	 * Release the file opened instance ("close" it).
@@ -47,6 +49,24 @@ struct file_operations {
	 * data is specific to command and device, may be not used.
	 */
	int (*ioctl) (struct file *filep, int cmd, void *data);


	/**
	 * Create a memory map of this object in memory.
	 * Devices may use it as they want to, for example to provide big buffers
	 * shared with userland.
	 * area should be set with all non-private fields having a valid value,
	 * which is not very well defined...
	 * At least field ops is not expected to be set, but the interface is not
	 * well designed for now.
	 * TODO either use a 'hints' argument with mem_area-like type, or define
	 * exactly what should be set and what is set by this function itself
	 *
	 * NULL if device of filesystem do not implements memory mapped areas.
	 *
	 * Return 0 if mapping is accepted, negative value else.
	 */
	int (*map_area) (struct file *filep, struct mem_area *area);
};

#endif //_FS_FILE_OPERATIONS_H
+36 −0
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@
#include "file_system.h"
#include "file_operations.h"
#include "vfs_directory.h"
#include <sys/mem_area.h>


// pool allocation for file struct
@@ -157,3 +158,38 @@ int vfs_fstat(struct file *filep, struct stat *buf) {
		return -1;
	}
}


int vfs_map_area(struct file *filep, size_t size, size_t offset, void *address,
		int flags, size_t infile_size, struct process *proc)
{
	int ret = -EINVAL;

	if(filep->op->map_area != NULL) {
		struct mem_area *area;
		area = mem_area_alloc();
		if(area == NULL) {
			ret = -ENOMEM;
		}
		else {
			// prepare area struct from arguments
			area->address = address;
			area->max_size = size;
			area->flags = flags | MEM_AREA_TYPE_FILE;
			area->file.base_offset = offset;
			area->file.infile_size = (flags & MEM_AREA_PARTIAL) ? infile_size : size;
			area->file.filep = filep;
			
			ret = filep->op->map_area(filep, area);
			if(ret == 0) {
				ret = mem_area_insert(proc, area);
			}
			else {
				// failed, free area (do not *release* it, free directly)
				mem_area_free(area);
			}
		}
	}
	
	return ret;
}
+14 −0
Original line number Diff line number Diff line
@@ -90,4 +90,18 @@ int vfs_ioctl(struct file *filep, int cmd, void *data);
int vfs_fstat(struct file *filep, struct stat *buf);


struct process;

/**
 * Map size bytes of the object in memory, from given offset, to given address
 * in the address space of a given process.
 * Area permissions, and additionnal flags, may be provided, using constants
 * from sys/mem_area.h
 * from_file is important only if flag contains MEM_AREA_PARTIAL
 *
 * TODO make a 'hints' structure to reduce number of arguments?
 */
int vfs_map_area(struct file *filep, size_t size, size_t offset, void *address,
		int flags, size_t infile_size, struct process *proc);

#endif //_FS_VFS_FILE_H
Loading