Changeset View
Changeset View
Standalone View
Standalone View
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c
Show First 20 Lines • Show All 59 Lines • ▼ Show 20 Lines | |||||
#include <sys/zfs_ctldir.h> | #include <sys/zfs_ctldir.h> | ||||
#include <sys/zfs_fuid.h> | #include <sys/zfs_fuid.h> | ||||
#include <sys/sunddi.h> | #include <sys/sunddi.h> | ||||
#include <sys/dnlc.h> | #include <sys/dnlc.h> | ||||
#include <sys/dmu_objset.h> | #include <sys/dmu_objset.h> | ||||
#include <sys/spa_boot.h> | #include <sys/spa_boot.h> | ||||
#include <sys/jail.h> | #include <sys/jail.h> | ||||
#include <ufs/ufs/quota.h> | #include <ufs/ufs/quota.h> | ||||
#include <sys/rmlock.h> | |||||
#include "zfs_comutil.h" | #include "zfs_comutil.h" | ||||
struct mtx zfs_debug_mtx; | struct mtx zfs_debug_mtx; | ||||
MTX_SYSINIT(zfs_debug_mtx, &zfs_debug_mtx, "zfs_debug", MTX_DEF); | MTX_SYSINIT(zfs_debug_mtx, &zfs_debug_mtx, "zfs_debug", MTX_DEF); | ||||
SYSCTL_NODE(_vfs, OID_AUTO, zfs, CTLFLAG_RW, 0, "ZFS file system"); | SYSCTL_NODE(_vfs, OID_AUTO, zfs, CTLFLAG_RW, 0, "ZFS file system"); | ||||
Show All 11 Lines | SYSCTL_INT(_vfs_zfs_version, OID_AUTO, acl, CTLFLAG_RD, &zfs_version_acl, 0, | ||||
"ZFS_ACL_VERSION"); | "ZFS_ACL_VERSION"); | ||||
static int zfs_version_spa = SPA_VERSION; | static int zfs_version_spa = SPA_VERSION; | ||||
SYSCTL_INT(_vfs_zfs_version, OID_AUTO, spa, CTLFLAG_RD, &zfs_version_spa, 0, | SYSCTL_INT(_vfs_zfs_version, OID_AUTO, spa, CTLFLAG_RD, &zfs_version_spa, 0, | ||||
"SPA_VERSION"); | "SPA_VERSION"); | ||||
static int zfs_version_zpl = ZPL_VERSION; | static int zfs_version_zpl = ZPL_VERSION; | ||||
SYSCTL_INT(_vfs_zfs_version, OID_AUTO, zpl, CTLFLAG_RD, &zfs_version_zpl, 0, | SYSCTL_INT(_vfs_zfs_version, OID_AUTO, zpl, CTLFLAG_RD, &zfs_version_zpl, 0, | ||||
"ZPL_VERSION"); | "ZPL_VERSION"); | ||||
static int zfs_root_setvnode(zfsvfs_t *zfsvfs); | |||||
static void zfs_root_dropvnode(zfsvfs_t *zfsvfs); | |||||
static int zfs_quotactl(vfs_t *vfsp, int cmds, uid_t id, void *arg); | static int zfs_quotactl(vfs_t *vfsp, int cmds, uid_t id, void *arg); | ||||
static int zfs_mount(vfs_t *vfsp); | static int zfs_mount(vfs_t *vfsp); | ||||
static int zfs_umount(vfs_t *vfsp, int fflag); | static int zfs_umount(vfs_t *vfsp, int fflag); | ||||
static int zfs_root(vfs_t *vfsp, int flags, vnode_t **vpp); | static int zfs_root(vfs_t *vfsp, int flags, vnode_t **vpp); | ||||
static int zfs_statfs(vfs_t *vfsp, struct statfs *statp); | static int zfs_statfs(vfs_t *vfsp, struct statfs *statp); | ||||
static int zfs_vget(vfs_t *vfsp, ino_t ino, int flags, vnode_t **vpp); | static int zfs_vget(vfs_t *vfsp, ino_t ino, int flags, vnode_t **vpp); | ||||
static int zfs_sync(vfs_t *vfsp, int waitfor); | static int zfs_sync(vfs_t *vfsp, int waitfor); | ||||
static int zfs_checkexp(vfs_t *vfsp, struct sockaddr *nam, int *extflagsp, | static int zfs_checkexp(vfs_t *vfsp, struct sockaddr *nam, int *extflagsp, | ||||
▲ Show 20 Lines • Show All 1,101 Lines • ▼ Show 20 Lines | |||||
#else | #else | ||||
rrm_init(&zfsvfs->z_teardown_lock, B_FALSE); | rrm_init(&zfsvfs->z_teardown_lock, B_FALSE); | ||||
#endif | #endif | ||||
rw_init(&zfsvfs->z_teardown_inactive_lock, NULL, RW_DEFAULT, NULL); | rw_init(&zfsvfs->z_teardown_inactive_lock, NULL, RW_DEFAULT, NULL); | ||||
rw_init(&zfsvfs->z_fuid_lock, NULL, RW_DEFAULT, NULL); | rw_init(&zfsvfs->z_fuid_lock, NULL, RW_DEFAULT, NULL); | ||||
for (int i = 0; i != ZFS_OBJ_MTX_SZ; i++) | for (int i = 0; i != ZFS_OBJ_MTX_SZ; i++) | ||||
mutex_init(&zfsvfs->z_hold_mtx[i], NULL, MUTEX_DEFAULT, NULL); | mutex_init(&zfsvfs->z_hold_mtx[i], NULL, MUTEX_DEFAULT, NULL); | ||||
rm_init(&zfsvfs->z_rootvnodelock, "zfs root vnode lock"); | |||||
error = zfsvfs_init(zfsvfs, os); | error = zfsvfs_init(zfsvfs, os); | ||||
if (error != 0) { | if (error != 0) { | ||||
*zfvp = NULL; | *zfvp = NULL; | ||||
kmem_free(zfsvfs, sizeof (zfsvfs_t)); | kmem_free(zfsvfs, sizeof (zfsvfs_t)); | ||||
return (error); | return (error); | ||||
} | } | ||||
*zfvp = zfsvfs; | *zfvp = zfsvfs; | ||||
▲ Show 20 Lines • Show All 90 Lines • ▼ Show 20 Lines | zfsvfs_free(zfsvfs_t *zfsvfs) | ||||
* This is a barrier to prevent the filesystem from going away in | * This is a barrier to prevent the filesystem from going away in | ||||
* zfs_znode_move() until we can safely ensure that the filesystem is | * zfs_znode_move() until we can safely ensure that the filesystem is | ||||
* not unmounted. We consider the filesystem valid before the barrier | * not unmounted. We consider the filesystem valid before the barrier | ||||
* and invalid after the barrier. | * and invalid after the barrier. | ||||
*/ | */ | ||||
rw_enter(&zfsvfs_lock, RW_READER); | rw_enter(&zfsvfs_lock, RW_READER); | ||||
rw_exit(&zfsvfs_lock); | rw_exit(&zfsvfs_lock); | ||||
rm_destroy(&zfsvfs->z_rootvnodelock); | |||||
zfs_fuid_destroy(zfsvfs); | zfs_fuid_destroy(zfsvfs); | ||||
mutex_destroy(&zfsvfs->z_znodes_lock); | mutex_destroy(&zfsvfs->z_znodes_lock); | ||||
mutex_destroy(&zfsvfs->z_lock); | mutex_destroy(&zfsvfs->z_lock); | ||||
list_destroy(&zfsvfs->z_all_znodes); | list_destroy(&zfsvfs->z_all_znodes); | ||||
rrm_destroy(&zfsvfs->z_teardown_lock); | rrm_destroy(&zfsvfs->z_teardown_lock); | ||||
rw_destroy(&zfsvfs->z_teardown_inactive_lock); | rw_destroy(&zfsvfs->z_teardown_inactive_lock); | ||||
rw_destroy(&zfsvfs->z_fuid_lock); | rw_destroy(&zfsvfs->z_fuid_lock); | ||||
▲ Show 20 Lines • Show All 590 Lines • ▼ Show 20 Lines | if (error == 0) | ||||
error = spa_import_rootpool(pname); | error = spa_import_rootpool(pname); | ||||
if (error) | if (error) | ||||
goto out; | goto out; | ||||
} | } | ||||
DROP_GIANT(); | DROP_GIANT(); | ||||
error = zfs_domount(vfsp, osname); | error = zfs_domount(vfsp, osname); | ||||
PICKUP_GIANT(); | PICKUP_GIANT(); | ||||
zfs_root_setvnode((zfsvfs_t *)vfsp->vfs_data); | |||||
#ifdef illumos | #ifdef illumos | ||||
/* | /* | ||||
* Add an extra VFS_HOLD on our parent vfs so that it can't | * Add an extra VFS_HOLD on our parent vfs so that it can't | ||||
* disappear due to a forced unmount. | * disappear due to a forced unmount. | ||||
*/ | */ | ||||
if (error == 0 && ((zfsvfs_t *)vfsp->vfs_data)->z_issnap) | if (error == 0 && ((zfsvfs_t *)vfsp->vfs_data)->z_issnap) | ||||
VFS_HOLD(mvp->v_vfsp); | VFS_HOLD(mvp->v_vfsp); | ||||
#endif | #endif | ||||
▲ Show 20 Lines • Show All 56 Lines • ▼ Show 20 Lines | zfs_statfs(vfs_t *vfsp, struct statfs *statp) | ||||
statp->f_namemax = MAXNAMELEN - 1; | statp->f_namemax = MAXNAMELEN - 1; | ||||
ZFS_EXIT(zfsvfs); | ZFS_EXIT(zfsvfs); | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
zfs_root_setvnode(zfsvfs_t *zfsvfs) | |||||
{ | |||||
znode_t *rootzp; | |||||
int error; | |||||
ZFS_ENTER(zfsvfs); | |||||
error = zfs_zget(zfsvfs, zfsvfs->z_root, &rootzp); | |||||
if (error != 0) | |||||
panic("could not zfs_zget for root vnode"); | |||||
ZFS_EXIT(zfsvfs); | |||||
rm_wlock(&zfsvfs->z_rootvnodelock); | |||||
if (zfsvfs->z_rootvnode != NULL) | |||||
panic("zfs mount point already has a root vnode: %p\n", | |||||
zfsvfs->z_rootvnode); | |||||
zfsvfs->z_rootvnode = ZTOV(rootzp); | |||||
rm_wunlock(&zfsvfs->z_rootvnodelock); | |||||
return (0); | |||||
} | |||||
static void | |||||
zfs_root_putvnode(zfsvfs_t *zfsvfs) | |||||
{ | |||||
struct vnode *vp; | |||||
rm_wlock(&zfsvfs->z_rootvnodelock); | |||||
vp = zfsvfs->z_rootvnode; | |||||
zfsvfs->z_rootvnode = NULL; | |||||
rm_wunlock(&zfsvfs->z_rootvnodelock); | |||||
if (vp != NULL) | |||||
vrele(vp); | |||||
} | |||||
static int | |||||
zfs_root(vfs_t *vfsp, int flags, vnode_t **vpp) | zfs_root(vfs_t *vfsp, int flags, vnode_t **vpp) | ||||
{ | { | ||||
struct rm_priotracker tracker; | |||||
zfsvfs_t *zfsvfs = vfsp->vfs_data; | zfsvfs_t *zfsvfs = vfsp->vfs_data; | ||||
znode_t *rootzp; | znode_t *rootzp; | ||||
int error; | int error; | ||||
ZFS_ENTER(zfsvfs); | rm_rlock(&zfsvfs->z_rootvnodelock, &tracker); | ||||
*vpp = zfsvfs->z_rootvnode; | |||||
if (*vpp != NULL && (((*vpp)->v_iflag & VI_DOOMED) == 0)) { | |||||
vrefact(*vpp); | |||||
rm_runlock(&zfsvfs->z_rootvnodelock, &tracker); | |||||
goto lock; | |||||
} | |||||
rm_runlock(&zfsvfs->z_rootvnodelock, &tracker); | |||||
/* | |||||
* We found the vnode but did not like it. | |||||
*/ | |||||
if (*vpp != NULL) { | |||||
*vpp = NULL; | |||||
zfs_root_putvnode(zfsvfs); | |||||
} | |||||
ZFS_ENTER(zfsvfs); | |||||
error = zfs_zget(zfsvfs, zfsvfs->z_root, &rootzp); | error = zfs_zget(zfsvfs, zfsvfs->z_root, &rootzp); | ||||
if (error == 0) | if (error == 0) | ||||
*vpp = ZTOV(rootzp); | *vpp = ZTOV(rootzp); | ||||
ZFS_EXIT(zfsvfs); | ZFS_EXIT(zfsvfs); | ||||
if (error == 0) { | if (error == 0) { | ||||
lock: | |||||
error = vn_lock(*vpp, flags); | error = vn_lock(*vpp, flags); | ||||
if (error != 0) { | if (error != 0) { | ||||
VN_RELE(*vpp); | VN_RELE(*vpp); | ||||
*vpp = NULL; | *vpp = NULL; | ||||
} | } | ||||
} | } | ||||
return (error); | return (error); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 101 Lines • ▼ Show 20 Lines | |||||
static int | static int | ||||
zfs_umount(vfs_t *vfsp, int fflag) | zfs_umount(vfs_t *vfsp, int fflag) | ||||
{ | { | ||||
kthread_t *td = curthread; | kthread_t *td = curthread; | ||||
zfsvfs_t *zfsvfs = vfsp->vfs_data; | zfsvfs_t *zfsvfs = vfsp->vfs_data; | ||||
objset_t *os; | objset_t *os; | ||||
cred_t *cr = td->td_ucred; | cred_t *cr = td->td_ucred; | ||||
int ret; | int ret; | ||||
zfs_root_putvnode(zfsvfs); | |||||
ret = secpolicy_fs_unmount(cr, vfsp); | ret = secpolicy_fs_unmount(cr, vfsp); | ||||
if (ret) { | if (ret) { | ||||
if (dsl_deleg_access((char *)refstr_value(vfsp->vfs_resource), | if (dsl_deleg_access((char *)refstr_value(vfsp->vfs_resource), | ||||
ZFS_DELEG_PERM_MOUNT, cr)) | ZFS_DELEG_PERM_MOUNT, cr)) | ||||
return (ret); | return (ret); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 653 Lines • Show Last 20 Lines |