Changeset View
Changeset View
Standalone View
Standalone View
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c
Show First 20 Lines • Show All 74 Lines • ▼ Show 20 Lines | |||||
#include <sys/dsl_dataset.h> | #include <sys/dsl_dataset.h> | ||||
#include <sys/dsl_destroy.h> | #include <sys/dsl_destroy.h> | ||||
#include <sys/dsl_deleg.h> | #include <sys/dsl_deleg.h> | ||||
#include <sys/mount.h> | #include <sys/mount.h> | ||||
#include <sys/zap.h> | #include <sys/zap.h> | ||||
#include "zfs_namecheck.h" | #include "zfs_namecheck.h" | ||||
/* Common access mode for all virtual directories under the ctldir */ | |||||
const u_short zfsctl_ctldir_mode = S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | | |||||
S_IROTH | S_IXOTH; | |||||
/* | /* | ||||
* "Synthetic" filesystem implementation. | * "Synthetic" filesystem implementation. | ||||
*/ | */ | ||||
/* | /* | ||||
* Assert that A implies B. | * Assert that A implies B. | ||||
*/ | */ | ||||
#define KASSERT_IMPLY(A, B, msg) KASSERT(!(A) || (B), (msg)); | #define KASSERT_IMPLY(A, B, msg) KASSERT(!(A) || (B), (msg)); | ||||
▲ Show 20 Lines • Show All 400 Lines • ▼ Show 20 Lines | zfsctl_common_getattr(vnode_t *vp, vattr_t *vap) | ||||
/* | /* | ||||
* We are a purely virtual object, so we have no | * We are a purely virtual object, so we have no | ||||
* blocksize or allocated blocks. | * blocksize or allocated blocks. | ||||
*/ | */ | ||||
vap->va_blksize = 0; | vap->va_blksize = 0; | ||||
vap->va_nblocks = 0; | vap->va_nblocks = 0; | ||||
vap->va_seq = 0; | vap->va_seq = 0; | ||||
vn_fsid(vp, vap); | vn_fsid(vp, vap); | ||||
vap->va_mode = S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | | vap->va_mode = zfsctl_ctldir_mode; | ||||
S_IROTH | S_IXOTH; | |||||
vap->va_type = VDIR; | vap->va_type = VDIR; | ||||
/* | /* | ||||
* We live in the now (for atime). | * We live in the now (for atime). | ||||
*/ | */ | ||||
gethrestime(&now); | gethrestime(&now); | ||||
vap->va_atime = now; | vap->va_atime = now; | ||||
/* FreeBSD: Reset chflags(2) flags. */ | /* FreeBSD: Reset chflags(2) flags. */ | ||||
vap->va_flags = 0; | vap->va_flags = 0; | ||||
▲ Show 20 Lines • Show All 210 Lines • ▼ Show 20 Lines | zfsctl_root_vptocnp(struct vop_vptocnp_args *ap) | ||||
VOP_UNLOCK(dvp, 0); | VOP_UNLOCK(dvp, 0); | ||||
*ap->a_vpp = dvp; | *ap->a_vpp = dvp; | ||||
*ap->a_buflen -= sizeof (dotzfs_name); | *ap->a_buflen -= sizeof (dotzfs_name); | ||||
bcopy(dotzfs_name, ap->a_buf + *ap->a_buflen, sizeof (dotzfs_name)); | bcopy(dotzfs_name, ap->a_buf + *ap->a_buflen, sizeof (dotzfs_name)); | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | |||||
zfsctl_common_pathconf(ap) | |||||
struct vop_pathconf_args /* { | |||||
struct vnode *a_vp; | |||||
int a_name; | |||||
int *a_retval; | |||||
} */ *ap; | |||||
{ | |||||
/* | |||||
* We care about ACL variables so that user land utilities like ls | |||||
* can display them correctly. Since the ctldir's st_dev is set to be | |||||
* the same as the parent dataset, we must support all variables that | |||||
* it supports. | |||||
*/ | |||||
switch (ap->a_name) { | |||||
case _PC_LINK_MAX: | |||||
*ap->a_retval = INT_MAX; | |||||
return (0); | |||||
case _PC_FILESIZEBITS: | |||||
*ap->a_retval = 64; | |||||
return (0); | |||||
case _PC_MIN_HOLE_SIZE: | |||||
*ap->a_retval = (int)SPA_MINBLOCKSIZE; | |||||
return (0); | |||||
case _PC_ACL_EXTENDED: | |||||
*ap->a_retval = 0; | |||||
return (0); | |||||
case _PC_ACL_NFS4: | |||||
*ap->a_retval = 1; | |||||
return (0); | |||||
case _PC_ACL_PATH_MAX: | |||||
*ap->a_retval = ACL_MAX_ENTRIES; | |||||
return (0); | |||||
default: | |||||
return (EINVAL); | |||||
} | |||||
} | |||||
/** | |||||
* Returns a trivial ACL | |||||
*/ | |||||
int | |||||
zfsctl_common_getacl(ap) | |||||
struct vop_getacl_args /* { | |||||
struct vnode *vp; | |||||
acl_type_t a_type; | |||||
struct acl *a_aclp; | |||||
struct ucred *cred; | |||||
struct thread *td; | |||||
} */ *ap; | |||||
{ | |||||
int i; | |||||
if (ap->a_type != ACL_TYPE_NFS4) | |||||
return (EINVAL); | |||||
acl_nfs4_sync_acl_from_mode(ap->a_aclp, zfsctl_ctldir_mode, 0); | |||||
/* | |||||
* acl_nfs4_sync_acl_from_mode assumes that the owner can always modify | |||||
* attributes. That is not the case for the ctldir, so we must clear | |||||
* those bits. We also must clear ACL_READ_NAMED_ATTRS, because xattrs | |||||
* aren't supported by the ctldir. | |||||
*/ | |||||
for (i = 0; i < ap->a_aclp->acl_cnt; i++) { | |||||
struct acl_entry *entry; | |||||
entry = &(ap->a_aclp->acl_entry[i]); | |||||
uint32_t old_perm = entry->ae_perm; | |||||
entry->ae_perm &= ~(ACL_WRITE_ACL | ACL_WRITE_OWNER | | |||||
ACL_WRITE_ATTRIBUTES | ACL_WRITE_NAMED_ATTRS | | |||||
ACL_READ_NAMED_ATTRS ); | |||||
} | |||||
return (0); | |||||
} | |||||
static struct vop_vector zfsctl_ops_root = { | static struct vop_vector zfsctl_ops_root = { | ||||
.vop_default = &default_vnodeops, | .vop_default = &default_vnodeops, | ||||
.vop_open = zfsctl_common_open, | .vop_open = zfsctl_common_open, | ||||
.vop_close = zfsctl_common_close, | .vop_close = zfsctl_common_close, | ||||
.vop_ioctl = VOP_EINVAL, | .vop_ioctl = VOP_EINVAL, | ||||
.vop_getattr = zfsctl_root_getattr, | .vop_getattr = zfsctl_root_getattr, | ||||
.vop_access = zfsctl_common_access, | .vop_access = zfsctl_common_access, | ||||
.vop_readdir = zfsctl_root_readdir, | .vop_readdir = zfsctl_root_readdir, | ||||
.vop_lookup = zfsctl_root_lookup, | .vop_lookup = zfsctl_root_lookup, | ||||
.vop_inactive = VOP_NULL, | .vop_inactive = VOP_NULL, | ||||
.vop_reclaim = zfsctl_common_reclaim, | .vop_reclaim = zfsctl_common_reclaim, | ||||
.vop_fid = zfsctl_common_fid, | .vop_fid = zfsctl_common_fid, | ||||
.vop_print = zfsctl_common_print, | .vop_print = zfsctl_common_print, | ||||
.vop_vptocnp = zfsctl_root_vptocnp, | .vop_vptocnp = zfsctl_root_vptocnp, | ||||
.vop_pathconf = zfsctl_common_pathconf, | |||||
.vop_getacl = zfsctl_common_getacl, | |||||
}; | }; | ||||
static int | static int | ||||
zfsctl_snapshot_zname(vnode_t *vp, const char *name, int len, char *zname) | zfsctl_snapshot_zname(vnode_t *vp, const char *name, int len, char *zname) | ||||
{ | { | ||||
objset_t *os = ((zfsvfs_t *)((vp)->v_vfsp->vfs_data))->z_os; | objset_t *os = ((zfsvfs_t *)((vp)->v_vfsp->vfs_data))->z_os; | ||||
dmu_objset_name(os, zname); | dmu_objset_name(os, zname); | ||||
▲ Show 20 Lines • Show All 312 Lines • ▼ Show 20 Lines | static struct vop_vector zfsctl_ops_snapdir = { | ||||
.vop_close = zfsctl_common_close, | .vop_close = zfsctl_common_close, | ||||
.vop_getattr = zfsctl_snapdir_getattr, | .vop_getattr = zfsctl_snapdir_getattr, | ||||
.vop_access = zfsctl_common_access, | .vop_access = zfsctl_common_access, | ||||
.vop_readdir = zfsctl_snapdir_readdir, | .vop_readdir = zfsctl_snapdir_readdir, | ||||
.vop_lookup = zfsctl_snapdir_lookup, | .vop_lookup = zfsctl_snapdir_lookup, | ||||
.vop_reclaim = zfsctl_common_reclaim, | .vop_reclaim = zfsctl_common_reclaim, | ||||
.vop_fid = zfsctl_common_fid, | .vop_fid = zfsctl_common_fid, | ||||
.vop_print = zfsctl_common_print, | .vop_print = zfsctl_common_print, | ||||
.vop_pathconf = zfsctl_common_pathconf, | |||||
.vop_getacl = zfsctl_common_getacl, | |||||
}; | }; | ||||
static int | static int | ||||
zfsctl_snapshot_inactive(ap) | zfsctl_snapshot_inactive(ap) | ||||
struct vop_inactive_args /* { | struct vop_inactive_args /* { | ||||
struct vnode *a_vp; | struct vnode *a_vp; | ||||
struct thread *a_td; | struct thread *a_td; | ||||
} */ *ap; | } */ *ap; | ||||
▲ Show 20 Lines • Show All 190 Lines • Show Last 20 Lines |