Changeset View
Changeset View
Standalone View
Standalone View
sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c
Show First 20 Lines • Show All 93 Lines • ▼ Show 20 Lines | |||||
*/ | */ | ||||
#ifdef _KERNEL | #ifdef _KERNEL | ||||
/* | /* | ||||
* Needed to close a small window in zfs_znode_move() that allows the zfsvfs to | * Needed to close a small window in zfs_znode_move() that allows the zfsvfs to | ||||
* be freed before it can be safely accessed. | * be freed before it can be safely accessed. | ||||
*/ | */ | ||||
krwlock_t zfsvfs_lock; | krwlock_t zfsvfs_lock; | ||||
#if defined(_KERNEL) && !defined(KMEM_DEBUG) | |||||
#define _ZFS_USE_SMR | |||||
static uma_zone_t znode_uma_zone; | |||||
#else | |||||
static kmem_cache_t *znode_cache = NULL; | static kmem_cache_t *znode_cache = NULL; | ||||
#endif | |||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
static void | static void | ||||
znode_evict_error(dmu_buf_t *dbuf, void *user_ptr) | znode_evict_error(dmu_buf_t *dbuf, void *user_ptr) | ||||
{ | { | ||||
/* | /* | ||||
* We should never drop all dbuf refs without first clearing | * We should never drop all dbuf refs without first clearing | ||||
* the eviction callback. | * the eviction callback. | ||||
▲ Show 20 Lines • Show All 250 Lines • ▼ Show 20 Lines | zfs_znode_move(void *buf, void *newbuf, size_t size, void *arg) | ||||
list_link_replace(&ozp->z_link_node, &nzp->z_link_node); | list_link_replace(&ozp->z_link_node, &nzp->z_link_node); | ||||
mutex_exit(&zfsvfs->z_znodes_lock); | mutex_exit(&zfsvfs->z_znodes_lock); | ||||
ZFS_EXIT(zfsvfs); | ZFS_EXIT(zfsvfs); | ||||
return (KMEM_CBRC_YES); | return (KMEM_CBRC_YES); | ||||
} | } | ||||
#endif /* illumos */ | #endif /* illumos */ | ||||
#ifdef _ZFS_USE_SMR | |||||
VFS_SMR_DECLARE; | |||||
static int | |||||
zfs_znode_cache_constructor_smr(void *mem, int size __unused, void *private, int flags) | |||||
{ | |||||
return (zfs_znode_cache_constructor(mem, private, flags)); | |||||
} | |||||
static void | |||||
zfs_znode_cache_destructor_smr(void *mem, int size __unused, void *private) | |||||
{ | |||||
zfs_znode_cache_destructor(mem, private); | |||||
} | |||||
void | void | ||||
zfs_znode_init(void) | zfs_znode_init(void) | ||||
{ | { | ||||
/* | /* | ||||
* Initialize zcache | * Initialize zcache | ||||
*/ | */ | ||||
rw_init(&zfsvfs_lock, NULL, RW_DEFAULT, NULL); | rw_init(&zfsvfs_lock, NULL, RW_DEFAULT, NULL); | ||||
ASSERT(znode_uma_zone == NULL); | |||||
znode_uma_zone = uma_zcreate("zfs_znode_cache", | |||||
sizeof (znode_t), zfs_znode_cache_constructor_smr, | |||||
zfs_znode_cache_destructor_smr, NULL, NULL, 0, 0); | |||||
VFS_SMR_ZONE_SET(znode_uma_zone); | |||||
} | |||||
static znode_t * | |||||
zfs_znode_alloc_kmem(int flags) | |||||
{ | |||||
return (uma_zalloc_smr(znode_uma_zone, flags)); | |||||
} | |||||
static void | |||||
zfs_znode_free_kmem(znode_t *zp) | |||||
{ | |||||
uma_zfree_smr(znode_uma_zone, zp); | |||||
} | |||||
#else | |||||
void | |||||
zfs_znode_init(void) | |||||
{ | |||||
/* | |||||
* Initialize zcache | |||||
*/ | |||||
rw_init(&zfsvfs_lock, NULL, RW_DEFAULT, NULL); | |||||
ASSERT(znode_cache == NULL); | ASSERT(znode_cache == NULL); | ||||
znode_cache = kmem_cache_create("zfs_znode_cache", | znode_cache = kmem_cache_create("zfs_znode_cache", | ||||
sizeof (znode_t), 0, zfs_znode_cache_constructor, | sizeof (znode_t), 0, zfs_znode_cache_constructor, | ||||
zfs_znode_cache_destructor, NULL, NULL, NULL, 0); | zfs_znode_cache_destructor, NULL, NULL, NULL, 0); | ||||
kmem_cache_set_move(znode_cache, zfs_znode_move); | kmem_cache_set_move(znode_cache, zfs_znode_move); | ||||
} | } | ||||
static znode_t * | |||||
zfs_znode_alloc_kmem(int flags) | |||||
{ | |||||
return (kmem_cache_alloc(znode_cache, flags)); | |||||
} | |||||
static void | |||||
zfs_znode_free_kmem(znode_t *zp) | |||||
{ | |||||
kmem_cache_free(znode_cache, zp); | |||||
} | |||||
#endif | |||||
void | void | ||||
zfs_znode_fini(void) | zfs_znode_fini(void) | ||||
{ | { | ||||
#ifdef illumos | #ifdef illumos | ||||
/* | /* | ||||
* Cleanup vfs & vnode ops | * Cleanup vfs & vnode ops | ||||
*/ | */ | ||||
zfs_remove_op_tables(); | zfs_remove_op_tables(); | ||||
#endif | #endif | ||||
/* | /* | ||||
* Cleanup zcache | * Cleanup zcache | ||||
*/ | */ | ||||
if (znode_cache) | #ifdef _ZFS_USE_SMR | ||||
if (znode_uma_zone) { | |||||
uma_zdestroy(znode_uma_zone); | |||||
znode_uma_zone = NULL; | |||||
} | |||||
#else | |||||
if (znode_cache) { | |||||
kmem_cache_destroy(znode_cache); | kmem_cache_destroy(znode_cache); | ||||
znode_cache = NULL; | znode_cache = NULL; | ||||
} | |||||
#endif | |||||
rw_destroy(&zfsvfs_lock); | rw_destroy(&zfsvfs_lock); | ||||
} | } | ||||
#ifdef illumos | #ifdef illumos | ||||
struct vnodeops *zfs_dvnodeops; | struct vnodeops *zfs_dvnodeops; | ||||
struct vnodeops *zfs_fvnodeops; | struct vnodeops *zfs_fvnodeops; | ||||
struct vnodeops *zfs_symvnodeops; | struct vnodeops *zfs_symvnodeops; | ||||
struct vnodeops *zfs_xdvnodeops; | struct vnodeops *zfs_xdvnodeops; | ||||
▲ Show 20 Lines • Show All 96 Lines • ▼ Show 20 Lines | zfs_create_share_dir(zfsvfs_t *zfsvfs, dmu_tx_t *tx) | ||||
int error; | int error; | ||||
vattr.va_mask = AT_MODE|AT_UID|AT_GID|AT_TYPE; | vattr.va_mask = AT_MODE|AT_UID|AT_GID|AT_TYPE; | ||||
vattr.va_type = VDIR; | vattr.va_type = VDIR; | ||||
vattr.va_mode = S_IFDIR|0555; | vattr.va_mode = S_IFDIR|0555; | ||||
vattr.va_uid = crgetuid(kcred); | vattr.va_uid = crgetuid(kcred); | ||||
vattr.va_gid = crgetgid(kcred); | vattr.va_gid = crgetgid(kcred); | ||||
sharezp = kmem_cache_alloc(znode_cache, KM_SLEEP); | sharezp = zfs_znode_alloc_kmem(KM_SLEEP); | ||||
ASSERT(!POINTER_IS_VALID(sharezp->z_zfsvfs)); | ASSERT(!POINTER_IS_VALID(sharezp->z_zfsvfs)); | ||||
sharezp->z_moved = 0; | sharezp->z_moved = 0; | ||||
sharezp->z_unlinked = 0; | sharezp->z_unlinked = 0; | ||||
sharezp->z_atime_dirty = 0; | sharezp->z_atime_dirty = 0; | ||||
sharezp->z_zfsvfs = zfsvfs; | sharezp->z_zfsvfs = zfsvfs; | ||||
sharezp->z_is_sa = zfsvfs->z_use_sa; | sharezp->z_is_sa = zfsvfs->z_use_sa; | ||||
VERIFY(0 == zfs_acl_ids_create(sharezp, IS_ROOT_NODE, &vattr, | VERIFY(0 == zfs_acl_ids_create(sharezp, IS_ROOT_NODE, &vattr, | ||||
kcred, NULL, &acl_ids)); | kcred, NULL, &acl_ids)); | ||||
zfs_mknode(sharezp, &vattr, tx, kcred, IS_ROOT_NODE, &zp, &acl_ids); | zfs_mknode(sharezp, &vattr, tx, kcred, IS_ROOT_NODE, &zp, &acl_ids); | ||||
ASSERT3P(zp, ==, sharezp); | ASSERT3P(zp, ==, sharezp); | ||||
POINTER_INVALIDATE(&sharezp->z_zfsvfs); | POINTER_INVALIDATE(&sharezp->z_zfsvfs); | ||||
error = zap_add(zfsvfs->z_os, MASTER_NODE_OBJ, | error = zap_add(zfsvfs->z_os, MASTER_NODE_OBJ, | ||||
ZFS_SHARES_DIR, 8, 1, &sharezp->z_id, tx); | ZFS_SHARES_DIR, 8, 1, &sharezp->z_id, tx); | ||||
zfsvfs->z_shares_dir = sharezp->z_id; | zfsvfs->z_shares_dir = sharezp->z_id; | ||||
zfs_acl_ids_free(&acl_ids); | zfs_acl_ids_free(&acl_ids); | ||||
sa_handle_destroy(sharezp->z_sa_hdl); | sa_handle_destroy(sharezp->z_sa_hdl); | ||||
kmem_cache_free(znode_cache, sharezp); | zfs_znode_free_kmem(sharezp); | ||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
* define a couple of values we need available | * define a couple of values we need available | ||||
* for both 64 and 32 bit environments. | * for both 64 and 32 bit environments. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 98 Lines • ▼ Show 20 Lines | zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_buf_t *db, int blksz, | ||||
znode_t *zp; | znode_t *zp; | ||||
vnode_t *vp; | vnode_t *vp; | ||||
uint64_t mode; | uint64_t mode; | ||||
uint64_t parent; | uint64_t parent; | ||||
sa_bulk_attr_t bulk[9]; | sa_bulk_attr_t bulk[9]; | ||||
int count = 0; | int count = 0; | ||||
int error; | int error; | ||||
zp = kmem_cache_alloc(znode_cache, KM_SLEEP); | zp = zfs_znode_alloc_kmem(KM_SLEEP); | ||||
#ifndef _ZFS_USE_SMR | |||||
KASSERT((zfsvfs->z_parent->z_vfs->mnt_kern_flag & MNTK_FPLOOKUP) == 0, | |||||
("%s: fast path lookup enabled without smr", __func__)); | |||||
#endif | |||||
KASSERT(curthread->td_vp_reserved != NULL, | KASSERT(curthread->td_vp_reserved != NULL, | ||||
("zfs_znode_alloc: getnewvnode without preallocated vnode")); | ("zfs_znode_alloc: getnewvnode without preallocated vnode")); | ||||
error = getnewvnode("zfs", zfsvfs->z_parent->z_vfs, &zfs_vnodeops, &vp); | error = getnewvnode("zfs", zfsvfs->z_parent->z_vfs, &zfs_vnodeops, &vp); | ||||
if (error != 0) { | if (error != 0) { | ||||
kmem_cache_free(znode_cache, zp); | zfs_znode_free_kmem(zp); | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
zp->z_vnode = vp; | zp->z_vnode = vp; | ||||
vp->v_data = zp; | vp->v_data = zp; | ||||
ASSERT(!POINTER_IS_VALID(zp->z_zfsvfs)); | ASSERT(!POINTER_IS_VALID(zp->z_zfsvfs)); | ||||
zp->z_moved = 0; | zp->z_moved = 0; | ||||
Show All 30 Lines | #endif | ||||
SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_GID(zfsvfs), NULL, | SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_GID(zfsvfs), NULL, | ||||
&zp->z_gid, 8); | &zp->z_gid, 8); | ||||
if (sa_bulk_lookup(zp->z_sa_hdl, bulk, count) != 0 || zp->z_gen == 0) { | if (sa_bulk_lookup(zp->z_sa_hdl, bulk, count) != 0 || zp->z_gen == 0) { | ||||
if (hdl == NULL) | if (hdl == NULL) | ||||
sa_handle_destroy(zp->z_sa_hdl); | sa_handle_destroy(zp->z_sa_hdl); | ||||
zfs_vnode_forget(vp); | zfs_vnode_forget(vp); | ||||
zp->z_vnode = NULL; | zp->z_vnode = NULL; | ||||
kmem_cache_free(znode_cache, zp); | zfs_znode_free_kmem(zp); | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
zp->z_mode = mode; | zp->z_mode = mode; | ||||
vp->v_type = IFTOVT((mode_t)mode); | vp->v_type = IFTOVT((mode_t)mode); | ||||
switch (vp->v_type) { | switch (vp->v_type) { | ||||
▲ Show 20 Lines • Show All 349 Lines • ▼ Show 20 Lines | |||||
void | void | ||||
zfs_xvattr_set(znode_t *zp, xvattr_t *xvap, dmu_tx_t *tx) | zfs_xvattr_set(znode_t *zp, xvattr_t *xvap, dmu_tx_t *tx) | ||||
{ | { | ||||
xoptattr_t *xoap; | xoptattr_t *xoap; | ||||
xoap = xva_getxoptattr(xvap); | xoap = xva_getxoptattr(xvap); | ||||
ASSERT(xoap); | ASSERT(xoap); | ||||
ASSERT_VOP_IN_SEQC(ZTOV(zp)); | |||||
if (XVA_ISSET_REQ(xvap, XAT_CREATETIME)) { | if (XVA_ISSET_REQ(xvap, XAT_CREATETIME)) { | ||||
uint64_t times[2]; | uint64_t times[2]; | ||||
ZFS_TIME_ENCODE(&xoap->xoa_createtime, times); | ZFS_TIME_ENCODE(&xoap->xoa_createtime, times); | ||||
(void) sa_update(zp->z_sa_hdl, SA_ZPL_CRTIME(zp->z_zfsvfs), | (void) sa_update(zp->z_sa_hdl, SA_ZPL_CRTIME(zp->z_zfsvfs), | ||||
×, sizeof (times), tx); | ×, sizeof (times), tx); | ||||
XVA_SET_RTN(xvap, XAT_CREATETIME); | XVA_SET_RTN(xvap, XAT_CREATETIME); | ||||
} | } | ||||
if (XVA_ISSET_REQ(xvap, XAT_READONLY)) { | if (XVA_ISSET_REQ(xvap, XAT_READONLY)) { | ||||
▲ Show 20 Lines • Show All 413 Lines • ▼ Show 20 Lines | zfs_znode_free(znode_t *zp) | ||||
list_remove(&zfsvfs->z_all_znodes, zp); | list_remove(&zfsvfs->z_all_znodes, zp); | ||||
mutex_exit(&zfsvfs->z_znodes_lock); | mutex_exit(&zfsvfs->z_znodes_lock); | ||||
if (zp->z_acl_cached) { | if (zp->z_acl_cached) { | ||||
zfs_acl_free(zp->z_acl_cached); | zfs_acl_free(zp->z_acl_cached); | ||||
zp->z_acl_cached = NULL; | zp->z_acl_cached = NULL; | ||||
} | } | ||||
kmem_cache_free(znode_cache, zp); | zfs_znode_free_kmem(zp); | ||||
#ifdef illumos | #ifdef illumos | ||||
VFS_RELE(zfsvfs->z_vfs); | VFS_RELE(zfsvfs->z_vfs); | ||||
#endif | #endif | ||||
} | } | ||||
void | void | ||||
zfs_tstamp_update_setup(znode_t *zp, uint_t flag, uint64_t mtime[2], | zfs_tstamp_update_setup(znode_t *zp, uint_t flag, uint64_t mtime[2], | ||||
▲ Show 20 Lines • Show All 443 Lines • ▼ Show 20 Lines | zfs_create_fs(objset_t *os, cred_t *cr, nvlist_t *zplprops, dmu_tx_t *tx) | ||||
vattr.va_mask = AT_MODE|AT_UID|AT_GID|AT_TYPE; | vattr.va_mask = AT_MODE|AT_UID|AT_GID|AT_TYPE; | ||||
vattr.va_type = VDIR; | vattr.va_type = VDIR; | ||||
vattr.va_mode = S_IFDIR|0755; | vattr.va_mode = S_IFDIR|0755; | ||||
vattr.va_uid = crgetuid(cr); | vattr.va_uid = crgetuid(cr); | ||||
vattr.va_gid = crgetgid(cr); | vattr.va_gid = crgetgid(cr); | ||||
zfsvfs = kmem_zalloc(sizeof (zfsvfs_t), KM_SLEEP); | zfsvfs = kmem_zalloc(sizeof (zfsvfs_t), KM_SLEEP); | ||||
rootzp = kmem_cache_alloc(znode_cache, KM_SLEEP); | rootzp = zfs_znode_alloc_kmem(KM_SLEEP); | ||||
ASSERT(!POINTER_IS_VALID(rootzp->z_zfsvfs)); | ASSERT(!POINTER_IS_VALID(rootzp->z_zfsvfs)); | ||||
rootzp->z_moved = 0; | rootzp->z_moved = 0; | ||||
rootzp->z_unlinked = 0; | rootzp->z_unlinked = 0; | ||||
rootzp->z_atime_dirty = 0; | rootzp->z_atime_dirty = 0; | ||||
rootzp->z_is_sa = USE_SA(version, os); | rootzp->z_is_sa = USE_SA(version, os); | ||||
zfsvfs->z_os = os; | zfsvfs->z_os = os; | ||||
zfsvfs->z_parent = zfsvfs; | zfsvfs->z_parent = zfsvfs; | ||||
Show All 27 Lines | zfs_create_fs(objset_t *os, cred_t *cr, nvlist_t *zplprops, dmu_tx_t *tx) | ||||
zfs_mknode(rootzp, &vattr, tx, cr, IS_ROOT_NODE, &zp, &acl_ids); | zfs_mknode(rootzp, &vattr, tx, cr, IS_ROOT_NODE, &zp, &acl_ids); | ||||
ASSERT3P(zp, ==, rootzp); | ASSERT3P(zp, ==, rootzp); | ||||
error = zap_add(os, moid, ZFS_ROOT_OBJ, 8, 1, &rootzp->z_id, tx); | error = zap_add(os, moid, ZFS_ROOT_OBJ, 8, 1, &rootzp->z_id, tx); | ||||
ASSERT(error == 0); | ASSERT(error == 0); | ||||
zfs_acl_ids_free(&acl_ids); | zfs_acl_ids_free(&acl_ids); | ||||
POINTER_INVALIDATE(&rootzp->z_zfsvfs); | POINTER_INVALIDATE(&rootzp->z_zfsvfs); | ||||
sa_handle_destroy(rootzp->z_sa_hdl); | sa_handle_destroy(rootzp->z_sa_hdl); | ||||
kmem_cache_free(znode_cache, rootzp); | zfs_znode_free_kmem(rootzp); | ||||
/* | /* | ||||
* Create shares directory | * Create shares directory | ||||
*/ | */ | ||||
error = zfs_create_share_dir(zfsvfs, tx); | error = zfs_create_share_dir(zfsvfs, tx); | ||||
ASSERT(error == 0); | ASSERT(error == 0); | ||||
▲ Show 20 Lines • Show All 303 Lines • Show Last 20 Lines |