Initial commit: Schunix as it stands before the SchOS rename
An x86-64 operating system built from xv6, now largely rewritten: SMP, a copy-on-write root filesystem (SchFS), PCI/USB/virtio drivers, a TTF rasteriser, and a Linux-numbered syscall ABI. No history before this point -- the tree was never under version control. This commit exists so the rename that follows has something to undo to.
This commit is contained in:
commit
d0f7acf9eb
275 changed files with 51417 additions and 0 deletions
132
include/file.h
Normal file
132
include/file.h
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
struct file {
|
||||
enum { FD_NONE, FD_PIPE, FD_INODE, FD_SOCKET } type;
|
||||
int ref; // reference count
|
||||
char readable;
|
||||
char writable;
|
||||
// O_NONBLOCK. A property of the open file description, not of the
|
||||
// descriptor, which is why it lives here and not in myproc()->ofile_flags --
|
||||
// dup() shares it and F_SETFL on either fd changes it for both, exactly as
|
||||
// POSIX says.
|
||||
char nonblock;
|
||||
struct pipe *pipe;
|
||||
struct inode *ip;
|
||||
struct socket *sock;
|
||||
uint64 off;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Filesystem operations
|
||||
//
|
||||
// One table per filesystem, chosen by iget() from the device number and hung
|
||||
// off the inode. Everything above this line -- the syscall layer, exec, the
|
||||
// page cache -- calls the wrappers in fs.c and never learns which filesystem it
|
||||
// is talking to.
|
||||
//
|
||||
// A vtable rather than a chain of `if (dev == SCHFS_DEV)` because there are two
|
||||
// filesystems today and there will be more: the whole point of the exercise is
|
||||
// that adding one is a new table, not another branch in fifteen functions.
|
||||
//
|
||||
// Every hook takes an inode that is already locked, except ialloc (which has no
|
||||
// inode yet) and iload (which is what makes one valid in the first place).
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
struct stat;
|
||||
|
||||
struct fs_ops {
|
||||
const char *name;
|
||||
|
||||
// Fill in the type/size/link fields of a freshly iget()'d inode.
|
||||
void (*iload)(struct inode *);
|
||||
// Write those fields back to disk.
|
||||
void (*istore)(struct inode *);
|
||||
// The last link is gone and nobody has it open: release the object.
|
||||
void (*ifree)(struct inode *);
|
||||
|
||||
int (*read)(struct inode *, int user_dst, uint64 dst, uint64 off, uint n);
|
||||
int (*write)(struct inode *, int user_src, uint64 src, uint64 off, uint n);
|
||||
// Set the length. Growing is allowed only where the filesystem can represent
|
||||
// the gap; v1 cannot and ignores it.
|
||||
void (*truncate)(struct inode *, uint64 newsize);
|
||||
|
||||
// Directory operations. `poff` is an opaque cookie identifying where the
|
||||
// entry lives, meaningful only to the same filesystem's dirunlink.
|
||||
struct inode *(*dirlookup)(struct inode *dp, char *name, uint *poff);
|
||||
int (*dirlink)(struct inode *dp, char *name, uint64 inum);
|
||||
int (*dirunlink)(struct inode *dp, char *name, uint off);
|
||||
int (*dirempty)(struct inode *dp);
|
||||
|
||||
// Create an object with no name yet. The caller sets nlink and calls
|
||||
// dirlink; until it does, the object is unreachable.
|
||||
struct inode *(*ialloc)(uint dev, short type);
|
||||
|
||||
// Read directory entries into a getdents64-shaped stream. `off` is an opaque
|
||||
// position that starts at 0 and is echoed back; returns bytes written, 0 at
|
||||
// the end of the directory, or negative on error.
|
||||
int (*getdents)(struct inode *dp, char *out, int cap, uint64 *off);
|
||||
};
|
||||
|
||||
// In-memory inode.
|
||||
//
|
||||
// `inum` and `size` are 64-bit because the filesystem underneath may be: SchFS
|
||||
// object ids and file sizes are both uint64 on disk, and a 32-bit copy here
|
||||
// would silently truncate them into a different file. The v1 filesystem uses a
|
||||
// small fraction of the range and is unaffected.
|
||||
struct inode {
|
||||
uint dev;
|
||||
uint64 inum;
|
||||
int ref;
|
||||
struct sleeplock lock;
|
||||
int valid;
|
||||
const struct fs_ops *ops; // chosen by iget from dev; never null once held
|
||||
|
||||
short type;
|
||||
short major;
|
||||
short minor;
|
||||
short nlink;
|
||||
uint64 size;
|
||||
|
||||
uint rwmode;
|
||||
uint supermode;
|
||||
uint showmode;
|
||||
uint atime;
|
||||
uint mtime;
|
||||
uint ctime;
|
||||
uint addrs[NDIRECT+3];
|
||||
};
|
||||
#define I_VALID 0x2
|
||||
|
||||
// Device number that means "the mounted SchFS volume". Real disks are 0 and 1,
|
||||
// and this is deliberately far from them so a stray value never looks like a
|
||||
// SchFS inode.
|
||||
#define SCHFS_DEV 64
|
||||
|
||||
// Device number that means "the synthetic /proc". Like SCHFS_DEV, it is
|
||||
// deliberately nowhere near a real disk's 0 or 1.
|
||||
#define PROCFS_DEV 65
|
||||
|
||||
// table mapping major device number to
|
||||
// device functions
|
||||
struct devsw {
|
||||
int (*read)(struct inode*, uint, char*, int);
|
||||
int (*write)(struct inode*, uint, char*, int);
|
||||
// Optional. Returns 0 when a read would block, which is the only thing
|
||||
// fileread needs to know to honour O_NONBLOCK without every device driver
|
||||
// growing a flags argument. A device that omits this is treated as always
|
||||
// ready, which is the right answer for a disk and for /dev/zero.
|
||||
int (*ready)(struct inode*);
|
||||
// Optional. The last descriptor for this open file is going away. A device
|
||||
// that hands a program exclusive-feeling control of the hardware needs this
|
||||
// to put the hardware back -- /dev/fb0 uses it to give the text console its
|
||||
// screen back when whatever was drawing on it exits.
|
||||
void (*close)(struct inode*);
|
||||
// Optional. A descriptor has just been opened on this device. /dev/input
|
||||
// uses it to discard events that arrived while nobody was listening -- see
|
||||
// inputopen().
|
||||
void (*open)(struct inode*);
|
||||
};
|
||||
|
||||
extern struct devsw devsw[];
|
||||
|
||||
#define CONSOLE 1
|
||||
// Major number of /dev/input/eventN. The minor is the device index.
|
||||
#define INPUT_MAJOR 7
|
||||
Loading…
Reference in a new issue