Changeset View
Changeset View
Standalone View
Standalone View
sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c
Show First 20 Lines • Show All 3,795 Lines • ▼ Show 20 Lines | zfs_link(znode_t *tdzp, znode_t *szp, const char *name, cred_t *cr, | ||||
if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS) | if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS) | ||||
zil_commit(zilog, 0); | zil_commit(zilog, 0); | ||||
ZFS_EXIT(zfsvfs); | ZFS_EXIT(zfsvfs); | ||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
* common code for zfs_space-related operations | |||||
* | |||||
* This function is called from zfs_space and zfs_deallocate. | |||||
*/ | |||||
static int | |||||
zfs_space_common(znode_t *zp, int cmd, off_t off, off_t len, int flag, | |||||
cred_t *cr) | |||||
{ | |||||
zfsvfs_t *zfsvfs = ZTOZSB(zp); | |||||
uint64_t uoff, ulen; | |||||
int error; | |||||
if (cmd != F_FREESP) | |||||
return (EINVAL); | |||||
/* | |||||
* Callers might not be able to detect properly that we are read-only, | |||||
* so check it explicitly here. | |||||
*/ | |||||
if (zfs_is_readonly(zfsvfs)) | |||||
return (EROFS); | |||||
if (len < 0) | |||||
return (EINVAL); | |||||
/* | |||||
* Permissions aren't checked on Solaris because on this OS | |||||
* zfs_space() can only be called with an opened file handle. | |||||
* On Linux we can get here through truncate_range() which | |||||
allanjude: Does this comment need updating to instead say what FreeBSD does in this case? | |||||
Not Done Inline ActionsThat seems necessary. I don't recall we have the same limitation like Solaris that VOP can only issued on opened files. khng: That seems necessary. I don't recall we have the same limitation like Solaris that VOP can only… | |||||
* operates directly on inodes, so we need to check access rights. | |||||
*/ | |||||
if ((error = zfs_zaccess(zp, ACE_WRITE_DATA, 0, B_FALSE, cr))) | |||||
return (error); | |||||
uoff = off; | |||||
ulen = len; | |||||
error = zfs_freesp(zp, uoff, ulen, flag, TRUE); | |||||
return (error); | |||||
} | |||||
/* | |||||
* Free or allocate space in a file. Currently, this function only | * Free or allocate space in a file. Currently, this function only | ||||
* supports the `F_FREESP' command. However, this command is somewhat | * supports the `F_FREESP' command. However, this command is somewhat | ||||
* misnamed, as its functionality includes the ability to allocate as | * misnamed, as its functionality includes the ability to allocate as | ||||
* well as free space. | * well as free space. | ||||
* | * | ||||
* IN: ip - inode of file to free data in. | * IN: ip - inode of file to free data in. | ||||
* cmd - action to take (only F_FREESP supported). | * cmd - action to take (only F_FREESP supported). | ||||
* bfp - section of file to free/alloc. | * bfp - section of file to free/alloc. | ||||
* flag - current file open mode flags. | * flag - current file open mode flags. | ||||
* offset - current file offset. | * offset - current file offset. | ||||
* cr - credentials of caller. | * cr - credentials of caller. | ||||
* | * | ||||
* RETURN: 0 on success, error code on failure. | * RETURN: 0 on success, error code on failure. | ||||
* | * | ||||
* Timestamps: | * Timestamps: | ||||
* ip - ctime|mtime updated | * ip - ctime|mtime updated | ||||
*/ | */ | ||||
/* ARGSUSED */ | /* ARGSUSED */ | ||||
int | int | ||||
zfs_space(znode_t *zp, int cmd, flock64_t *bfp, int flag, | zfs_space(znode_t *zp, int cmd, flock64_t *bfp, int flag, | ||||
offset_t offset, cred_t *cr) | offset_t offset, cred_t *cr) | ||||
{ | { | ||||
zfsvfs_t *zfsvfs = ZTOZSB(zp); | zfsvfs_t *zfsvfs = ZTOZSB(zp); | ||||
uint64_t off, len; | off_t off, len; | ||||
int error; | int error; | ||||
ZFS_ENTER(zfsvfs); | ZFS_ENTER(zfsvfs); | ||||
ZFS_VERIFY_ZP(zp); | ZFS_VERIFY_ZP(zp); | ||||
if (cmd != F_FREESP) { | |||||
ZFS_EXIT(zfsvfs); | |||||
return (SET_ERROR(EINVAL)); | |||||
} | |||||
/* | |||||
* Callers might not be able to detect properly that we are read-only, | |||||
* so check it explicitly here. | |||||
*/ | |||||
if (zfs_is_readonly(zfsvfs)) { | |||||
ZFS_EXIT(zfsvfs); | |||||
return (SET_ERROR(EROFS)); | |||||
} | |||||
if (bfp->l_len < 0) { | |||||
ZFS_EXIT(zfsvfs); | |||||
return (SET_ERROR(EINVAL)); | |||||
} | |||||
/* | |||||
* Permissions aren't checked on Solaris because on this OS | |||||
* zfs_space() can only be called with an opened file handle. | |||||
* On Linux we can get here through truncate_range() which | |||||
* operates directly on inodes, so we need to check access rights. | |||||
*/ | |||||
if ((error = zfs_zaccess(zp, ACE_WRITE_DATA, 0, B_FALSE, cr))) { | |||||
ZFS_EXIT(zfsvfs); | |||||
return (error); | |||||
} | |||||
off = bfp->l_start; | off = bfp->l_start; | ||||
len = bfp->l_len; /* 0 means from off to end of file */ | len = bfp->l_len; /* 0 means from off to end of file */ | ||||
error = zfs_freesp(zp, off, len, flag, TRUE); | error = zfs_space_common(zp, cmd, off, len, flag, cr); | ||||
ZFS_EXIT(zfsvfs); | ZFS_EXIT(zfsvfs); | ||||
return (error); | return (error); | ||||
} | } | ||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
static void | static void | ||||
zfs_inactive(vnode_t *vp, cred_t *cr, caller_context_t *ct) | zfs_inactive(vnode_t *vp, cred_t *cr, caller_context_t *ct) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 1,315 Lines • ▼ Show 20 Lines | zfs_freebsd_pathconf(struct vop_pathconf_args *ap) | ||||
} | } | ||||
if (error != EOPNOTSUPP) | if (error != EOPNOTSUPP) | ||||
return (error); | return (error); | ||||
switch (ap->a_name) { | switch (ap->a_name) { | ||||
case _PC_NAME_MAX: | case _PC_NAME_MAX: | ||||
*ap->a_retval = NAME_MAX; | *ap->a_retval = NAME_MAX; | ||||
return (0); | return (0); | ||||
case _PC_FDEALLOC_PRESENT: | |||||
*ap->a_retval = 1; | |||||
return (0); | |||||
case _PC_PIPE_BUF: | case _PC_PIPE_BUF: | ||||
if (ap->a_vp->v_type == VDIR || ap->a_vp->v_type == VFIFO) { | if (ap->a_vp->v_type == VDIR || ap->a_vp->v_type == VFIFO) { | ||||
*ap->a_retval = PIPE_BUF; | *ap->a_retval = PIPE_BUF; | ||||
return (0); | return (0); | ||||
} | } | ||||
return (EINVAL); | return (EINVAL); | ||||
default: | default: | ||||
return (vop_stdpathconf(ap)); | return (vop_stdpathconf(ap)); | ||||
▲ Show 20 Lines • Show All 580 Lines • ▼ Show 20 Lines | #endif | ||||
vput(covered_vp); | vput(covered_vp); | ||||
} | } | ||||
vn_lock(vp, ltype | LK_RETRY); | vn_lock(vp, ltype | LK_RETRY); | ||||
if (VN_IS_DOOMED(vp)) | if (VN_IS_DOOMED(vp)) | ||||
error = SET_ERROR(ENOENT); | error = SET_ERROR(ENOENT); | ||||
return (error); | return (error); | ||||
} | } | ||||
/* | |||||
* This is mostly the same as zfs_space except it also limits the range of | |||||
* operation to zp->z_size. The log | |||||
* record of zfs_space during replay would be the same as ordinary zfs_space. | |||||
*/ | |||||
static int | |||||
zfs_deallocate(struct vop_deallocate_args *ap) | |||||
{ | |||||
vnode_t *vp; | |||||
znode_t *zp; | |||||
zfsvfs_t *zfsvfs; | |||||
off_t offset, len; | |||||
int error; | |||||
vp = ap->a_vp; | |||||
zp = VTOZ(vp); | |||||
zfsvfs = ZTOZSB(zp); | |||||
ZFS_ENTER(zfsvfs); | |||||
ZFS_VERIFY_ZP(zp); | |||||
offset = *ap->a_offset; | |||||
len = *ap->a_len; | |||||
len = omin(len, zp->z_size - offset); | |||||
if (len == 0) { | |||||
error = 0; | |||||
goto out; | |||||
} | |||||
error = zfs_space_common(zp, F_FREESP, offset, len, O_RDWR, ap->a_cred); | |||||
out: | |||||
if (__predict_true(error == 0)) | |||||
*ap->a_len = 0; | |||||
ZFS_EXIT(zfsvfs); | |||||
return (error); | |||||
} | |||||
struct vop_vector zfs_vnodeops; | struct vop_vector zfs_vnodeops; | ||||
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, | ||||
#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, | .vop_fplookup_symlink = zfs_freebsd_fplookup_symlink, | ||||
.vop_access = zfs_freebsd_access, | .vop_access = zfs_freebsd_access, | ||||
.vop_allocate = VOP_EINVAL, | .vop_allocate = VOP_EINVAL, | ||||
.vop_deallocate = zfs_deallocate, | |||||
.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, | ||||
.vop_mkdir = zfs_freebsd_mkdir, | .vop_mkdir = zfs_freebsd_mkdir, | ||||
.vop_readdir = zfs_freebsd_readdir, | .vop_readdir = zfs_freebsd_readdir, | ||||
▲ Show 20 Lines • Show All 71 Lines • Show Last 20 Lines |
Does this comment need updating to instead say what FreeBSD does in this case?