Changeset View
Changeset View
Standalone View
Standalone View
sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c
Show First 20 Lines • Show All 1,946 Lines • ▼ Show 20 Lines | zfs_umount(vfs_t *vfsp, int fflag) | ||||
/* | /* | ||||
* Unmount any snapshots mounted under .zfs before unmounting the | * Unmount any snapshots mounted under .zfs before unmounting the | ||||
* dataset itself. | * dataset itself. | ||||
*/ | */ | ||||
if (zfsvfs->z_ctldir != NULL) { | if (zfsvfs->z_ctldir != NULL) { | ||||
if ((ret = zfsctl_umount_snapshots(vfsp, fflag, cr)) != 0) | if ((ret = zfsctl_umount_snapshots(vfsp, fflag, cr)) != 0) | ||||
return (ret); | return (ret); | ||||
ret = vflush(vfsp, 0, 0, td); | |||||
ASSERT(ret == EBUSY); | |||||
if (!(fflag & MS_FORCE)) { | |||||
if (zfsvfs->z_ctldir->v_count > 1) | |||||
return (EBUSY); | |||||
ASSERT(zfsvfs->z_ctldir->v_count == 1); | |||||
} | } | ||||
zfsctl_destroy(zfsvfs); | |||||
ASSERT(zfsvfs->z_ctldir == NULL); | |||||
} | |||||
if (fflag & MS_FORCE) { | if (fflag & MS_FORCE) { | ||||
/* | /* | ||||
* Mark file system as unmounted before calling | * Mark file system as unmounted before calling | ||||
* vflush(FORCECLOSE). This way we ensure no future vnops | * vflush(FORCECLOSE). This way we ensure no future vnops | ||||
* will be called and risk operating on DOOMED vnodes. | * will be called and risk operating on DOOMED vnodes. | ||||
*/ | */ | ||||
rrm_enter(&zfsvfs->z_teardown_lock, RW_WRITER, FTAG); | rrm_enter(&zfsvfs->z_teardown_lock, RW_WRITER, FTAG); | ||||
zfsvfs->z_unmounted = B_TRUE; | zfsvfs->z_unmounted = B_TRUE; | ||||
rrm_exit(&zfsvfs->z_teardown_lock, FTAG); | rrm_exit(&zfsvfs->z_teardown_lock, FTAG); | ||||
} | } | ||||
/* | /* | ||||
* Flush all the files. | * Flush all the files. | ||||
*/ | */ | ||||
ret = vflush(vfsp, 0, (fflag & MS_FORCE) ? FORCECLOSE : 0, td); | ret = vflush(vfsp, 0, (fflag & MS_FORCE) ? FORCECLOSE : 0, td); | ||||
if (ret != 0) { | if (ret != 0) | ||||
if (!zfsvfs->z_issnap) { | |||||
zfsctl_create(zfsvfs); | |||||
ASSERT(zfsvfs->z_ctldir != NULL); | |||||
} | |||||
return (ret); | return (ret); | ||||
} | |||||
#ifdef illumos | #ifdef illumos | ||||
if (!(fflag & MS_FORCE)) { | if (!(fflag & MS_FORCE)) { | ||||
/* | /* | ||||
* Check the number of active vnodes in the file system. | * Check the number of active vnodes in the file system. | ||||
* Our count is maintained in the vfs structure, but the | * Our count is maintained in the vfs structure, but the | ||||
* number is off by 1 to indicate a hold on the vfs | * number is off by 1 to indicate a hold on the vfs | ||||
* structure itself. | * structure itself. | ||||
▲ Show 20 Lines • Show All 94 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
CTASSERT(SHORT_FID_LEN <= sizeof(struct fid)); | CTASSERT(SHORT_FID_LEN <= sizeof(struct fid)); | ||||
CTASSERT(LONG_FID_LEN <= sizeof(struct fid)); | CTASSERT(LONG_FID_LEN <= sizeof(struct fid)); | ||||
static int | static int | ||||
zfs_fhtovp(vfs_t *vfsp, fid_t *fidp, int flags, vnode_t **vpp) | zfs_fhtovp(vfs_t *vfsp, fid_t *fidp, int flags, vnode_t **vpp) | ||||
{ | { | ||||
struct componentname cn; | |||||
zfsvfs_t *zfsvfs = vfsp->vfs_data; | zfsvfs_t *zfsvfs = vfsp->vfs_data; | ||||
znode_t *zp; | znode_t *zp; | ||||
vnode_t *dvp; | |||||
uint64_t object = 0; | uint64_t object = 0; | ||||
uint64_t fid_gen = 0; | uint64_t fid_gen = 0; | ||||
uint64_t gen_mask; | uint64_t gen_mask; | ||||
uint64_t zp_gen; | uint64_t zp_gen; | ||||
int i, err; | int i, err; | ||||
*vpp = NULL; | *vpp = NULL; | ||||
Show All 38 Lines | zfs_fhtovp(vfs_t *vfsp, fid_t *fidp, int flags, vnode_t **vpp) | ||||
/* | /* | ||||
* A zero fid_gen means we are in .zfs or the .zfs/snapshot | * A zero fid_gen means we are in .zfs or the .zfs/snapshot | ||||
* directory tree. If the object == zfsvfs->z_shares_dir, then | * directory tree. If the object == zfsvfs->z_shares_dir, then | ||||
* we are in the .zfs/shares directory tree. | * we are in the .zfs/shares directory tree. | ||||
*/ | */ | ||||
if ((fid_gen == 0 && | if ((fid_gen == 0 && | ||||
(object == ZFSCTL_INO_ROOT || object == ZFSCTL_INO_SNAPDIR)) || | (object == ZFSCTL_INO_ROOT || object == ZFSCTL_INO_SNAPDIR)) || | ||||
(zfsvfs->z_shares_dir != 0 && object == zfsvfs->z_shares_dir)) { | (zfsvfs->z_shares_dir != 0 && object == zfsvfs->z_shares_dir)) { | ||||
*vpp = zfsvfs->z_ctldir; | ZFS_EXIT(zfsvfs); | ||||
ASSERT(*vpp != NULL); | VERIFY0(zfsctl_root(zfsvfs, LK_SHARED, &dvp)); | ||||
if (object == ZFSCTL_INO_SNAPDIR) { | if (object == ZFSCTL_INO_SNAPDIR) { | ||||
VERIFY(zfsctl_root_lookup(*vpp, "snapshot", vpp, NULL, | cn.cn_nameptr = "snapshot"; | ||||
0, NULL, NULL, NULL, NULL, NULL) == 0); | cn.cn_namelen = strlen(cn.cn_nameptr); | ||||
cn.cn_nameiop = LOOKUP; | |||||
cn.cn_flags = ISLASTCN | LOCKLEAF; | |||||
cn.cn_lkflags = flags; | |||||
VERIFY0(VOP_LOOKUP(dvp, vpp, &cn)); | |||||
vput(dvp); | |||||
} else if (object == zfsvfs->z_shares_dir) { | } else if (object == zfsvfs->z_shares_dir) { | ||||
VERIFY(zfsctl_root_lookup(*vpp, "shares", vpp, NULL, | /* | ||||
0, NULL, NULL, NULL, NULL, NULL) == 0); | * XXX This branch must not be taken, | ||||
* if it is, then the lookup below will | |||||
* explode. | |||||
*/ | |||||
cn.cn_nameptr = "shares"; | |||||
cn.cn_namelen = strlen(cn.cn_nameptr); | |||||
cn.cn_nameiop = LOOKUP; | |||||
cn.cn_flags = ISLASTCN; | |||||
cn.cn_lkflags = flags; | |||||
VERIFY0(VOP_LOOKUP(dvp, vpp, &cn)); | |||||
vput(dvp); | |||||
} else { | } else { | ||||
vref(*vpp); | *vpp = dvp; | ||||
} | } | ||||
ZFS_EXIT(zfsvfs); | |||||
err = vn_lock(*vpp, flags); | |||||
if (err != 0) | |||||
*vpp = NULL; | |||||
return (err); | return (err); | ||||
} | } | ||||
gen_mask = -1ULL >> (64 - 8 * i); | gen_mask = -1ULL >> (64 - 8 * i); | ||||
dprintf("getting %llu [%u mask %llx]\n", object, fid_gen, gen_mask); | dprintf("getting %llu [%u mask %llx]\n", object, fid_gen, gen_mask); | ||||
if (err = zfs_zget(zfsvfs, object, &zp)) { | if (err = zfs_zget(zfsvfs, object, &zp)) { | ||||
ZFS_EXIT(zfsvfs); | ZFS_EXIT(zfsvfs); | ||||
return (err); | return (err); | ||||
} | } | ||||
(void) sa_lookup(zp->z_sa_hdl, SA_ZPL_GEN(zfsvfs), &zp_gen, | (void) sa_lookup(zp->z_sa_hdl, SA_ZPL_GEN(zfsvfs), &zp_gen, | ||||
sizeof (uint64_t)); | sizeof (uint64_t)); | ||||
zp_gen = zp_gen & gen_mask; | zp_gen = zp_gen & gen_mask; | ||||
if (zp_gen == 0) | if (zp_gen == 0) | ||||
zp_gen = 1; | zp_gen = 1; | ||||
if (zp->z_unlinked || zp_gen != fid_gen) { | if (zp->z_unlinked || zp_gen != fid_gen) { | ||||
dprintf("znode gen (%u) != fid gen (%u)\n", zp_gen, fid_gen); | dprintf("znode gen (%u) != fid gen (%u)\n", zp_gen, fid_gen); | ||||
vrele(ZTOV(zp)); | vrele(ZTOV(zp)); | ||||
ZFS_EXIT(zfsvfs); | ZFS_EXIT(zfsvfs); | ||||
return (SET_ERROR(EINVAL)); | return (SET_ERROR(EINVAL)); | ||||
} | } | ||||
*vpp = ZTOV(zp); | *vpp = ZTOV(zp); | ||||
ZFS_EXIT(zfsvfs); | ZFS_EXIT(zfsvfs); | ||||
err = vn_lock(*vpp, flags | LK_RETRY); | err = vn_lock(*vpp, flags); | ||||
if (err == 0) | if (err == 0) | ||||
vnode_create_vobject(*vpp, zp->z_size, curthread); | vnode_create_vobject(*vpp, zp->z_size, curthread); | ||||
else | else | ||||
*vpp = NULL; | *vpp = NULL; | ||||
return (err); | return (err); | ||||
} | } | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 317 Lines • Show Last 20 Lines |