Skip to content

Commit

Permalink
Implement fcntl file locks
Browse files Browse the repository at this point in the history
  • Loading branch information
tbodt committed Feb 3, 2019
1 parent c64eac4 commit 71c5ef4
Show file tree
Hide file tree
Showing 7 changed files with 367 additions and 6 deletions.
65 changes: 63 additions & 2 deletions fs/fd.c
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
#include <stdlib.h>
#include <string.h>
#include "debug.h"
#include "kernel/task.h"
#include "kernel/errno.h"
#include "kernel/calls.h"
#include "kernel/resource.h"
#include "kernel/fs.h"
#include "fs/poll.h"
Expand Down Expand Up @@ -207,6 +206,8 @@ static int fdtable_close(struct fdtable *table, fd_t f) {
struct fd *fd = fdtable_get(table, f);
if (fd == NULL)
return _EBADF;
if (fd->inode != NULL) // temporary hack for files like sockets that right now don't have inodes but will eventually
file_lock_remove_owned_by(fd, table);
int err = fd_close(fd);
table->files[f] = NULL;
bit_clear(f, table->cloexec);
Expand Down Expand Up @@ -239,6 +240,13 @@ void fdtable_do_cloexec(struct fdtable *table) {
#define F_GETFL_ 3
#define F_SETFL_ 4

#define F_GETLK_ 5
#define F_SETLK_ 6
#define F_SETLKW_ 7
#define F_GETLK64_ 12
#define F_SETLK64_ 13
#define F_SETLKW64_ 14

dword_t sys_dup(fd_t f) {
struct fd *fd = f_get(f);
if (fd == NULL)
Expand Down Expand Up @@ -280,6 +288,9 @@ dword_t sys_fcntl64(fd_t f, dword_t cmd, dword_t arg) {
struct fd *fd = f_get(f);
if (fd == NULL)
return _EBADF;
struct flock32_ flock32;
struct flock_ flock;
int err;
switch (cmd) {
case F_DUPFD_:
STRACE("fcntl(%d, F_DUPFD, %d)", f, arg);
Expand All @@ -304,6 +315,56 @@ dword_t sys_fcntl64(fd_t f, dword_t cmd, dword_t arg) {
STRACE("fcntl(%d, F_SETFL, %#x)", f, arg);
return fd_setflags(fd, arg);

case F_GETLK_:
STRACE("fcntl(%d, F_GETLK, %#x)", f, arg);
if (user_read(arg, &flock32, sizeof(flock32)))
return _EFAULT;
flock.type = flock32.type;
flock.whence = flock32.whence;
flock.start = flock32.start;
flock.len = flock32.len;
flock.pid = flock32.pid;
err = fcntl_getlk(fd, &flock);
if (err >= 0) {
flock32.type = flock.type;
flock32.whence = flock.whence;
flock32.start = flock.start;
flock32.len = flock.len;
flock32.pid = flock.pid;
if (user_write(arg, &flock32, sizeof(flock32)))
return _EFAULT;
}
return err;

case F_GETLK64_:
STRACE("fcntl(%d, F_GETLK64, %#x)", f, arg);
if (user_read(arg, &flock, sizeof(flock)))
return _EFAULT;
err = fcntl_getlk(fd, &flock);
if (err >= 0)
if (user_write(arg, &flock, sizeof(flock)))
return _EFAULT;
return err;

case F_SETLK_:
case F_SETLKW_:
STRACE("fcntl(%d, F_SETLK%*s, %#x)", f, cmd == F_SETLKW_, "W", arg);
if (user_read(arg, &flock32, sizeof(flock32)))
return _EFAULT;
flock.type = flock32.type;
flock.whence = flock32.whence;
flock.start = flock32.start;
flock.len = flock32.len;
flock.pid = flock32.pid;
return fcntl_setlk(fd, &flock, cmd == F_SETLKW64_);

case F_SETLK64_:
case F_SETLKW64_:
STRACE("fcntl(%d, F_SETLK%*s64, %#x)", f, cmd == F_SETLKW_, "W", arg);
if (user_read(arg, &flock, sizeof(flock)))
return _EFAULT;
return fcntl_setlk(fd, &flock, cmd == F_SETLKW_);

default:
STRACE("fcntl(%d, %d)", f, cmd);
return _EINVAL;
Expand Down
2 changes: 1 addition & 1 deletion fs/fd.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ struct fd {

// fs/inode data
struct mount *mount;
int real_fd; // seeks on this fd require the lock
int real_fd; // seeks on this fd require the lock TODO think about making a special lock just for that
DIR *dir;
struct inode_data *inode;
ino_t fake_inode;
Expand Down
3 changes: 3 additions & 0 deletions fs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,11 @@ struct inode_data *inode_get(struct mount *mount, ino_t ino) {
inode->number = ino;
mount_retain(mount);
inode->mount = mount;
cond_init(&inode->posix_unlock);
list_init(&inode->posix_locks);
list_init(&inode->chain);
lock_init(&inode->lock);
list_add(&inodes_hash[index], &inode->chain);

out:
lock(&inode->lock);
Expand Down
45 changes: 43 additions & 2 deletions fs/inode.h
Original file line number Diff line number Diff line change
@@ -1,21 +1,62 @@
#ifndef FS_INODE_H
#define FS_INODE_H
#include <sys/types.h>
#include "misc.h"
#include "util/list.h"
#include "util/sync.h"
struct mount;
struct fd;

struct inode_data {
unsigned refcount;
ino_t number;
struct mount *mount;
struct list chain;
// useful stuff will go here blah blah blah blah blah
// fcntl lock management

struct list posix_locks;
cond_t posix_unlock;
lock_t lock;
};

struct inode_data *inode_get(struct mount *mount, ino_t inode);
void inode_retain(struct inode_data *inode);
void inode_release(struct inode_data *inode);

// file locking stuff (maybe should go in kernel/calls.h?)

#define F_RDLCK_ 0
#define F_WRLCK_ 1
#define F_UNLCK_ 2

struct file_lock {
off_t_ start;
off_t_ end;
int type;
pid_t_ pid;
void *owner;
struct list locks;
};

struct flock_ {
word_t type;
word_t whence;
off_t_ start;
off_t_ len;
pid_t_ pid;
} __attribute__((packed));
struct flock32_ {
word_t type;
word_t whence;
dword_t start;
dword_t len;
pid_t_ pid;
} __attribute__((packed));

int fcntl_getlk(struct fd *fd, struct flock_ *flock);
// cmd should be either F_SETLK or F_SETLKW
int fcntl_setlk(struct fd *fd, struct flock_ *flock, bool block);

// locks the inode internally
void file_lock_remove_owned_by(struct fd *fd, void *owner);

#endif
Loading

0 comments on commit 71c5ef4

Please sign in to comment.