Changeset View
Changeset View
Standalone View
Standalone View
sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops.c
Show First 20 Lines • Show All 5,267 Lines • ▼ Show 20 Lines | zfs_freebsd_fplookup_vexec(struct vop_fplookup_vexec_args *v) | ||||
if (pflags & ZFS_XATTR) | if (pflags & ZFS_XATTR) | ||||
return (EAGAIN); | return (EAGAIN); | ||||
if ((pflags & ZFS_NO_EXECS_DENIED) == 0) | if ((pflags & ZFS_NO_EXECS_DENIED) == 0) | ||||
return (EAGAIN); | return (EAGAIN); | ||||
return (0); | return (0); | ||||
} | } | ||||
#endif | #endif | ||||
static int | |||||
zfs_freebsd_fplookup_symlink(struct vop_fplookup_symlink_args *v) | |||||
{ | |||||
vnode_t *vp; | |||||
znode_t *zp; | |||||
char *target; | |||||
vp = v->a_vp; | |||||
zp = VTOZ_SMR(vp); | |||||
if (__predict_false(zp == NULL)) { | |||||
return (EAGAIN); | |||||
} | |||||
target = atomic_load_ptr(&zp->z_cached_symlink); | |||||
if (target == NULL) { | |||||
return (EAGAIN); | |||||
} | |||||
return (cache_symlink_resolve(v->a_fpl, target, strlen(target))); | |||||
} | |||||
#ifndef _SYS_SYSPROTO_H_ | #ifndef _SYS_SYSPROTO_H_ | ||||
struct vop_access_args { | struct vop_access_args { | ||||
struct vnode *a_vp; | struct vnode *a_vp; | ||||
accmode_t a_accmode; | accmode_t a_accmode; | ||||
struct ucred *a_cred; | struct ucred *a_cred; | ||||
struct thread *a_td; | struct thread *a_td; | ||||
}; | }; | ||||
#endif | #endif | ||||
▲ Show 20 Lines • Show All 470 Lines • ▼ Show 20 Lines | |||||
#endif | #endif | ||||
static int | static int | ||||
zfs_freebsd_symlink(struct vop_symlink_args *ap) | zfs_freebsd_symlink(struct vop_symlink_args *ap) | ||||
{ | { | ||||
struct componentname *cnp = ap->a_cnp; | struct componentname *cnp = ap->a_cnp; | ||||
vattr_t *vap = ap->a_vap; | vattr_t *vap = ap->a_vap; | ||||
znode_t *zp = NULL; | znode_t *zp = NULL; | ||||
char *symlink; | |||||
size_t symlink_len; | |||||
int rc; | int rc; | ||||
ASSERT(cnp->cn_flags & SAVENAME); | ASSERT(cnp->cn_flags & SAVENAME); | ||||
vap->va_type = VLNK; /* FreeBSD: Syscall only sets va_mode. */ | vap->va_type = VLNK; /* FreeBSD: Syscall only sets va_mode. */ | ||||
vattr_init_mask(vap); | vattr_init_mask(vap); | ||||
*ap->a_vpp = NULL; | *ap->a_vpp = NULL; | ||||
rc = zfs_symlink(VTOZ(ap->a_dvp), cnp->cn_nameptr, vap, | rc = zfs_symlink(VTOZ(ap->a_dvp), cnp->cn_nameptr, vap, | ||||
ap->a_target, &zp, cnp->cn_cred, 0 /* flags */); | ap->a_target, &zp, cnp->cn_cred, 0 /* flags */); | ||||
if (rc == 0) | if (rc == 0) { | ||||
*ap->a_vpp = ZTOV(zp); | *ap->a_vpp = ZTOV(zp); | ||||
ASSERT_VOP_ELOCKED(ZTOV(zp), __func__); | |||||
MPASS(zp->z_cached_symlink == NULL); | |||||
symlink_len = strlen(ap->a_target); | |||||
symlink = cache_symlink_alloc(symlink_len, M_WAITOK); | |||||
if (symlink != NULL) { | |||||
memcpy(symlink, ap->a_target, symlink_len); | |||||
atomic_store_rel_ptr((uintptr_t *)&zp->z_cached_symlink, | |||||
(uintptr_t)symlink); | |||||
} | |||||
} | |||||
return (rc); | return (rc); | ||||
} | } | ||||
#ifndef _SYS_SYSPROTO_H_ | #ifndef _SYS_SYSPROTO_H_ | ||||
struct vop_readlink_args { | struct vop_readlink_args { | ||||
struct vnode *a_vp; | struct vnode *a_vp; | ||||
struct uio *a_uio; | struct uio *a_uio; | ||||
struct ucred *a_cred; | struct ucred *a_cred; | ||||
}; | }; | ||||
#endif | #endif | ||||
static int | static int | ||||
zfs_freebsd_readlink(struct vop_readlink_args *ap) | zfs_freebsd_readlink(struct vop_readlink_args *ap) | ||||
{ | { | ||||
znode_t *zp = VTOZ(ap->a_vp); | |||||
struct uio *auio; | |||||
char *symlink, *base; | |||||
size_t symlink_len; | |||||
int error; | |||||
bool trycache; | |||||
return (zfs_readlink(ap->a_vp, ap->a_uio, ap->a_cred, NULL)); | auio = ap->a_uio; | ||||
trycache = false; | |||||
if (auio->uio_segflg == UIO_SYSSPACE && auio->uio_iovcnt == 1) { | |||||
base = auio->uio_iov->iov_base; | |||||
symlink_len = auio->uio_iov->iov_len; | |||||
trycache = true; | |||||
} | } | ||||
error = zfs_readlink(ap->a_vp, auio, ap->a_cred, NULL); | |||||
if (atomic_load_ptr(&zp->z_cached_symlink) != NULL || | |||||
error != 0 || !trycache) { | |||||
return (error); | |||||
} | |||||
symlink_len -= auio->uio_resid; | |||||
symlink = cache_symlink_alloc(symlink_len, M_WAITOK); | |||||
if (symlink != NULL) { | |||||
memcpy(symlink, base, symlink_len); | |||||
if (!atomic_cmpset_rel_ptr((uintptr_t *)&zp->z_cached_symlink, | |||||
(uintptr_t)NULL, (uintptr_t)symlink)) { | |||||
cache_symlink_free(symlink); | |||||
} | |||||
} | |||||
return (error); | |||||
} | |||||
#ifndef _SYS_SYSPROTO_H_ | #ifndef _SYS_SYSPROTO_H_ | ||||
struct vop_link_args { | struct vop_link_args { | ||||
struct vnode *a_tdvp; | struct vnode *a_tdvp; | ||||
struct vnode *a_vp; | struct vnode *a_vp; | ||||
struct componentname *a_cnp; | struct componentname *a_cnp; | ||||
}; | }; | ||||
#endif | #endif | ||||
▲ Show 20 Lines • Show All 729 Lines • ▼ Show 20 Lines | struct vop_vector zfs_vnodeops = { | ||||
.vop_inactive = zfs_freebsd_inactive, | .vop_inactive = zfs_freebsd_inactive, | ||||
#if __FreeBSD_version >= 1300042 | #if __FreeBSD_version >= 1300042 | ||||
.vop_need_inactive = zfs_freebsd_need_inactive, | .vop_need_inactive = zfs_freebsd_need_inactive, | ||||
#endif | #endif | ||||
.vop_reclaim = zfs_freebsd_reclaim, | .vop_reclaim = zfs_freebsd_reclaim, | ||||
#if __FreeBSD_version >= 1300102 | #if __FreeBSD_version >= 1300102 | ||||
.vop_fplookup_vexec = zfs_freebsd_fplookup_vexec, | .vop_fplookup_vexec = zfs_freebsd_fplookup_vexec, | ||||
#endif | #endif | ||||
.vop_fplookup_symlink = zfs_freebsd_fplookup_symlink, | |||||
kib: This line requires `#if __FreeBSD_version` check, again. | |||||
Done Inline ActionsI'm going to add them when upstreaming. mjg: I'm going to add them when upstreaming. | |||||
.vop_access = zfs_freebsd_access, | .vop_access = zfs_freebsd_access, | ||||
.vop_allocate = VOP_EINVAL, | .vop_allocate = VOP_EINVAL, | ||||
.vop_lookup = zfs_cache_lookup, | .vop_lookup = zfs_cache_lookup, | ||||
.vop_cachedlookup = zfs_freebsd_cachedlookup, | .vop_cachedlookup = zfs_freebsd_cachedlookup, | ||||
.vop_getattr = zfs_freebsd_getattr, | .vop_getattr = zfs_freebsd_getattr, | ||||
.vop_setattr = zfs_freebsd_setattr, | .vop_setattr = zfs_freebsd_setattr, | ||||
.vop_create = zfs_freebsd_create, | .vop_create = zfs_freebsd_create, | ||||
.vop_mknod = (vop_mknod_t *)zfs_freebsd_create, | .vop_mknod = (vop_mknod_t *)zfs_freebsd_create, | ||||
Show All 33 Lines | |||||
VFS_VOP_VECTOR_REGISTER(zfs_vnodeops); | VFS_VOP_VECTOR_REGISTER(zfs_vnodeops); | ||||
struct vop_vector zfs_fifoops = { | struct vop_vector zfs_fifoops = { | ||||
.vop_default = &fifo_specops, | .vop_default = &fifo_specops, | ||||
.vop_fsync = zfs_freebsd_fsync, | .vop_fsync = zfs_freebsd_fsync, | ||||
#if __FreeBSD_version >= 1300102 | #if __FreeBSD_version >= 1300102 | ||||
.vop_fplookup_vexec = zfs_freebsd_fplookup_vexec, | .vop_fplookup_vexec = zfs_freebsd_fplookup_vexec, | ||||
#endif | #endif | ||||
.vop_fplookup_symlink = zfs_freebsd_fplookup_symlink, | |||||
.vop_access = zfs_freebsd_access, | .vop_access = zfs_freebsd_access, | ||||
.vop_getattr = zfs_freebsd_getattr, | .vop_getattr = zfs_freebsd_getattr, | ||||
.vop_inactive = zfs_freebsd_inactive, | .vop_inactive = zfs_freebsd_inactive, | ||||
.vop_read = VOP_PANIC, | .vop_read = VOP_PANIC, | ||||
.vop_reclaim = zfs_freebsd_reclaim, | .vop_reclaim = zfs_freebsd_reclaim, | ||||
.vop_setattr = zfs_freebsd_setattr, | .vop_setattr = zfs_freebsd_setattr, | ||||
.vop_write = VOP_PANIC, | .vop_write = VOP_PANIC, | ||||
.vop_pathconf = zfs_freebsd_pathconf, | .vop_pathconf = zfs_freebsd_pathconf, | ||||
.vop_fid = zfs_freebsd_fid, | .vop_fid = zfs_freebsd_fid, | ||||
.vop_getacl = zfs_freebsd_getacl, | .vop_getacl = zfs_freebsd_getacl, | ||||
.vop_setacl = zfs_freebsd_setacl, | .vop_setacl = zfs_freebsd_setacl, | ||||
.vop_aclcheck = zfs_freebsd_aclcheck, | .vop_aclcheck = zfs_freebsd_aclcheck, | ||||
}; | }; | ||||
VFS_VOP_VECTOR_REGISTER(zfs_fifoops); | VFS_VOP_VECTOR_REGISTER(zfs_fifoops); | ||||
/* | /* | ||||
* special share hidden files vnode operations template | * special share hidden files vnode operations template | ||||
*/ | */ | ||||
struct vop_vector zfs_shareops = { | struct vop_vector zfs_shareops = { | ||||
.vop_default = &default_vnodeops, | .vop_default = &default_vnodeops, | ||||
#if __FreeBSD_version >= 1300121 | #if __FreeBSD_version >= 1300121 | ||||
.vop_fplookup_vexec = VOP_EAGAIN, | .vop_fplookup_vexec = VOP_EAGAIN, | ||||
#endif | #endif | ||||
.vop_fplookup_symlink = VOP_EAGAIN, | |||||
.vop_access = zfs_freebsd_access, | .vop_access = zfs_freebsd_access, | ||||
.vop_inactive = zfs_freebsd_inactive, | .vop_inactive = zfs_freebsd_inactive, | ||||
.vop_reclaim = zfs_freebsd_reclaim, | .vop_reclaim = zfs_freebsd_reclaim, | ||||
.vop_fid = zfs_freebsd_fid, | .vop_fid = zfs_freebsd_fid, | ||||
.vop_pathconf = zfs_freebsd_pathconf, | .vop_pathconf = zfs_freebsd_pathconf, | ||||
}; | }; | ||||
VFS_VOP_VECTOR_REGISTER(zfs_shareops); | VFS_VOP_VECTOR_REGISTER(zfs_shareops); |
This line requires #if __FreeBSD_version check, again.