update name of code to labcodes
This commit is contained in:
248
labcodes/lab8/kern/fs/vfs/inode.h
Normal file
248
labcodes/lab8/kern/fs/vfs/inode.h
Normal file
@@ -0,0 +1,248 @@
|
||||
#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__ */
|
||||
|
||||
Reference in New Issue
Block a user