aboutsummaryrefslogtreecommitdiff
path: root/kernel/include/fs/vnode.h
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/include/fs/vnode.h')
-rw-r--r--kernel/include/fs/vnode.h358
1 files changed, 358 insertions, 0 deletions
diff --git a/kernel/include/fs/vnode.h b/kernel/include/fs/vnode.h
new file mode 100644
index 0000000..ff4b9be
--- /dev/null
+++ b/kernel/include/fs/vnode.h
@@ -0,0 +1,358 @@
+/*
+ * FILE: vnode.h
+ * AUTH: mcc
+ * DESC:
+ * DATE: Fri Mar 13 18:54:11 1998
+ * $Id: vnode.h,v 1.2.2.2 2006/06/04 01:02:32 afenn Exp $
+ */
+
+#pragma once
+
+#include "drivers/blockdev.h"
+#include "drivers/chardev.h"
+#include "drivers/dev.h"
+#include "mm/mobj.h"
+#include "mm/pframe.h"
+#include "proc/kmutex.h"
+#include "util/list.h"
+
+struct fs;
+struct dirent;
+struct stat;
+struct file;
+struct vnode;
+struct kmutex;
+
+#define VNODE_LOADING 0
+#define VNODE_LOADED 1
+
+typedef struct vnode_ops
+{
+ /* The following functions map directly to their corresponding
+ * system calls. Unless otherwise noted, they return 0 on
+ * success, and -errno on failure.
+ */
+
+ /* Operations that can be performed on non-directory files: */
+ /*
+ * read transfers at most count bytes from file into buf. It
+ * begins reading from the file at pos bytes into the file. On
+ * success, it returns the number of bytes transferred, or 0 if the
+ * end of the file has been reached (pos >= file->vn_len).
+ */
+ ssize_t (*read)(struct vnode *file, size_t pos, void *buf, size_t count);
+
+ /*
+ * write transfers count bytes from buf into file. It begins
+ * writing at pos bytes into the file. If offset+count extends
+ * past the end of the file, the file's length will be increased.
+ * If offset is before the end of the file, the existing data is
+ * overwritten. On success, it returns the number of bytes
+ * transferred.
+ */
+ ssize_t (*write)(struct vnode *file, size_t pos, const void *buf,
+ size_t count);
+
+ /*
+ * Implementations should supply an mobj through the "ret"
+ * argument (not by setting vma->vma_obj). If for any reason
+ * this cannot be done an appropriate error code should be
+ * returned instead.
+ */
+ long (*mmap)(struct vnode *file, struct mobj **ret);
+
+ /* Operations that can be performed on directory files: */
+
+ /*
+ * mknod creates a special specified by name and namelen in the
+ * directory pointed to by dir with the specified mode and devid.
+ *
+ * Upon success, ret must point to the newly created file.
+ */
+ long (*mknod)(struct vnode *dir, const char *name, size_t namelen, int mode,
+ devid_t devid, struct vnode **ret);
+
+ /*
+ * lookup attempts to find the file specified by name and namelen in the
+ * directory pointed to by dir.
+ *
+ * Upon success, ret must point to the child vnode.
+ */
+ long (*lookup)(struct vnode *dir, const char *name, size_t namelen,
+ struct vnode **out);
+
+ /*
+ * Creates a directory entry in dir specified by name and namelen pointing
+ * to the inode of target.
+ */
+ long (*link)(struct vnode *dir, const char *name, size_t namelen,
+ struct vnode *target);
+
+ /*
+ * unlink removes the directory entry in dir corresponding to the file
+ * specified by name and namelen.
+ */
+ long (*unlink)(struct vnode *dir, const char *name, size_t namelen);
+
+ /*
+ * rename
+ */
+ long (*rename)(struct vnode *olddir, const char *oldname, size_t oldnamelen,
+ struct vnode *newdir, const char *newname,
+ size_t newnamelen);
+
+ /*
+ * mkdir creates a directory specified by name and namelen in the
+ * directory pointed to by out.
+ *
+ * Upon success, out must point to the newly created directory.
+ * Upon failure, out must be unchanged.
+ */
+ long (*mkdir)(struct vnode *dir, const char *name, size_t namelen,
+ struct vnode **out);
+
+ /*
+ * rmdir removes the directory specified by name and namelen from dir.
+ * The directory to be removed must be empty: the only directory entries
+ * must be "." and "..".
+ */
+ long (*rmdir)(struct vnode *dir, const char *name, size_t namelen);
+
+ /*
+ * readdir reads one directory entry from the dir into the struct
+ * dirent. On success, it returns the amount that offset should be
+ * increased by to obtain the next directory entry with a
+ * subsequent call to readdir. If the end of the file as been
+ * reached (offset == file->vn_len), no directory entry will be
+ * read and 0 will be returned.
+ */
+ ssize_t (*readdir)(struct vnode *dir, size_t pos, struct dirent *d);
+
+ /* Operations that can be performed on any type of "file" (
+ * includes normal file, directory, block/byte device */
+ /*
+ * stat sets the fields in the given buf, filling it with
+ * information about file.
+ */
+ long (*stat)(struct vnode *vnode, struct stat *buf);
+
+ /*
+ * acquire is called on a vnode when a file takes its first
+ * reference to the vnode. The file is passed in.
+ */
+ long (*acquire)(struct vnode *vnode, struct file *file);
+
+ /*
+ * release is called on a vnode when the refcount of a file
+ * descriptor that has it open comes down to 0. Each call to
+ * acquire has exactly one matching call to release with the
+ * same file that was passed to acquire.
+ */
+ long (*release)(struct vnode *vnode, struct file *file);
+
+ long (*get_pframe)(struct vnode *vnode, size_t pagenum, long forwrite,
+ pframe_t **pfp);
+
+ /*
+ * Read the page of 'vnode' containing 'offset' into the
+ * page-aligned and page-sized buffer pointed to by
+ * 'buf'.
+ */
+ long (*fill_pframe)(struct vnode *vnode, pframe_t *pf);
+
+ /*
+ * Write the contents of the page-aligned and page-sized
+ * buffer pointed to by 'buf' to the page of 'vnode'
+ * containing 'offset'.
+ */
+ long (*flush_pframe)(struct vnode *vnode, pframe_t *pf);
+
+ /*
+ * This will truncate the file to have a length of zero
+ * Should only be used on regular files, not directories.
+ */
+ void (*truncate_file)(struct vnode *vnode);
+} vnode_ops_t;
+
+typedef struct vnode
+{
+ /*
+ * Function pointers to the implementations of file operations (the
+ * functions are provided by the filesystem implementation).
+ */
+ struct vnode_ops *vn_ops;
+
+ /*
+ * The filesystem to which this vnode belongs. This is initialized by
+ * the VFS subsystem when the vnode is first created and should never
+ * change.
+ */
+ struct fs *vn_fs;
+
+#ifdef __MOUNTING__
+ /* This field is used only for implementing mount points (not required) */
+ /* This field points the the root of the file system mounted at
+ * this vnode. If no file system is mounted at this point this is a
+ * self pointer (i.e. vn->vn_mount = vn). See vget for why this is
+ * makes things easier for us. */
+ struct vnode *vn_mount;
+#endif
+
+ /*
+ * The object responsible for managing the memory where pages read
+ * from this file reside. The VFS subsystem may use this field, but it
+ * does not need to create it.
+ */
+ struct mobj vn_mobj;
+
+ /*
+ * A number which uniquely identifies this vnode within its filesystem.
+ * (Similar and usually identical to what you might know as the inode
+ * number of a file).
+ */
+ ino_t vn_vno;
+
+ /*
+ * File type. See stat.h.
+ */
+ int vn_mode;
+
+ /*
+ * Length of file. Initialized at the fs-implementation-level (in the
+ * 'read_vnode' fs_t entry point). Maintained at the filesystem
+ * implementation level (within the implementations of relevant vnode
+ * entry points).
+ */
+ size_t vn_len;
+
+ /*
+ * A generic pointer which the file system can use to store any extra
+ * data it needs.
+ */
+ void *vn_i;
+
+ /*
+ * The device identifier.
+ * Only relevant to vnodes representing device files.
+ */
+ devid_t vn_devid;
+
+ /*
+ * The state of the vnode. Can either be loading or loaded. The vnode
+ * cannot be used until the vnode is in the loaded state. Potential
+ * users should wait on `vn_waitq` if the vnode is being loaded.
+ * This field is protected by the 'vn_state_lock'.
+ */
+ int vn_state;
+
+ /*
+ * Allows vnode users to wait on the vnode, until the vnode is ready.
+ */
+ ktqueue_t vn_waitq;
+
+ union {
+ chardev_t *chardev;
+ blockdev_t *blockdev;
+ } vn_dev;
+
+ /* Used (only) by the v{get,ref,put} facilities (vfs/vnode.c): */
+ list_link_t vn_link; /* link on system vnode list */
+} vnode_t;
+
+void init_special_vnode(vnode_t *vn);
+
+/* Core vnode management routines: */
+/*
+ * Obtain a vnode representing the file that filesystem 'fs' identifies
+ * by inode number 'vnum'; returns the vnode_t corresponding to the
+ * given filesystem and vnode number. If a vnode for the given file
+ * already exists (it already has an entry in the system inode table) then
+ * the reference count of that vnode is incremented and it is returned.
+ * Otherwise a new vnode is created in the system inode table with a
+ * reference count of 1.
+ * This function has no unsuccessful return.
+ *
+ * MAY BLOCK.
+ */
+struct vnode *vget(struct fs *fs, ino_t vnum);
+
+/*
+ * Lock a vnode (locks vn_mobj).
+ */
+void vlock(vnode_t *vn);
+
+/*
+ * Lock two vnodes in order! This prevents the A/B locking problem when locking
+ * two directories or two files.
+ */
+void vlock_in_order(vnode_t *a, vnode_t *b);
+
+/*
+ * Acquires a vnode locked (see vget above)
+ */
+vnode_t *vget_locked(struct fs *fs, ino_t ino);
+
+/**
+ * Unlock and put a vnode (see vput)
+ */
+void vput_locked(struct vnode **vnp);
+
+/**
+ * Unlocks a vnode
+ */
+void vunlock(vnode_t *vn);
+
+/**
+ * Unlocks two vnodes (effectively just 2 unlocks)
+ */
+void vunlock_in_order(vnode_t *a, vnode_t *b);
+
+/*
+ * Increments the reference count of the provided vnode
+ * (i.e. the refcount of vn_mobj).
+ */
+void vref(vnode_t *vn);
+
+/*
+ * This function decrements the reference count on this vnode
+ * (i.e. the refcount of vn_mobj).
+ *
+ * If, as a result of this, refcount reaches zero, the underlying
+ * fs's 'delete_vnode' entry point will be called and the vnode will be
+ * freed.
+ *
+ * If the linkcount of the corresponding on inode on the filesystem is zero,
+ * then the inode will be freed.
+ *
+ */
+void vput(vnode_t **vnp);
+
+/* Auxilliary: */
+
+/* Unmounting (shutting down the VFS) is the primary reason for the
+ * existence of the following three routines (when unmounting an s5 fs,
+ * they are used in the order that they are listed here): */
+/*
+ * Checks to see if there are any actively-referenced vnodes
+ * belonging to the specified filesystem.
+ * Returns -EBUSY if there is at least one such actively-referenced
+ * vnode, and 0 otherwise.
+ *
+ */
+long vfs_is_in_use(struct fs *fs);
+
+/*
+ * Returns the number of vnodes from this filesystem that are in
+ * use.
+ */
+size_t vfs_count_active_vnodes(struct fs *fs);
+
+/* Diagnostic: */
+/*
+ * Prints the vnodes that are in use. Specifying a fs_t will restrict
+ * the vnodes to just that fs. Specifying NULL will print all vnodes
+ * in the entire system.
+ *
+ * Note that this is currently unimplemented.
+ */
+void vnode_print(struct fs *fs);