Change udf to vcache, keyed on udf_node->loc.loc.

This commit is contained in:
hannken 2015-04-06 08:39:23 +00:00
parent 51022ca953
commit a494ee15b8
4 changed files with 151 additions and 200 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: udf.h,v 1.47 2014/09/17 19:47:05 reinoud Exp $ */
/* $NetBSD: udf.h,v 1.48 2015/04/06 08:39:23 hannken Exp $ */
/*
* Copyright (c) 2006, 2008 Reinoud Zandijk
@ -94,6 +94,7 @@ extern int udf_verbose;
#define DPRINTFIF(name, cond, arg) {}
#endif
VFS_PROTOS(udf);
/* constants to identify what kind of identifier we are dealing with */
#define UDF_REGID_DOMAIN 1
@ -339,7 +340,6 @@ struct udf_mount {
/* rb tree for lookup icb to udf_node and sorted list for sync */
kmutex_t ihash_lock;
kmutex_t get_node_lock;
struct rb_tree udf_node_tree;
/* syncing */

View File

@ -1,4 +1,4 @@
/* $NetBSD: udf_subr.c,v 1.128 2015/02/07 04:18:03 christos Exp $ */
/* $NetBSD: udf_subr.c,v 1.129 2015/04/06 08:39:23 hannken Exp $ */
/*
* Copyright (c) 2006, 2008 Reinoud Zandijk
@ -29,7 +29,7 @@
#include <sys/cdefs.h>
#ifndef lint
__KERNEL_RCSID(0, "$NetBSD: udf_subr.c,v 1.128 2015/02/07 04:18:03 christos Exp $");
__KERNEL_RCSID(0, "$NetBSD: udf_subr.c,v 1.129 2015/04/06 08:39:23 hannken Exp $");
#endif /* not lint */
@ -3444,31 +3444,6 @@ udf_init_nodes_tree(struct udf_mount *ump)
}
static struct udf_node *
udf_node_lookup(struct udf_mount *ump, struct long_ad *icbptr)
{
struct udf_node *udf_node;
struct vnode *vp;
loop:
mutex_enter(&ump->ihash_lock);
udf_node = rb_tree_find_node(&ump->udf_node_tree, icbptr);
if (udf_node) {
vp = udf_node->vnode;
assert(vp);
mutex_enter(vp->v_interlock);
mutex_exit(&ump->ihash_lock);
if (vget(vp, LK_EXCLUSIVE))
goto loop;
return udf_node;
}
mutex_exit(&ump->ihash_lock);
return NULL;
}
static void
udf_register_node(struct udf_node *udf_node)
{
@ -5279,44 +5254,33 @@ error_out:
*/
int
udf_get_node(struct udf_mount *ump, struct long_ad *node_icb_loc,
struct udf_node **udf_noderes)
udf_loadvnode(struct mount *mp, struct vnode *vp,
const void *key, size_t key_len, const void **new_key)
{
union dscrptr *dscr;
struct udf_mount *ump;
struct udf_node *udf_node;
struct vnode *nvp;
struct long_ad icb_loc, next_icb_loc, last_fe_icb_loc;
struct long_ad node_icb_loc, icb_loc, next_icb_loc, last_fe_icb_loc;
uint64_t file_size;
uint32_t lb_size, sector, dummy;
int udf_file_type, dscr_type, strat, strat4096, needs_indirect;
int slot, eof, error;
int num_indir_followed = 0;
DPRINTF(NODE, ("udf_get_node called\n"));
*udf_noderes = udf_node = NULL;
DPRINTF(NODE, ("udf_loadvnode called\n"));
udf_node = NULL;
ump = VFSTOUDF(mp);
/* lock to disallow simultanious creation of same udf_node */
mutex_enter(&ump->get_node_lock);
DPRINTF(NODE, ("\tlookup in hash table\n"));
/* lookup in hash table */
assert(ump);
assert(node_icb_loc);
udf_node = udf_node_lookup(ump, node_icb_loc);
if (udf_node) {
DPRINTF(NODE, ("\tgot it from the hash!\n"));
/* vnode is returned locked */
*udf_noderes = udf_node;
mutex_exit(&ump->get_node_lock);
return 0;
}
KASSERT(key_len == sizeof(node_icb_loc.loc));
memset(&node_icb_loc, 0, sizeof(node_icb_loc));
node_icb_loc.len = ump->logical_vol->lb_size;
memcpy(&node_icb_loc.loc, key, key_len);
/* garbage check: translate udf_node_icb_loc to sectornr */
error = udf_translate_vtop(ump, node_icb_loc, &sector, &dummy);
error = udf_translate_vtop(ump, &node_icb_loc, &sector, &dummy);
if (error) {
DPRINTF(NODE, ("\tcan't translate icb address!\n"));
/* no use, this will fail anyway */
mutex_exit(&ump->get_node_lock);
return EINVAL;
}
@ -5324,33 +5288,18 @@ udf_get_node(struct udf_mount *ump, struct long_ad *node_icb_loc,
udf_node = pool_get(&udf_node_pool, PR_WAITOK);
memset(udf_node, 0, sizeof(struct udf_node));
DPRINTF(NODE, ("\tget new vnode\n"));
/* give it a vnode */
error = getnewvnode(VT_UDF, ump->vfs_mountp, udf_vnodeop_p, NULL, &nvp);
if (error) {
pool_put(&udf_node_pool, udf_node);
mutex_exit(&ump->get_node_lock);
return error;
}
/* always return locked vnode */
if ((error = vn_lock(nvp, LK_EXCLUSIVE | LK_RETRY))) {
/* recycle vnode and unlock; simultaneous will fail too */
ungetnewvnode(nvp);
pool_put(&udf_node_pool, udf_node);
mutex_exit(&ump->get_node_lock);
return error;
}
vp->v_tag = VT_UDF;
vp->v_op = udf_vnodeop_p;
vp->v_data = udf_node;
/* initialise crosslinks, note location of fe/efe for hashing */
udf_node->ump = ump;
udf_node->vnode = nvp;
nvp->v_data = udf_node;
udf_node->loc = *node_icb_loc;
udf_node->vnode = vp;
udf_node->loc = node_icb_loc;
udf_node->lockf = 0;
mutex_init(&udf_node->node_mutex, MUTEX_DEFAULT, IPL_NONE);
cv_init(&udf_node->node_lock, "udf_nlk");
genfs_node_init(nvp, &udf_genfsops); /* inititise genfs */
genfs_node_init(vp, &udf_genfsops); /* inititise genfs */
udf_node->outstanding_bufs = 0;
udf_node->outstanding_nodedscr = 0;
udf_node->uncommitted_lbs = 0;
@ -5359,15 +5308,12 @@ udf_get_node(struct udf_mount *ump, struct long_ad *node_icb_loc,
if (ump->fileset_desc)
if (memcmp(&udf_node->loc, &ump->fileset_desc->rootdir_icb,
sizeof(struct long_ad)) == 0)
nvp->v_vflag |= VV_ROOT;
vp->v_vflag |= VV_ROOT;
/* insert into the hash lookup */
udf_register_node(udf_node);
/* safe to unlock, the entry is in the hash table, vnode is locked */
mutex_exit(&ump->get_node_lock);
icb_loc = *node_icb_loc;
icb_loc = node_icb_loc;
needs_indirect = 0;
strat4096 = 0;
udf_file_type = UDF_ICB_FILETYPE_UNKNOWN;
@ -5471,10 +5417,6 @@ udf_get_node(struct udf_mount *ump, struct long_ad *node_icb_loc,
/* recycle udf_node */
udf_dispose_node(udf_node);
VOP_UNLOCK(nvp);
nvp->v_data = NULL;
ungetnewvnode(nvp);
return EINVAL; /* error code ok? */
}
DPRINTF(NODE, ("\tnode fe/efe read in fine\n"));
@ -5567,10 +5509,6 @@ udf_get_node(struct udf_mount *ump, struct long_ad *node_icb_loc,
/* recycle udf_node */
udf_dispose_node(udf_node);
VOP_UNLOCK(nvp);
nvp->v_data = NULL;
ungetnewvnode(nvp);
return EINVAL; /* error code ok? */
}
@ -5587,49 +5525,69 @@ udf_get_node(struct udf_mount *ump, struct long_ad *node_icb_loc,
switch (udf_file_type) {
case UDF_ICB_FILETYPE_DIRECTORY :
case UDF_ICB_FILETYPE_STREAMDIR :
nvp->v_type = VDIR;
vp->v_type = VDIR;
break;
case UDF_ICB_FILETYPE_BLOCKDEVICE :
nvp->v_type = VBLK;
vp->v_type = VBLK;
break;
case UDF_ICB_FILETYPE_CHARDEVICE :
nvp->v_type = VCHR;
vp->v_type = VCHR;
break;
case UDF_ICB_FILETYPE_SOCKET :
nvp->v_type = VSOCK;
vp->v_type = VSOCK;
break;
case UDF_ICB_FILETYPE_FIFO :
nvp->v_type = VFIFO;
vp->v_type = VFIFO;
break;
case UDF_ICB_FILETYPE_SYMLINK :
nvp->v_type = VLNK;
vp->v_type = VLNK;
break;
case UDF_ICB_FILETYPE_VAT :
case UDF_ICB_FILETYPE_META_MAIN :
case UDF_ICB_FILETYPE_META_MIRROR :
nvp->v_type = VNON;
vp->v_type = VNON;
break;
case UDF_ICB_FILETYPE_RANDOMACCESS :
case UDF_ICB_FILETYPE_REALTIME :
nvp->v_type = VREG;
vp->v_type = VREG;
break;
default:
/* YIKES, something else */
nvp->v_type = VNON;
vp->v_type = VNON;
}
/* TODO specfs, fifofs etc etc. vnops setting */
/* don't forget to set vnode's v_size */
uvm_vnp_setsize(nvp, file_size);
uvm_vnp_setsize(vp, file_size);
/* TODO ext attr and streamdir udf_nodes */
*udf_noderes = udf_node;
*new_key = &udf_node->loc.loc;
return 0;
}
int
udf_get_node(struct udf_mount *ump, struct long_ad *node_icb_loc,
struct udf_node **udf_noderes)
{
int error;
struct vnode *vp;
error = vcache_get(ump->vfs_mountp, &node_icb_loc->loc,
sizeof(node_icb_loc->loc), &vp);
if (error)
return error;
error = vn_lock(vp, LK_EXCLUSIVE);
if (error) {
vrele(vp);
return error;
}
*udf_noderes = VTOI(vp);
return 0;
}
/* --------------------------------------------------------------------- */
int
@ -5759,19 +5717,19 @@ udf_dispose_node(struct udf_node *udf_node)
/*
* create a new node using the specified vnodeops, vap and cnp but with the
* udf_file_type. This allows special files to be created. Use with care.
* create a new node using the specified dvp, vap and cnp.
* This allows special files to be created. Use with care.
*/
static int
udf_create_node_raw(struct vnode *dvp, struct vnode **vpp, int udf_file_type,
int (**vnodeops)(void *), struct vattr *vap, struct componentname *cnp)
int
udf_newvnode(struct mount *mp, struct vnode *dvp, struct vnode *vp,
struct vattr *vap, kauth_cred_t cred,
size_t *key_len, const void **new_key)
{
union dscrptr *dscr;
struct udf_node *dir_node = VTOI(dvp);
struct udf_node *udf_node;
struct udf_mount *ump = dir_node->ump;
struct vnode *nvp;
struct long_ad node_icb_loc;
uint64_t parent_unique_id;
uint64_t lmapping;
@ -5779,28 +5737,65 @@ udf_create_node_raw(struct vnode *dvp, struct vnode **vpp, int udf_file_type,
uint16_t vpart_num;
uid_t uid;
gid_t gid, parent_gid;
int fid_size, error;
int (**vnodeops)(void *);
int udf_file_type, fid_size, error;
vnodeops = udf_vnodeop_p;
udf_file_type = UDF_ICB_FILETYPE_RANDOMACCESS;
switch (vap->va_type) {
case VREG :
udf_file_type = UDF_ICB_FILETYPE_RANDOMACCESS;
break;
case VDIR :
udf_file_type = UDF_ICB_FILETYPE_DIRECTORY;
break;
case VLNK :
udf_file_type = UDF_ICB_FILETYPE_SYMLINK;
break;
case VBLK :
udf_file_type = UDF_ICB_FILETYPE_BLOCKDEVICE;
/* specfs */
return ENOTSUP;
break;
case VCHR :
udf_file_type = UDF_ICB_FILETYPE_CHARDEVICE;
/* specfs */
return ENOTSUP;
break;
case VFIFO :
udf_file_type = UDF_ICB_FILETYPE_FIFO;
/* fifofs */
return ENOTSUP;
break;
case VSOCK :
udf_file_type = UDF_ICB_FILETYPE_SOCKET;
return ENOTSUP;
break;
case VNON :
case VBAD :
default :
/* nothing; can we even create these? */
return EINVAL;
}
lb_size = udf_rw32(ump->logical_vol->lb_size);
*vpp = NULL;
/* allocate vnode */
error = getnewvnode(VT_UDF, ump->vfs_mountp, vnodeops, NULL, &nvp);
if (error)
return error;
/* reserve space for one logical block */
vpart_num = ump->node_part;
error = udf_reserve_space(ump, NULL, UDF_C_NODE,
vpart_num, 1, /* can_fail */ true);
if (error)
goto error_out_unget;
return error;
/* allocate node */
error = udf_allocate_space(ump, NULL, UDF_C_NODE,
vpart_num, 1, &lmapping);
if (error)
goto error_out_unreserve;
if (error) {
udf_do_unreserve_space(ump, NULL, vpart_num, 1);
return error;
}
lb_num = lmapping;
/* initialise pointer to location */
@ -5816,8 +5811,8 @@ udf_create_node_raw(struct vnode *dvp, struct vnode **vpp, int udf_file_type,
/* initialise crosslinks, note location of fe/efe for hashing */
/* bugalert: synchronise with udf_get_node() */
udf_node->ump = ump;
udf_node->vnode = nvp;
nvp->v_data = udf_node;
udf_node->vnode = vp;
vp->v_data = udf_node;
udf_node->loc = node_icb_loc;
udf_node->write_loc = node_icb_loc;
udf_node->lockf = 0;
@ -5827,8 +5822,11 @@ udf_create_node_raw(struct vnode *dvp, struct vnode **vpp, int udf_file_type,
udf_node->outstanding_nodedscr = 0;
udf_node->uncommitted_lbs = 0;
vp->v_tag = VT_UDF;
vp->v_op = vnodeops;
/* initialise genfs */
genfs_node_init(nvp, &udf_genfsops);
genfs_node_init(vp, &udf_genfsops);
/* insert into the hash lookup */
udf_register_node(udf_node);
@ -5861,25 +5859,49 @@ udf_create_node_raw(struct vnode *dvp, struct vnode **vpp, int udf_file_type,
KASSERT(dscr->tag.tag_loc == udf_node->loc.loc.lb_num);
/* update vnode's size and type */
nvp->v_type = vap->va_type;
uvm_vnp_setsize(nvp, fid_size);
vp->v_type = vap->va_type;
uvm_vnp_setsize(vp, fid_size);
/* set access mode */
udf_setaccessmode(udf_node, vap->va_mode);
/* set ownership */
uid = kauth_cred_geteuid(cnp->cn_cred);
uid = kauth_cred_geteuid(cred);
gid = parent_gid;
udf_setownership(udf_node, uid, gid);
*key_len = sizeof(udf_node->loc.loc);;
*new_key = &udf_node->loc.loc;
return 0;
}
int
udf_create_node(struct vnode *dvp, struct vnode **vpp, struct vattr *vap,
struct componentname *cnp)
{
struct udf_node *udf_node, *dir_node = VTOI(dvp);
struct udf_mount *ump = dir_node->ump;
int error;
error = vcache_new(dvp->v_mount, dvp, vap, cnp->cn_cred, vpp);
if (error)
return error;
udf_node = VTOI(*vpp);
error = udf_dir_attach(ump, dir_node, udf_node, vap, cnp);
if (error) {
struct long_ad *node_icb_loc = &udf_node->loc;
uint32_t lb_num = udf_rw32(node_icb_loc->loc.lb_num);
uint16_t vpart_num = udf_rw16(node_icb_loc->loc.part_num);
/* free disc allocation for node */
udf_free_allocated_space(ump, lb_num, vpart_num, 1);
/* recycle udf_node */
udf_dispose_node(udf_node);
vrele(nvp);
vrele(*vpp);
*vpp = NULL;
return error;
@ -5888,76 +5910,7 @@ udf_create_node_raw(struct vnode *dvp, struct vnode **vpp, int udf_file_type,
/* adjust file count */
udf_adjust_filecount(udf_node, 1);
/* return result */
*vpp = nvp;
return 0;
error_out_unreserve:
udf_do_unreserve_space(ump, NULL, vpart_num, 1);
error_out_unget:
nvp->v_data = NULL;
ungetnewvnode(nvp);
return error;
}
int
udf_create_node(struct vnode *dvp, struct vnode **vpp, struct vattr *vap,
struct componentname *cnp)
{
int (**vnodeops)(void *);
int udf_file_type;
DPRINTF(NODE, ("udf_create_node called\n"));
/* what type are we creating ? */
vnodeops = udf_vnodeop_p;
/* start with a default */
udf_file_type = UDF_ICB_FILETYPE_RANDOMACCESS;
*vpp = NULL;
switch (vap->va_type) {
case VREG :
udf_file_type = UDF_ICB_FILETYPE_RANDOMACCESS;
break;
case VDIR :
udf_file_type = UDF_ICB_FILETYPE_DIRECTORY;
break;
case VLNK :
udf_file_type = UDF_ICB_FILETYPE_SYMLINK;
break;
case VBLK :
udf_file_type = UDF_ICB_FILETYPE_BLOCKDEVICE;
/* specfs */
return ENOTSUP;
break;
case VCHR :
udf_file_type = UDF_ICB_FILETYPE_CHARDEVICE;
/* specfs */
return ENOTSUP;
break;
case VFIFO :
udf_file_type = UDF_ICB_FILETYPE_FIFO;
/* specfs */
return ENOTSUP;
break;
case VSOCK :
udf_file_type = UDF_ICB_FILETYPE_SOCKET;
/* specfs */
return ENOTSUP;
break;
case VNON :
case VBAD :
default :
/* nothing; can we even create these? */
return EINVAL;
}
return udf_create_node_raw(dvp, vpp, udf_file_type, vnodeops, vap, cnp);
}
/* --------------------------------------------------------------------- */

View File

@ -1,4 +1,4 @@
/* $NetBSD: udf_vfsops.c,v 1.67 2014/04/16 18:55:19 maxv Exp $ */
/* $NetBSD: udf_vfsops.c,v 1.68 2015/04/06 08:39:23 hannken Exp $ */
/*
* Copyright (c) 2006, 2008 Reinoud Zandijk
@ -28,7 +28,7 @@
#include <sys/cdefs.h>
#ifndef lint
__KERNEL_RCSID(0, "$NetBSD: udf_vfsops.c,v 1.67 2014/04/16 18:55:19 maxv Exp $");
__KERNEL_RCSID(0, "$NetBSD: udf_vfsops.c,v 1.68 2015/04/06 08:39:23 hannken Exp $");
#endif /* not lint */
@ -79,9 +79,6 @@ MALLOC_JUSTDEFINE(M_UDFVOLD, "UDF volspace", "UDF volume space descriptors");
MALLOC_JUSTDEFINE(M_UDFTEMP, "UDF temp", "UDF scrap space");
struct pool udf_node_pool;
/* supported functions predefined */
VFS_PROTOS(udf);
static struct sysctllog *udf_sysctl_log;
/* internal functions */
@ -111,6 +108,8 @@ struct vfsops udf_vfsops = {
.vfs_statvfs = udf_statvfs,
.vfs_sync = udf_sync,
.vfs_vget = udf_vget,
.vfs_loadvnode = udf_loadvnode,
.vfs_newvnode = udf_newvnode,
.vfs_fhtovp = udf_fhtovp,
.vfs_vptofh = udf_vptofh,
.vfs_init = udf_init,
@ -261,7 +260,6 @@ free_udf_mountinfo(struct mount *mp)
MPFREE(ump->la_lmapping, M_TEMP);
mutex_destroy(&ump->ihash_lock);
mutex_destroy(&ump->get_node_lock);
mutex_destroy(&ump->logvol_mutex);
mutex_destroy(&ump->allocate_mutex);
cv_destroy(&ump->dirtynodes_cv);
@ -584,7 +582,6 @@ udf_mountfs(struct vnode *devvp, struct mount *mp,
/* init locks */
mutex_init(&ump->logvol_mutex, MUTEX_DEFAULT, IPL_NONE);
mutex_init(&ump->ihash_lock, MUTEX_DEFAULT, IPL_NONE);
mutex_init(&ump->get_node_lock, MUTEX_DEFAULT, IPL_NONE);
mutex_init(&ump->allocate_mutex, MUTEX_DEFAULT, IPL_NONE);
cv_init(&ump->dirtynodes_cv, "udfsync2");

View File

@ -1,4 +1,4 @@
/* $NetBSD: udf_vnops.c,v 1.99 2015/04/06 08:38:25 hannken Exp $ */
/* $NetBSD: udf_vnops.c,v 1.100 2015/04/06 08:39:23 hannken Exp $ */
/*
* Copyright (c) 2006, 2008 Reinoud Zandijk
@ -32,7 +32,7 @@
#include <sys/cdefs.h>
#ifndef lint
__KERNEL_RCSID(0, "$NetBSD: udf_vnops.c,v 1.99 2015/04/06 08:38:25 hannken Exp $");
__KERNEL_RCSID(0, "$NetBSD: udf_vnops.c,v 1.100 2015/04/06 08:39:23 hannken Exp $");
#endif /* not lint */
@ -129,8 +129,6 @@ udf_inactive(void *v)
/* --------------------------------------------------------------------- */
int udf_sync(struct mount *mp, int waitfor, kauth_cred_t cred, struct lwp *lwp);
int
udf_reclaim(void *v)
{
@ -176,6 +174,9 @@ udf_reclaim(void *v)
tsleep(&udf_node->outstanding_nodedscr, PRIBIO, "recl wait", hz/8);
}
vcache_remove(vp->v_mount, &udf_node->loc.loc,
sizeof(udf_node->loc.loc));
/* dispose all node knowledge */
udf_dispose_node(udf_node);