Changeset View
Changeset View
Standalone View
Standalone View
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
Show All 32 Lines | |||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/time.h> | #include <sys/time.h> | ||||
#include <sys/systm.h> | #include <sys/systm.h> | ||||
#include <sys/sysmacros.h> | #include <sys/sysmacros.h> | ||||
#include <sys/resource.h> | #include <sys/resource.h> | ||||
#include <sys/vfs.h> | #include <sys/vfs.h> | ||||
#include <sys/vm.h> | #include <sys/vm.h> | ||||
#include <sys/vnode.h> | #include <sys/vnode.h> | ||||
#include <sys/smr.h> | |||||
#include <sys/file.h> | #include <sys/file.h> | ||||
#include <sys/stat.h> | #include <sys/stat.h> | ||||
#include <sys/kmem.h> | #include <sys/kmem.h> | ||||
#include <sys/taskq.h> | #include <sys/taskq.h> | ||||
#include <sys/uio.h> | #include <sys/uio.h> | ||||
#include <sys/atomic.h> | #include <sys/atomic.h> | ||||
#include <sys/namei.h> | #include <sys/namei.h> | ||||
#include <sys/mman.h> | #include <sys/mman.h> | ||||
Show All 24 Lines | |||||
#include <sys/bio.h> | #include <sys/bio.h> | ||||
#include <sys/buf.h> | #include <sys/buf.h> | ||||
#include <sys/sched.h> | #include <sys/sched.h> | ||||
#include <sys/acl.h> | #include <sys/acl.h> | ||||
#include <sys/vmmeter.h> | #include <sys/vmmeter.h> | ||||
#include <vm/vm_param.h> | #include <vm/vm_param.h> | ||||
#include <sys/zil.h> | #include <sys/zil.h> | ||||
VFS_SMR_DECLARE; | |||||
/* | /* | ||||
* Programming rules. | * Programming rules. | ||||
* | * | ||||
* Each vnode op performs some logical unit of work. To do this, the ZPL must | * Each vnode op performs some logical unit of work. To do this, the ZPL must | ||||
* properly lock its in-core state, create a DMU transaction, do the work, | * properly lock its in-core state, create a DMU transaction, do the work, | ||||
* record this work in the intent log (ZIL), commit the DMU transaction, | * record this work in the intent log (ZIL), commit the DMU transaction, | ||||
* and wait for the intent log to commit if it is a synchronous operation. | * and wait for the intent log to commit if it is a synchronous operation. | ||||
* Moreover, the vnode ops must work in both normal and log replay context. | * Moreover, the vnode ops must work in both normal and log replay context. | ||||
▲ Show 20 Lines • Show All 3,604 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
zfsvfs_t *zfsvfs; | zfsvfs_t *zfsvfs; | ||||
znode_t *sdzp, *tdzp, *szp, *tzp; | znode_t *sdzp, *tdzp, *szp, *tzp; | ||||
zilog_t *zilog = NULL; | zilog_t *zilog = NULL; | ||||
dmu_tx_t *tx; | dmu_tx_t *tx; | ||||
char *snm = scnp->cn_nameptr; | char *snm = scnp->cn_nameptr; | ||||
char *tnm = tcnp->cn_nameptr; | char *tnm = tcnp->cn_nameptr; | ||||
int error = 0; | int error = 0; | ||||
bool want_seqc_end = false; | |||||
/* Reject renames across filesystems. */ | /* Reject renames across filesystems. */ | ||||
if ((*svpp)->v_mount != tdvp->v_mount || | if ((*svpp)->v_mount != tdvp->v_mount || | ||||
((*tvpp) != NULL && (*svpp)->v_mount != (*tvpp)->v_mount)) { | ((*tvpp) != NULL && (*svpp)->v_mount != (*tvpp)->v_mount)) { | ||||
error = SET_ERROR(EXDEV); | error = SET_ERROR(EXDEV); | ||||
goto out; | goto out; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 114 Lines • ▼ Show 20 Lines | if (tzp) { | ||||
} else { | } else { | ||||
if ((*tvpp)->v_type == VDIR) { | if ((*tvpp)->v_type == VDIR) { | ||||
error = SET_ERROR(EISDIR); | error = SET_ERROR(EISDIR); | ||||
goto unlockout; | goto unlockout; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
vn_seqc_write_begin(*svpp); | |||||
vn_seqc_write_begin(sdvp); | |||||
if (*tvpp != NULL) | |||||
vn_seqc_write_begin(*tvpp); | |||||
if (tdvp != *tvpp) | |||||
vn_seqc_write_begin(tdvp); | |||||
want_seqc_end = true; | |||||
vnevent_rename_src(*svpp, sdvp, scnp->cn_nameptr, ct); | vnevent_rename_src(*svpp, sdvp, scnp->cn_nameptr, ct); | ||||
if (tzp) | if (tzp) | ||||
vnevent_rename_dest(*tvpp, tdvp, tnm, ct); | vnevent_rename_dest(*tvpp, tdvp, tnm, ct); | ||||
/* | /* | ||||
* notify the target directory if it is not the same | * notify the target directory if it is not the same | ||||
* as source directory. | * as source directory. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 70 Lines • ▼ Show 20 Lines | if (error == 0) { | ||||
cache_purge_negative(tdvp); | cache_purge_negative(tdvp); | ||||
} | } | ||||
} | } | ||||
dmu_tx_commit(tx); | dmu_tx_commit(tx); | ||||
unlockout: /* all 4 vnodes are locked, ZFS_ENTER called */ | unlockout: /* all 4 vnodes are locked, ZFS_ENTER called */ | ||||
ZFS_EXIT(zfsvfs); | ZFS_EXIT(zfsvfs); | ||||
if (want_seqc_end) { | |||||
vn_seqc_write_end(*svpp); | |||||
vn_seqc_write_end(sdvp); | |||||
if (*tvpp != NULL) | |||||
vn_seqc_write_end(*tvpp); | |||||
if (tdvp != *tvpp) | |||||
vn_seqc_write_end(tdvp); | |||||
want_seqc_end = false; | |||||
} | |||||
VOP_UNLOCK(*svpp); | VOP_UNLOCK(*svpp); | ||||
VOP_UNLOCK(sdvp); | VOP_UNLOCK(sdvp); | ||||
out: /* original two vnodes are locked */ | out: /* original two vnodes are locked */ | ||||
MPASS(!want_seqc_end); | |||||
if (error == 0 && zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS) | if (error == 0 && zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS) | ||||
zil_commit(zilog, 0); | zil_commit(zilog, 0); | ||||
if (*tvpp != NULL) | if (*tvpp != NULL) | ||||
VOP_UNLOCK(*tvpp); | VOP_UNLOCK(*tvpp); | ||||
if (tdvp != *tvpp) | if (tdvp != *tvpp) | ||||
VOP_UNLOCK(tdvp); | VOP_UNLOCK(tdvp); | ||||
return (error); | return (error); | ||||
▲ Show 20 Lines • Show All 927 Lines • ▼ Show 20 Lines | struct vop_write_args /* { | ||||
struct ucred *a_cred; | struct ucred *a_cred; | ||||
} */ *ap; | } */ *ap; | ||||
{ | { | ||||
return (zfs_write(ap->a_vp, ap->a_uio, ioflags(ap->a_ioflag), | return (zfs_write(ap->a_vp, ap->a_uio, ioflags(ap->a_ioflag), | ||||
ap->a_cred, NULL)); | ap->a_cred, NULL)); | ||||
} | } | ||||
/* | |||||
* VOP_FPLOOKUP_VEXEC routines are subject to special circumstances, see | |||||
* the comment above cache_fplookup for details. | |||||
*/ | |||||
static int | static int | ||||
zfs_freebsd_fplookup_vexec(struct vop_fplookup_vexec_args *v) | |||||
{ | |||||
vnode_t *vp; | |||||
znode_t *zp; | |||||
uint64_t pflags; | |||||
vp = v->a_vp; | |||||
zp = VTOZ_SMR(vp); | |||||
if (__predict_false(zp == NULL)) | |||||
return (EAGAIN); | |||||
pflags = atomic_load_64(&zp->z_pflags); | |||||
if (pflags & ZFS_AV_QUARANTINED) | |||||
return (EAGAIN); | |||||
if (pflags & ZFS_XATTR) | |||||
return (EAGAIN); | |||||
if ((pflags & ZFS_NO_EXECS_DENIED) == 0) | |||||
return (EAGAIN); | |||||
return (0); | |||||
} | |||||
static int | |||||
zfs_freebsd_access(ap) | zfs_freebsd_access(ap) | ||||
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; | ||||
} */ *ap; | } */ *ap; | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 1,120 Lines • ▼ Show 20 Lines | |||||
struct vop_vector zfs_fifoops; | struct vop_vector zfs_fifoops; | ||||
struct vop_vector zfs_shareops; | struct vop_vector zfs_shareops; | ||||
struct vop_vector zfs_vnodeops = { | struct vop_vector zfs_vnodeops = { | ||||
.vop_default = &default_vnodeops, | .vop_default = &default_vnodeops, | ||||
.vop_inactive = zfs_freebsd_inactive, | .vop_inactive = zfs_freebsd_inactive, | ||||
.vop_need_inactive = zfs_freebsd_need_inactive, | .vop_need_inactive = zfs_freebsd_need_inactive, | ||||
.vop_reclaim = zfs_freebsd_reclaim, | .vop_reclaim = zfs_freebsd_reclaim, | ||||
.vop_fplookup_vexec = zfs_freebsd_fplookup_vexec, | |||||
.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 = zfs_freebsd_create, | .vop_mknod = zfs_freebsd_create, | ||||
▲ Show 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | |||||
}; | }; | ||||
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, | ||||
.vop_fplookup_vexec = zfs_freebsd_fplookup_vexec, | |||||
.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); |