#ifndef __KERN_FS_VFS_INODE_H__
|
|
#define __KERN_FS_VFS_INODE_H__
|
|
|
|
#include <defs.h>
|
|
#include <dev.h>
|
|
#include <sfs.h>
|
|
#include <atomic.h>
|
|
#include <assert.h>
|
|
|
|
struct stat;
|
|
struct iobuf;
|
|
|
|
/*
|
|
* A struct inode is an abstract representation of a file.
|
|
*
|
|
* It is an interface that allows the kernel's filesystem-independent
|
|
* code to interact usefully with multiple sets of filesystem code.
|
|
*/
|
|
|
|
/*
|
|
* Abstract low-level file.
|
|
*
|
|
* Note: in_info is Filesystem-specific data, in_type is the inode type
|
|
*
|
|
* open_count is managed using VOP_INCOPEN and VOP_DECOPEN by
|
|
* vfs_open() and vfs_close(). Code above the VFS layer should not
|
|
* need to worry about it.
|
|
*/
|
|
struct inode {
|
|
union {
|
|
struct device __device_info;
|
|
struct sfs_inode __sfs_inode_info;
|
|
} in_info;
|
|
enum {
|
|
inode_type_device_info = 0x1234,
|
|
inode_type_sfs_inode_info,
|
|
} in_type;
|
|
int ref_count;
|
|
int open_count;
|
|
struct fs *in_fs;
|
|
const struct inode_ops *in_ops;
|
|
};
|
|
|
|
#define __in_type(type) inode_type_##type##_info
|
|
|
|
#define check_inode_type(node, type) ((node)->in_type == __in_type(type))
|
|
|
|
#define __vop_info(node, type) \
|
|
({ \
|
|
struct inode *__node = (node); \
|
|
assert(__node != NULL && check_inode_type(__node, type)); \
|
|
&(__node->in_info.__##type##_info); \
|
|
})
|
|
|
|
#define vop_info(node, type) __vop_info(node, type)
|
|
|
|
#define info2node(info, type) \
|
|
to_struct((info), struct inode, in_info.__##type##_info)
|
|
|
|
struct inode *__alloc_inode(int type);
|
|
|
|
#define alloc_inode(type) __alloc_inode(__in_type(type))
|
|
|
|
#define MAX_INODE_COUNT 0x10000
|
|
|
|
int inode_ref_inc(struct inode *node);
|
|
int inode_ref_dec(struct inode *node);
|
|
int inode_open_inc(struct inode *node);
|
|
int inode_open_dec(struct inode *node);
|
|
|
|
void inode_init(struct inode *node, const struct inode_ops *ops, struct fs *fs);
|
|
void inode_kill(struct inode *node);
|
|
|
|
#define VOP_MAGIC 0x8c4ba476
|
|
|
|
/*
|
|
* Abstract operations on a inode.
|
|
*
|
|
* These are used in the form VOP_FOO(inode, args), which are macros
|
|
* that expands to inode->inode_ops->vop_foo(inode, args). The operations
|
|
* "foo" are:
|
|
*
|
|
* vop_open - Called on 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 inode 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 inodes.
|
|
* This maintains the open count so VOP_LASTCLOSE can
|
|
* be called at the right time.
|
|
*
|
|
* vop_close - To be called on *last* close() of a file.
|
|
*
|
|
* VOP_LASTCLOSE should not be called directly from
|
|
* above the VFS layer - use vfs_close() to close
|
|
* inodes opened with vfs_open().
|
|
*
|
|
* vop_reclaim - Called when inode is no longer in use. Note that
|
|
* this may be substantially after vop_lastclose is
|
|
* called.
|
|
*
|
|
*****************************************
|
|
*
|
|
* 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_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_fstat -Return info about a file. The pointer is a
|
|
* pointer to struct stat; see stat.h.
|
|
*
|
|
* vop_gettype - Return type of file. The values for file types
|
|
* are in sfs.h.
|
|
*
|
|
* vop_tryseek - Check if seeking to the specified position within
|
|
* the file is legal. (For instance, all seeks
|
|
* are illegal on serial port devices, and seeks
|
|
* past EOF on files whose sizes are fixed may be
|
|
* as well.)
|
|
*
|
|
* vop_fsync - Force any dirty buffers associated with this file
|
|
* to stable storage.
|
|
*
|
|
* 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 io buffer.
|
|
* 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
|
|
* inode for the file as per vop_lookup.
|
|
*
|
|
*****************************************
|
|
*
|
|
* vop_lookup - Parse PATHNAME relative to the passed directory
|
|
* DIR, and hand back the inode for the file it
|
|
* refers to. May destroy PATHNAME. Should increment
|
|
* refcount on inode handed back.
|
|
*/
|
|
struct inode_ops {
|
|
unsigned long vop_magic;
|
|
int (*vop_open)(struct inode *node, uint32_t open_flags);
|
|
int (*vop_close)(struct inode *node);
|
|
int (*vop_read)(struct inode *node, struct iobuf *iob);
|
|
int (*vop_write)(struct inode *node, struct iobuf *iob);
|
|
int (*vop_fstat)(struct inode *node, struct stat *stat);
|
|
int (*vop_fsync)(struct inode *node);
|
|
int (*vop_namefile)(struct inode *node, struct iobuf *iob);
|
|
int (*vop_getdirentry)(struct inode *node, struct iobuf *iob);
|
|
int (*vop_reclaim)(struct inode *node);
|
|
int (*vop_gettype)(struct inode *node, uint32_t *type_store);
|
|
int (*vop_tryseek)(struct inode *node, off_t pos);
|
|
int (*vop_truncate)(struct inode *node, off_t len);
|
|
int (*vop_create)(struct inode *node, const char *name, bool excl, struct inode **node_store);
|
|
int (*vop_lookup)(struct inode *node, char *path, struct inode **node_store);
|
|
int (*vop_ioctl)(struct inode *node, int op, void *data);
|
|
};
|
|
|
|
/*
|
|
* Consistency check
|
|
*/
|
|
void inode_check(struct inode *node, const char *opstr);
|
|
|
|
#define __vop_op(node, sym) \
|
|
({ \
|
|
struct inode *__node = (node); \
|
|
assert(__node != NULL && __node->in_ops != NULL && __node->in_ops->vop_##sym != NULL); \
|
|
inode_check(__node, #sym); \
|
|
__node->in_ops->vop_##sym; \
|
|
})
|
|
|
|
#define vop_open(node, open_flags) (__vop_op(node, open)(node, open_flags))
|
|
#define vop_close(node) (__vop_op(node, close)(node))
|
|
#define vop_read(node, iob) (__vop_op(node, read)(node, iob))
|
|
#define vop_write(node, iob) (__vop_op(node, write)(node, iob))
|
|
#define vop_fstat(node, stat) (__vop_op(node, fstat)(node, stat))
|
|
#define vop_fsync(node) (__vop_op(node, fsync)(node))
|
|
#define vop_namefile(node, iob) (__vop_op(node, namefile)(node, iob))
|
|
#define vop_getdirentry(node, iob) (__vop_op(node, getdirentry)(node, iob))
|
|
#define vop_reclaim(node) (__vop_op(node, reclaim)(node))
|
|
#define vop_ioctl(node, op, data) (__vop_op(node, ioctl)(node, op, data))
|
|
#define vop_gettype(node, type_store) (__vop_op(node, gettype)(node, type_store))
|
|
#define vop_tryseek(node, pos) (__vop_op(node, tryseek)(node, pos))
|
|
#define vop_truncate(node, len) (__vop_op(node, truncate)(node, len))
|
|
#define vop_create(node, name, excl, node_store) (__vop_op(node, create)(node, name, excl, node_store))
|
|
#define vop_lookup(node, path, node_store) (__vop_op(node, lookup)(node, path, node_store))
|
|
|
|
|
|
#define vop_fs(node) ((node)->in_fs)
|
|
#define vop_init(node, ops, fs) inode_init(node, ops, fs)
|
|
#define vop_kill(node) inode_kill(node)
|
|
|
|
/*
|
|
* Reference count manipulation (handled above filesystem level)
|
|
*/
|
|
#define vop_ref_inc(node) inode_ref_inc(node)
|
|
#define vop_ref_dec(node) inode_ref_dec(node)
|
|
/*
|
|
* Open count manipulation (handled above filesystem level)
|
|
*
|
|
* VOP_INCOPEN is called by vfs_open. VOP_DECOPEN is called by vfs_close.
|
|
* Neither of these should need to be called from above the vfs layer.
|
|
*/
|
|
#define vop_open_inc(node) inode_open_inc(node)
|
|
#define vop_open_dec(node) inode_open_dec(node)
|
|
|
|
|
|
static inline int
|
|
inode_ref_count(struct inode *node) {
|
|
return node->ref_count;
|
|
}
|
|
|
|
static inline int
|
|
inode_open_count(struct inode *node) {
|
|
return node->open_count;
|
|
}
|
|
|
|
#endif /* !__KERN_FS_VFS_INODE_H__ */
|
|
|