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 6 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
7 changes: 7 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,12 @@ 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);

void vfs_vcache_init(void);
vnode_t *vfs_vcache_hashget(mount_t *mp, ino_t ino);
vnode_t *vfs_vcache_new_vnode(void);
void vfs_vcache_put(vnode_t *vn);
void vfs_vcache_invalidate(vnode_t *vn);

#endif /* !_KERNEL */

#endif /* !_SYS_VFS_H_ */
12 changes: 10 additions & 2 deletions include/sys/vnode.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,17 @@ typedef struct {
spin_t vl_interlock;
} vnlock_t;

typedef enum vnode_flags {
VF_CACHED, /* 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
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
83 changes: 36 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);
static void tmpfs_update_time(tmpfs_node_t *v, tmpfs_time_type_t type);

Expand Down Expand Up @@ -510,7 +508,7 @@ 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)))
if ((error = tmpfs_chtimes(v, &va->va_atime, &va->va_mtime, cred)))
return error;
}

Expand Down Expand Up @@ -558,11 +556,10 @@ 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)
if (node->tfn_links == 0) {
/* vfs_vcache_invalidate(v); */
tmpfs_free_node(tfm, node);
}

return 0;
}
Expand Down Expand Up @@ -604,10 +601,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 @@ -634,26 +633,12 @@ static vnodeops_t tmpfs_vnodeops = {.v_lookup = tmpfs_vop_lookup,

/* 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 @@ -707,19 +692,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 @@ -746,19 +731,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_hashget(mp, tfn->tfn_ino);
if (!vn) {
vn = vfs_vcache_new_vnode();
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 @@ -777,15 +767,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 @@ -996,20 +986,21 @@ 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) {
int err;
if ((err = cred_can_utime(v->tfn_vnode, v->tfn_uid, cred)))
tmpfs_node_t *node = TMPFS_NODE_OF(v);
if ((err = cred_can_utime(v, node->tfn_uid, cred)))
return err;

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 +1039,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
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