diff options
author | Alex Auvolat <alex.auvolat@ens.fr> | 2015-02-19 20:18:39 +0100 |
---|---|---|
committer | Alex Auvolat <alex.auvolat@ens.fr> | 2015-02-19 20:18:39 +0100 |
commit | f876e66e717c4dd853da12892048262afe47ffdf (patch) | |
tree | bc7aa8ebfbb86bfa0a443fda718569a6c9e51e82 /src | |
parent | 7b27ab493b56f9e77d805c4f44a1717f3a79231e (diff) | |
download | kogata-f876e66e717c4dd853da12892048262afe47ffdf.tar.gz kogata-f876e66e717c4dd853da12892048262afe47ffdf.zip |
Add syscall for ioctl on open handle
Diffstat (limited to 'src')
-rw-r--r-- | src/common/include/fs.h | 1 | ||||
-rw-r--r-- | src/common/include/syscallproto.h | 5 | ||||
-rw-r--r-- | src/kernel/include/vfs.h | 12 | ||||
-rw-r--r-- | src/kernel/user/syscall.c | 10 | ||||
-rw-r--r-- | src/kernel/user/vfs.c | 13 | ||||
-rw-r--r-- | src/lib/include/syscall.h | 1 | ||||
-rw-r--r-- | src/lib/libkogata/syscall.c | 3 |
7 files changed, 39 insertions, 6 deletions
diff --git a/src/common/include/fs.h b/src/common/include/fs.h index 1ee3d5e..b3a618b 100644 --- a/src/common/include/fs.h +++ b/src/common/include/fs.h @@ -20,6 +20,7 @@ #define FM_CREATE (0x10) #define FM_TRUNC (0x20) #define FM_APPEND (0x40) +#define FM_IOCTL (0x80) #define FM_DCREATE (0x100) // create file in directory #define FM_DMOVE (0x200) // move file from directory #define FM_DUNLINK (0x400) // delete file from directory diff --git a/src/common/include/syscallproto.h b/src/common/include/syscallproto.h index 8c86762..ede8cb1 100644 --- a/src/common/include/syscallproto.h +++ b/src/common/include/syscallproto.h @@ -16,7 +16,7 @@ #define SC_DELETE 21 // args: file, file_strlen #define SC_MOVE 22 // args: old_file, old_file_strlen, new_file, new_file_strlen #define SC_STAT 23 // args: file, file_strlen, out stat_t* data -#define SC_IOCTL 24 // args: file, file_strlen, code, out void* data +#define SC_IOCTL 24 // args: file, file_strlen, command, out void* data #define SC_OPEN 30 // args: file, file_strlen, mode #define SC_CLOSE 31 // args: fd @@ -24,7 +24,8 @@ #define SC_WRITE 33 // args: fd, offset, size, data #define SC_READDIR 34 // args: fd, out dirent_t *data #define SC_STAT_OPEN 35 // args: fd, out stat_t *data -- stat on open file handle -#define SC_GET_MODE 36 // args: fd -- get mode for open file handle +#define SC_IOCTL_OPEN 36 // args: fd, command, out void* data +#define SC_GET_MODE 37 // args: fd -- get mode for open file handle #define SC_MAKE_FS 40 #define SC_FS_ADD_SRC 41 diff --git a/src/kernel/include/vfs.h b/src/kernel/include/vfs.h index 37b28b9..bae4e6f 100644 --- a/src/kernel/include/vfs.h +++ b/src/kernel/include/vfs.h @@ -18,10 +18,15 @@ // some data managed by the underlying filesystem. The following types are aliases to void*, // but are used to disambiguate the different types of void* : fs_handle_ptr, fs_node_ptr, fs_ptr +// Conventions : +// - ioctl returns negative values on error. null or positives are valid return values from underlying +// driver + // About thread safety : -// - The VFS implements a locking mechanism on handles so that only one operation is executed -// at the same time on a given handle -// - Same for FS nodes +// - The VFS implements a locking mechanism on FS nodes so that only one operation is executed +// at the same time on a given node (including: open, stat, walk, delete, move, create, ioctl) +// - The VFS does not implement locks on handles : several simultaneous read/writes are possible, and +// it is the driver's responsiblity to prevent that if necessary // - The VFS does not lock nodes that have a handle open to them : it is the FS code's responsibility // to refuse some commands if neccessary on a node that is open. // - The VFS does not implement any locking mechanism on filesystems themselves (e.g. the add_source @@ -166,6 +171,7 @@ int file_get_mode(fs_handle_t *f); size_t file_read(fs_handle_t *f, size_t offset, size_t len, char* buf); size_t file_write(fs_handle_t *f, size_t offset, size_t len, const char* buf); bool file_stat(fs_handle_t *f, stat_t *st); +int file_ioctl(fs_handle_t *f, int command, void* data); bool file_readdir(fs_handle_t *f, dirent_t *d); /* vim: set ts=4 sw=4 tw=0 noet :*/ diff --git a/src/kernel/user/syscall.c b/src/kernel/user/syscall.c index 8a2cf18..6fdd633 100644 --- a/src/kernel/user/syscall.c +++ b/src/kernel/user/syscall.c @@ -263,6 +263,15 @@ static uint32_t stat_open_sc(sc_args_t args) { return file_stat(h, o); } +static uint32_t ioctl_open_sc(sc_args_t args) { + fs_handle_t *h = proc_read_fd(current_process(), args.a); + if (h == 0) return -1; + + void* data = (void*)args.c; + if (data >= (void*)K_HIGHHALF_ADDR) return -1; + return file_ioctl(h, args.b, data); +} + static uint32_t get_mode_sc(sc_args_t args) { fs_handle_t *h = proc_read_fd(current_process(), args.a); if (h == 0) return 0; @@ -296,6 +305,7 @@ void setup_syscall_table() { sc_handlers[SC_WRITE] = write_sc; sc_handlers[SC_READDIR] = readdir_sc; sc_handlers[SC_STAT_OPEN] = stat_open_sc; + sc_handlers[SC_IOCTL_OPEN] = ioctl_open_sc; sc_handlers[SC_GET_MODE] = get_mode_sc; } diff --git a/src/kernel/user/vfs.c b/src/kernel/user/vfs.c index a5d56ef..ab49553 100644 --- a/src/kernel/user/vfs.c +++ b/src/kernel/user/vfs.c @@ -356,7 +356,7 @@ bool fs_stat(fs_t *fs, const char* file, stat_t *st) { int fs_ioctl(fs_t *fs, const char* file, int command, void* data) { fs_node_t* n = fs_walk_path(&fs->root, file); - if (n == 0) return false; + if (n == 0) return -1; mutex_lock(&n->lock); int ret = (n->ops->ioctl ? n->ops->ioctl(n->data, command, data) : -1); @@ -461,6 +461,17 @@ bool file_stat(fs_handle_t *f, stat_t *st) { return ret; } +int file_ioctl(fs_handle_t *f, int command, void* data) { + if (!(f->mode & FM_IOCTL)) return -1; + + mutex_lock(&f->node->lock); + int ret = -1; + if (f->node->ops->ioctl) ret = f->node->ops->ioctl(f->node->data, command, data); + mutex_unlock(&f->node->lock); + + return ret; +} + bool file_readdir(fs_handle_t *f, dirent_t *d) { if (!(f->mode & FM_READDIR)) return 0; diff --git a/src/lib/include/syscall.h b/src/lib/include/syscall.h index 3d9fcd5..0f1efb0 100644 --- a/src/lib/include/syscall.h +++ b/src/lib/include/syscall.h @@ -33,6 +33,7 @@ size_t read(fd_t file, size_t offset, size_t len, char *buf); size_t write(fd_t file, size_t offset, size_t len, const char* buf); bool readdir(fd_t file, dirent_t *d); bool stat_open(fd_t file, stat_t *s); +int ioctl_open(fd_t file, int command, void* data); int get_mode(fd_t file); // more todo diff --git a/src/lib/libkogata/syscall.c b/src/lib/libkogata/syscall.c index 008a2a9..2e0ef0f 100644 --- a/src/lib/libkogata/syscall.c +++ b/src/lib/libkogata/syscall.c @@ -82,6 +82,9 @@ bool readdir(fd_t file, dirent_t *d) { bool stat_open(fd_t file, stat_t *s) { return call(SC_STAT_OPEN, file, (uint32_t)s, 0, 0, 0); } +int ioctl_open(fd_t file, int command, void* data) { + return call(SC_IOCTL_OPEN, file, command, (uint32_t)data, 0, 0); +} int get_mode(fd_t file) { return call(SC_GET_MODE, file, 0, 0, 0, 0); } |