os161/kern/include/vnode.h
2015-12-23 00:50:04 +00:00

317 lines
13 KiB
C

/*
* Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
* The President and Fellows of Harvard College.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef _VNODE_H_
#define _VNODE_H_
#include <spinlock.h>
struct uio;
struct stat;
/*
* A struct vnode is an abstract representation of a file.
*
* It is an interface in the Java sense that allows the kernel's
* filesystem-independent code to interact usefully with multiple sets
* of filesystem code.
*/
/*
* Abstract low-level file.
*
* Note: vn_fs may be null if the vnode refers to a device.
*/
struct vnode {
int vn_refcount; /* Reference count */
struct spinlock vn_countlock; /* Lock for vn_refcount */
struct fs *vn_fs; /* Filesystem vnode belongs to */
void *vn_data; /* Filesystem-specific data */
const struct vnode_ops *vn_ops; /* Functions on this vnode */
};
/*
* Abstract operations on a vnode.
*
* These are used in the form VOP_FOO(vnode, args), which are macros
* that expands to vnode->vn_ops->vop_foo(vnode, args). The operations
* "foo" are:
*
* vop_eachopen - Called on *each* open() of a file. Can be used to
* reject illegal or undesired open modes. Note that
* various operations can be performed without the
* file actually being opened.
* The vnode need not look at O_CREAT, O_EXCL, or
* O_TRUNC, as these are handled in the VFS layer.
*
* VOP_EACHOPEN should not be called directly from
* above the VFS layer - use vfs_open() to open vnodes.
*
* vop_reclaim - Called when vnode is no longer in use.
*
*****************************************
*
* vop_read - Read data from file to uio, at offset specified
* in the uio, updating uio_resid to reflect the
* amount read, and updating uio_offset to match.
* Not allowed on directories or symlinks.
*
* vop_readlink - Read the contents of a symlink into a uio.
* Not allowed on other types of object.
*
* vop_getdirentry - Read a single filename from a directory into a
* uio, choosing what name based on the offset
* field in the uio, and updating that field.
* Unlike with I/O on regular files, the value of
* the offset field is not interpreted outside
* the filesystem and thus need not be a byte
* count. However, the uio_resid field should be
* handled in the normal fashion.
* On non-directory objects, return ENOTDIR.
*
* vop_write - Write data from uio to file at offset specified
* in the uio, updating uio_resid to reflect the
* amount written, and updating uio_offset to match.
* Not allowed on directories or symlinks.
*
* vop_ioctl - Perform ioctl operation OP on file using data
* DATA. The interpretation of the data is specific
* to each ioctl.
*
* vop_stat - Return info about a file. The pointer is a
* pointer to struct stat; see kern/stat.h.
*
* vop_gettype - Return type of file. The values for file types
* are in kern/stattypes.h.
*
* vop_isseekable - Check if this file is seekable. All regular files
* and directories are seekable, but some devices are
* not.
*
* vop_fsync - Force any dirty buffers associated with this file
* to stable storage.
*
* vop_mmap - Map file into memory. If you implement this
* feature, you're responsible for choosing the
* arguments for this operation.
*
* vop_truncate - Forcibly set size of file to the length passed
* in, discarding any excess blocks.
*
* vop_namefile - Compute pathname relative to filesystem root
* of the file and copy to the specified
* uio. Need not work on objects that are not
* directories.
*
*****************************************
*
* vop_creat - Create a regular file named NAME in the passed
* directory DIR. If boolean EXCL is true, fail if
* the file already exists; otherwise, use the
* existing file if there is one. Hand back the
* vnode for the file as per vop_lookup.
*
* vop_symlink - Create symlink named NAME in the passed directory,
* with contents CONTENTS.
*
* vop_mkdir - Make directory NAME in the passed directory PARENTDIR.
*
* vop_link - Create hard link, with name NAME, to file FILE
* in the passed directory DIR.
*
* vop_remove - Delete non-directory object NAME from passed
* directory. If NAME refers to a directory,
* return EISDIR. If passed vnode is not a
* directory, return ENOTDIR.
*
* vop_rmdir - Delete directory object NAME from passed
* directory.
*
* vop_rename - Rename file NAME1 in directory VN1 to be
* file NAME2 in directory VN2.
*
*****************************************
*
* vop_lookup - Parse PATHNAME relative to the passed directory
* DIR, and hand back the vnode for the file it
* refers to. May destroy PATHNAME. Should increment
* refcount on vnode handed back.
*
* vop_lookparent - Parse PATHNAME relative to the passed directory
* DIR, and hand back (1) the vnode for the
* parent directory of the file it refers to, and
* (2) the last component of the filename, copied
* into kernel buffer BUF with max length LEN. May
* destroy PATHNAME. Should increment refcount on
* vnode handed back.
*/
#define VOP_MAGIC 0xa2b3c4d5
struct vnode_ops {
unsigned long vop_magic; /* should always be VOP_MAGIC */
int (*vop_eachopen)(struct vnode *object, int flags_from_open);
int (*vop_reclaim)(struct vnode *vnode);
int (*vop_read)(struct vnode *file, struct uio *uio);
int (*vop_readlink)(struct vnode *link, struct uio *uio);
int (*vop_getdirentry)(struct vnode *dir, struct uio *uio);
int (*vop_write)(struct vnode *file, struct uio *uio);
int (*vop_ioctl)(struct vnode *object, int op, userptr_t data);
int (*vop_stat)(struct vnode *object, struct stat *statbuf);
int (*vop_gettype)(struct vnode *object, mode_t *result);
bool (*vop_isseekable)(struct vnode *object);
int (*vop_fsync)(struct vnode *object);
int (*vop_mmap)(struct vnode *file /* add stuff */);
int (*vop_truncate)(struct vnode *file, off_t len);
int (*vop_namefile)(struct vnode *file, struct uio *uio);
int (*vop_creat)(struct vnode *dir,
const char *name, bool excl, mode_t mode,
struct vnode **result);
int (*vop_symlink)(struct vnode *dir,
const char *contents, const char *name);
int (*vop_mkdir)(struct vnode *parentdir,
const char *name, mode_t mode);
int (*vop_link)(struct vnode *dir,
const char *name, struct vnode *file);
int (*vop_remove)(struct vnode *dir,
const char *name);
int (*vop_rmdir)(struct vnode *dir,
const char *name);
int (*vop_rename)(struct vnode *vn1, const char *name1,
struct vnode *vn2, const char *name2);
int (*vop_lookup)(struct vnode *dir,
char *pathname, struct vnode **result);
int (*vop_lookparent)(struct vnode *dir,
char *pathname, struct vnode **result,
char *buf, size_t len);
};
#define __VOP(vn, sym) (vnode_check(vn, #sym), (vn)->vn_ops->vop_##sym)
#define VOP_EACHOPEN(vn, flags) (__VOP(vn, eachopen)(vn, flags))
#define VOP_RECLAIM(vn) (__VOP(vn, reclaim)(vn))
#define VOP_READ(vn, uio) (__VOP(vn, read)(vn, uio))
#define VOP_READLINK(vn, uio) (__VOP(vn, readlink)(vn, uio))
#define VOP_GETDIRENTRY(vn, uio) (__VOP(vn,getdirentry)(vn, uio))
#define VOP_WRITE(vn, uio) (__VOP(vn, write)(vn, uio))
#define VOP_IOCTL(vn, code, buf) (__VOP(vn, ioctl)(vn,code,buf))
#define VOP_STAT(vn, ptr) (__VOP(vn, stat)(vn, ptr))
#define VOP_GETTYPE(vn, result) (__VOP(vn, gettype)(vn, result))
#define VOP_ISSEEKABLE(vn) (__VOP(vn, isseekable)(vn))
#define VOP_FSYNC(vn) (__VOP(vn, fsync)(vn))
#define VOP_MMAP(vn /*add stuff */) (__VOP(vn, mmap)(vn /*add stuff */))
#define VOP_TRUNCATE(vn, pos) (__VOP(vn, truncate)(vn, pos))
#define VOP_NAMEFILE(vn, uio) (__VOP(vn, namefile)(vn, uio))
#define VOP_CREAT(vn,nm,excl,mode,res) (__VOP(vn, creat)(vn,nm,excl,mode,res))
#define VOP_SYMLINK(vn, name, content) (__VOP(vn, symlink)(vn, name, content))
#define VOP_MKDIR(vn, name, mode) (__VOP(vn, mkdir)(vn, name, mode))
#define VOP_LINK(vn, name, vn2) (__VOP(vn, link)(vn, name, vn2))
#define VOP_REMOVE(vn, name) (__VOP(vn, remove)(vn, name))
#define VOP_RMDIR(vn, name) (__VOP(vn, rmdir)(vn, name))
#define VOP_RENAME(vn1,name1,vn2,name2)(__VOP(vn1,rename)(vn1,name1,vn2,name2))
#define VOP_LOOKUP(vn, name, res) (__VOP(vn, lookup)(vn, name, res))
#define VOP_LOOKPARENT(vn,nm,res,bf,ln) (__VOP(vn,lookparent)(vn,nm,res,bf,ln))
/*
* Consistency check
*/
void vnode_check(struct vnode *, const char *op);
/*
* Reference count manipulation (handled above filesystem level)
*/
void vnode_incref(struct vnode *);
void vnode_decref(struct vnode *);
#define VOP_INCREF(vn) vnode_incref(vn)
#define VOP_DECREF(vn) vnode_decref(vn)
/*
* Vnode initialization (intended for use by filesystem code)
* The reference count is initialized to 1.
*/
int vnode_init(struct vnode *, const struct vnode_ops *ops,
struct fs *fs, void *fsdata);
/*
* Vnode final cleanup (intended for use by filesystem code)
* The reference count is asserted to be 1.
*/
void vnode_cleanup(struct vnode *);
/*
* Common stubs for vnode functions that just fail, in various ways.
*/
int vopfail_uio_notdir(struct vnode *vn, struct uio *uio);
int vopfail_uio_isdir(struct vnode *vn, struct uio *uio);
int vopfail_uio_inval(struct vnode *vn, struct uio *uio);
int vopfail_uio_nosys(struct vnode *vn, struct uio *uio);
int vopfail_mmap_isdir(struct vnode *vn /* add stuff */);
int vopfail_mmap_perm(struct vnode *vn /* add stuff */);
int vopfail_mmap_nosys(struct vnode *vn /* add stuff */);
int vopfail_truncate_isdir(struct vnode *vn, off_t pos);
int vopfail_creat_notdir(struct vnode *vn, const char *name, bool excl,
mode_t mode, struct vnode **result);
int vopfail_symlink_notdir(struct vnode *vn, const char *contents,
const char *name);
int vopfail_symlink_nosys(struct vnode *vn, const char *contents,
const char *name);
int vopfail_mkdir_notdir(struct vnode *vn, const char *name, mode_t mode);
int vopfail_mkdir_nosys(struct vnode *vn, const char *name, mode_t mode);
int vopfail_link_notdir(struct vnode *dir, const char *name,
struct vnode *file);
int vopfail_link_nosys(struct vnode *dir, const char *name,
struct vnode *file);
int vopfail_string_notdir(struct vnode *vn, const char *name);
int vopfail_string_nosys(struct vnode *vn, const char *name);
int vopfail_rename_notdir(struct vnode *fromdir, const char *fromname,
struct vnode *todir, const char *toname);
int vopfail_rename_nosys(struct vnode *fromdir, const char *fromname,
struct vnode *todir, const char *toname);
int vopfail_lookup_notdir(struct vnode *vn, char *path, struct vnode **result);
int vopfail_lookparent_notdir(struct vnode *vn, char *path,
struct vnode **result, char *buf, size_t len);
#endif /* _VNODE_H_ */