Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

vcache #1153

Open
wants to merge 19 commits into
base: master
Choose a base branch
from
Open

vcache #1153

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions include/sys/vfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ typedef struct timeval timeval_t;
typedef struct file file_t;
typedef struct cred cred_t;
typedef struct timespec timespec_t;
typedef struct mount mount_t;

/*! \brief Called during kernel initialization. */
void init_vfs(void);
Expand Down Expand Up @@ -134,6 +135,43 @@ int vfs_maybe_descend(vnode_t **vp);
/* Finds name of v-node in given directory. */
int vfs_name_in_dir(vnode_t *dv, vnode_t *v, char *buf, size_t *lastp);

/**
* \brief Initialize the vcache subsystem
*/
void vfs_vcache_init(void);

/**
* \brief Borrow a new vnode from vcache.
* \return a vnode with its use count initialized to 1.
*/
vnode_t *vfs_vcache_borrow_new(void);

/**
* \brief Try acquiring a vnode for specified inode and mountpoint.
* \param mp mountpoint of the inode's filesystem
* \param ino inode to be used for vnode lookup
* \return requested vnodeor NULL if the vnode is not in vcache.
*/
vnode_t *vfs_vcache_reborrow(mount_t *mp, ino_t ino);

/**
* \brief Return a vnode that's not longer in use to vcache.
* \param vn vnode to be returned
* \warning vnode use count must be zero!
* Freelist can't contain vnodes that are in use.
*/
void vfs_vcache_return(vnode_t *vn);

/**
* \brief Detach vnode from a filesystem (if present in any).
* This will cause the vnode to get reclaimed immeditially.
* \warning a vnode is detachable if and only if it's on freelist,
* ie. it's usecnt is set to zero.
* \return 0 on success, otherwise an error code from VOP_RECLAIM
* (only if v_reclaim is implemented for that vnode)
*/
int vfs_vcache_detach(vnode_t *vn);

#endif /* !_KERNEL */

#endif /* !_SYS_VFS_H_ */
18 changes: 16 additions & 2 deletions include/sys/vnode.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ typedef int vnode_mkdir_t(vnode_t *dv, componentname_t *cn, vattr_t *va,
typedef int vnode_rmdir_t(vnode_t *dv, vnode_t *v, componentname_t *cn);
typedef int vnode_access_t(vnode_t *v, accmode_t mode, cred_t *cred);
typedef int vnode_ioctl_t(vnode_t *v, u_long cmd, void *data, file_t *fp);
typedef int vnode_inactive(vnode_t *v);
typedef int vnode_reclaim_t(vnode_t *v);
Comment on lines 54 to 56
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent naming schema.

typedef int vnode_readlink_t(vnode_t *v, uio_t *uio);
typedef int vnode_symlink_t(vnode_t *dv, componentname_t *cn, vattr_t *va,
Expand All @@ -74,6 +75,7 @@ typedef struct vnodeops {
vnode_rmdir_t *v_rmdir;
vnode_access_t *v_access;
vnode_ioctl_t *v_ioctl;
vnode_inactive *v_inactive;
vnode_reclaim_t *v_reclaim;
vnode_readlink_t *v_readlink;
vnode_symlink_t *v_symlink;
Expand All @@ -89,9 +91,17 @@ typedef struct {
spin_t vl_interlock;
} vnlock_t;

typedef enum vnode_flags {
VF_CACHED = 1, /* Use vcache subsystem when managing the vnode */
} vnode_flags_t;

typedef struct vnode {
vnodetype_t v_type; /* Vnode type, see above */
TAILQ_ENTRY(vnode) v_list; /* Entry on the mount vnodes list */
vnodetype_t v_type; /* Vnode type, see above */
TAILQ_ENTRY(vnode) v_list; /* Entry on the mount vnodes list */
TAILQ_ENTRY(vnode) v_free; /* Entry on vnode free list (vcache) */
TAILQ_ENTRY(vnode) v_cached; /* Entry on vnode list in vcache bucket */
ino_t v_ino; /* inode number (used by vcache) */
vnode_flags_t v_flags; /* Flags for internal vnode management. */

vnodeops_t *v_ops; /* Vnode operations */
void *v_data; /* Filesystem-specific arbitrary data */
Expand Down Expand Up @@ -193,6 +203,10 @@ static inline int VOP_IOCTL(vnode_t *v, u_long cmd, void *data, file_t *fp) {
return VOP_CALL(ioctl, v, cmd, data, fp);
}

static inline int VOP_INACTIVE(vnode_t *v) {
return VOP_CALL(inactive, v);
}

static inline int VOP_RECLAIM(vnode_t *v) {
return VOP_CALL(reclaim, v);
}
Expand Down
1 change: 1 addition & 0 deletions sys/kern/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ SOURCES = \
vfs_name.c \
vfs_readdir.c \
vfs_syscalls.c \
vfs_vcache.c \
vfs_vnode.c \
vm_map.c \
vm_object.c \
Expand Down
6 changes: 3 additions & 3 deletions sys/kern/devfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ static int devfs_vop_open(vnode_t *v, int mode, file_t *fp) {
}

/* Free a devfs device file after unlinking it. */
static int devfs_vop_reclaim(vnode_t *v) {
static int devfs_vop_inactive(vnode_t *v) {
devfs_node_t *dn = devfs_node_of(v);
devnode_t *dev = &dn->dn_device;
assert(dev->refcnt == 0);
Expand All @@ -263,7 +263,7 @@ static vnodeops_t devfs_dev_vnodeops = {
.v_open = devfs_vop_open,
.v_access = vnode_access_generic,
.v_getattr = devfs_vop_getattr,
.v_reclaim = devfs_vop_reclaim,
.v_inactive = devfs_vop_inactive,
};

/*
Expand Down Expand Up @@ -335,7 +335,7 @@ static vnodeops_t devfs_dir_vnodeops = {
.v_lookup = devfs_vop_lookup,
.v_readdir = devfs_vop_readdir,
.v_getattr = devfs_vop_getattr,
.v_reclaim = devfs_vop_reclaim,
.v_inactive = devfs_vop_inactive,
.v_open = vnode_open_generic,
};

Expand Down
90 changes: 43 additions & 47 deletions sys/kern/tmpfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ typedef struct tmpfs_dirent {
typedef TAILQ_HEAD(, tmpfs_dirent) tmpfs_dirent_list_t;

typedef struct tmpfs_node {
vnode_t *tfn_vnode; /* corresponding v-node */
vnodetype_t tfn_type; /* node type */

/* Node attributes (as in vattr) */
Expand Down Expand Up @@ -292,7 +291,6 @@ static inline tmpfs_node_t *TMPFS_NODE_OF(vnode_t *vp) {
}

/* Prototypes for internal routines. */
static void tmpfs_attach_vnode(tmpfs_node_t *tfn, mount_t *mp);
static tmpfs_node_t *tmpfs_new_node(tmpfs_mount_t *tfm, vattr_t *va,
vnodetype_t ntype);
static void tmpfs_free_node(tmpfs_mount_t *tfm, tmpfs_node_t *tfn);
Expand All @@ -301,15 +299,15 @@ static int tmpfs_create_file(vnode_t *dv, vnode_t **vp, vattr_t *va,
static void tmpfs_dir_attach(tmpfs_node_t *dnode, tmpfs_dirent_t *de,
tmpfs_node_t *node);
static int tmpfs_get_vnode(mount_t *mp, tmpfs_node_t *tfn, vnode_t **vp);
static int tmpfs_alloc_dirent(tmpfs_node_t *tfn, const char *name,
static int tmpfs_alloc_dirent(mount_t *mp, tmpfs_node_t *tfn, const char *name,
size_t namelen, tmpfs_dirent_t **dep);
static tmpfs_dirent_t *tmpfs_dir_lookup(tmpfs_node_t *tfn,
const componentname_t *cn);
static void tmpfs_dir_detach(tmpfs_node_t *dv, tmpfs_dirent_t *de);

static blkptr_t *tmpfs_get_blk(tmpfs_node_t *v, size_t blkno);
static int tmpfs_resize(tmpfs_mount_t *tfm, tmpfs_node_t *v, size_t newsize);
static int tmpfs_chtimes(tmpfs_node_t *v, timespec_t *atime, timespec_t *mtime,
static int tmpfs_chtimes(vnode_t *v, timespec_t *atime, timespec_t *mtime,
cred_t *cred, va_flags_t vaflags);
static void tmpfs_update_time(tmpfs_node_t *v, tmpfs_time_type_t type);

Expand Down Expand Up @@ -510,8 +508,8 @@ static int tmpfs_vop_setattr(vnode_t *v, vattr_t *va, cred_t *cred) {
}

if (va->va_atime.tv_sec != VNOVAL || va->va_mtime.tv_sec != VNOVAL) {
if ((error = tmpfs_chtimes(node, &va->va_atime, &va->va_mtime, cred,
va->va_flags)))
if ((error =
tmpfs_chtimes(v, &va->va_atime, &va->va_mtime, cred, va->va_flags)))
return error;
}

Expand Down Expand Up @@ -555,13 +553,18 @@ static int tmpfs_vop_rmdir(vnode_t *dv, vnode_t *v, componentname_t *cn) {
return 0;
}

static int tmpfs_vop_inactive(vnode_t *v) {
tmpfs_node_t *node = TMPFS_NODE_OF(v);

if (node->tfn_links == 0)
return vfs_vcache_detach(v);
return 0;
}

static int tmpfs_vop_reclaim(vnode_t *v) {
tmpfs_mount_t *tfm = TMPFS_ROOT_OF(v->v_mount);
tmpfs_node_t *node = TMPFS_NODE_OF(v);

v->v_data = NULL;
node->tfn_vnode = NULL;

if (node->tfn_links == 0)
tmpfs_free_node(tfm, node);

Expand Down Expand Up @@ -605,10 +608,12 @@ static int tmpfs_vop_symlink(vnode_t *dv, componentname_t *cn, vattr_t *va,
static int tmpfs_vop_link(vnode_t *dv, vnode_t *v, componentname_t *cn) {
tmpfs_node_t *dnode = TMPFS_NODE_OF(dv);
tmpfs_node_t *node = TMPFS_NODE_OF(v);
mount_t *mp = dv->v_mount;
tmpfs_dirent_t *de;
int error;

if ((error = tmpfs_alloc_dirent(dnode, cn->cn_nameptr, cn->cn_namelen, &de)))
if ((error =
tmpfs_alloc_dirent(mp, dnode, cn->cn_nameptr, cn->cn_namelen, &de)))
return error;
tmpfs_dir_attach(dnode, de, node);
return 0;
Expand All @@ -628,33 +633,20 @@ static vnodeops_t tmpfs_vnodeops = {.v_lookup = tmpfs_vop_lookup,
.v_mkdir = tmpfs_vop_mkdir,
.v_rmdir = tmpfs_vop_rmdir,
.v_access = vnode_access_generic,
.v_inactive = tmpfs_vop_inactive,
.v_reclaim = tmpfs_vop_reclaim,
.v_readlink = tmpfs_vop_readlink,
.v_symlink = tmpfs_vop_symlink,
.v_link = tmpfs_vop_link};
Comment on lines +636 to 640
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add , after last struct member - then shitty clang-format will be happy and it will produce human readable output :)


/* tmpfs internal routines */

/*
* tmpfs_attach_vnode: init v-node and associate with existing inode.
*/
static void tmpfs_attach_vnode(tmpfs_node_t *tfn, mount_t *mp) {
vnode_t *vn = vnode_new(tfn->tfn_type, &tmpfs_vnodeops, tfn);
vn->v_mount = mp;
vn->v_data = tfn;
vn->v_type = tfn->tfn_type;
vn->v_ops = &tmpfs_vnodeops;

tfn->tfn_vnode = vn;
}

/*
* tmpfs_new_node: create new inode of a specified type.
*/
static tmpfs_node_t *tmpfs_new_node(tmpfs_mount_t *tfm, vattr_t *va,
vnodetype_t ntype) {
tmpfs_node_t *node = tmpfs_alloc_inode(tfm);
node->tfn_vnode = NULL;
node->tfn_mode = va->va_mode;
node->tfn_type = ntype;
node->tfn_links = 0;
Expand Down Expand Up @@ -708,19 +700,19 @@ static int tmpfs_create_file(vnode_t *dv, vnode_t **vp, vattr_t *va,
vnodetype_t ntype, componentname_t *cn) {
tmpfs_node_t *dnode = TMPFS_NODE_OF(dv);
tmpfs_dirent_t *de;
mount_t *mp = dv->v_mount;
int error;

/* Allocate a new directory entry for the new file. */
if ((error = tmpfs_alloc_dirent(dnode, cn->cn_nameptr, cn->cn_namelen, &de)))
if ((error =
tmpfs_alloc_dirent(mp, dnode, cn->cn_nameptr, cn->cn_namelen, &de)))
return error;

tmpfs_node_t *node = tmpfs_new_node(TMPFS_ROOT_OF(dv->v_mount), va, ntype);
tmpfs_attach_vnode(node, dv->v_mount);

/* Attach directory entry */
tmpfs_dir_attach(dnode, de, node);
*vp = node->tfn_vnode;
return 0;
return tmpfs_get_vnode(dv->v_mount, node, vp);
}

/*
Expand All @@ -747,19 +739,24 @@ static void tmpfs_dir_attach(tmpfs_node_t *dnode, tmpfs_dirent_t *de,
* tmpfs_get_vnode: get a v-node with usecnt incremented.
*/
static int tmpfs_get_vnode(mount_t *mp, tmpfs_node_t *tfn, vnode_t **vp) {
vnode_t *vn = tfn->tfn_vnode;
if (vn == NULL) {
tmpfs_attach_vnode(tfn, mp);
} else {
vnode_hold(vn);
vnode_t *vn = vfs_vcache_reborrow(mp, tfn->tfn_ino);
if (!vn) {
vn = vfs_vcache_borrow_new();
vn->v_ino = tfn->tfn_ino;
vn->v_mount = mp;
vn->v_ops = &tmpfs_vnodeops;
vn->v_type = tfn->tfn_type;
vn->v_data = tfn;
}
*vp = tfn->tfn_vnode;

*vp = vn;

return 0;
}

static int tmpfs_dir_extend(tmpfs_node_t *tfn) {
static int tmpfs_dir_extend(mount_t *mp, tmpfs_node_t *tfn) {
int error;
tmpfs_mount_t *tfm = TMPFS_ROOT_OF(tfn->tfn_vnode->v_mount);
tmpfs_mount_t *tfm = TMPFS_ROOT_OF(mp);

if ((error = tmpfs_resize(tfm, tfn, tfn->tfn_size + BLOCK_SIZE)))
return error;
Expand All @@ -778,15 +775,15 @@ static int tmpfs_dir_extend(tmpfs_node_t *tfn) {
/*
* tmpfs_alloc_dirent: allocate a new directory entry.
*/
static int tmpfs_alloc_dirent(tmpfs_node_t *tfn, const char *name,
static int tmpfs_alloc_dirent(mount_t *mp, tmpfs_node_t *tfn, const char *name,
size_t namelen, tmpfs_dirent_t **dep) {
int error = 0;

if (namelen + 1 > TMPFS_NAME_MAX)
return ENAMETOOLONG;

if (TAILQ_EMPTY(&tfn->tfn_dir.fdirents)) {
if ((error = tmpfs_dir_extend(tfn)))
if ((error = tmpfs_dir_extend(mp, tfn)))
return error;
}

Expand Down Expand Up @@ -997,19 +994,20 @@ static int tmpfs_resize(tmpfs_mount_t *tfm, tmpfs_node_t *v, size_t newsize) {
return 0;
}

static int tmpfs_chtimes(tmpfs_node_t *v, timespec_t *atime, timespec_t *mtime,
static int tmpfs_chtimes(vnode_t *v, timespec_t *atime, timespec_t *mtime,
cred_t *cred, va_flags_t vaflags) {
if (!cred_can_utime(v->tfn_vnode, v->tfn_uid, cred, vaflags))
tmpfs_node_t *node = TMPFS_NODE_OF(v);
if (!cred_can_utime(v, node->tfn_uid, cred, vaflags))
return EPERM;

mtx_lock(&v->tfn_timelock);
mtx_lock(&node->tfn_timelock);
if (atime->tv_sec != VNOVAL)
v->tfn_atime = *atime;
node->tfn_atime = *atime;
if (mtime->tv_sec != VNOVAL)
v->tfn_mtime = *mtime;
mtx_unlock(&v->tfn_timelock);
node->tfn_mtime = *mtime;
mtx_unlock(&node->tfn_timelock);
Comment on lines -1005 to +1008
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WITH_MTX_LOCK


tmpfs_update_time(v, TMPFS_UPDATE_CTIME);
tmpfs_update_time(node, TMPFS_UPDATE_CTIME);

return 0;
}
Expand Down Expand Up @@ -1048,12 +1046,10 @@ static int tmpfs_mount(mount_t *mp) {
va.va_uid = 0;
va.va_gid = 0;
tmpfs_node_t *root = tmpfs_new_node(tfm, &va, V_DIR);
tmpfs_attach_vnode(root, mp);
root->tfn_dir.parent = root; /* Parent of the root node is itself. */
root->tfn_links++; /* Extra link, because root has no directory entry. */

tfm->tfm_root = root;
vnode_drop(root->tfn_vnode);
return 0;
}

Expand Down
4 changes: 2 additions & 2 deletions sys/kern/tty.c
Original file line number Diff line number Diff line change
Expand Up @@ -1142,7 +1142,7 @@ static int tty_vn_open(vnode_t *v, int mode, file_t *fp) {
return _tty_vn_open(v, mode, fp);
}

static int tty_vn_reclaim(vnode_t *v) {
static int tty_vn_inactive(vnode_t *v) {
tty_free(devfs_node_data(v));
devfs_free(v->v_data);
return 0;
Expand All @@ -1151,7 +1151,7 @@ static int tty_vn_reclaim(vnode_t *v) {
static vnodeops_t tty_vnodeops = {
.v_open = tty_vn_open,
.v_close = tty_vn_close,
.v_reclaim = tty_vn_reclaim,
.v_inactive = tty_vn_inactive,
};

int tty_makedev(devfs_node_t *parent, const char *name, tty_t *tty) {
Expand Down
1 change: 1 addition & 0 deletions sys/kern/vfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ static vnodeops_t vfs_root_ops = {.v_lookup = vfs_root_vnode_lookup};
static int vfs_register(vfsconf_t *vfc);

void init_vfs(void) {
vfs_vcache_init();
vnodeops_init(&vfs_root_ops);

vfs_root_vnode = vnode_new(V_DIR, &vfs_root_ops, NULL);
Expand Down
Loading