/*
- * Copyright (c) 2000-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2017 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- *
+ *
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* unlawful or unlicensed copies of an Apple operating system, or to
* circumvent, violate, or enable the circumvention or violation of, any
* terms of an Apple operating system software license agreement.
- *
+ *
* Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this file.
- *
+ *
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
- *
+ *
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
/* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
#include <sys/mount.h>
#include <sys/mount_internal.h>
#include <sys/time.h>
+#include <sys/disk.h>
#include <sys/vnode_internal.h>
#include <sys/stat.h>
#include <sys/namei.h>
#include <sys/ucred.h>
#include <sys/buf.h>
#include <sys/errno.h>
-#include <sys/malloc.h>
+#include <kern/kalloc.h>
#include <sys/domain.h>
#include <sys/mbuf.h>
#include <sys/syslog.h>
#include <sys/user.h>
#include <sys/lockf.h>
#include <sys/xattr.h>
+#include <sys/kdebug.h>
#include <kern/assert.h>
-#include <kern/kalloc.h>
+#include <kern/zalloc.h>
#include <kern/task.h>
+#include <kern/policy_internal.h>
#include <libkern/OSByteOrder.h>
#include <security/mac_framework.h>
#endif
+#if NULLFS
+#include <miscfs/nullfs/nullfs.h>
+#endif
+
+#include <sys/sdt.h>
+
#define ESUCCESS 0
#undef mount_t
#undef vnode_t
#define COMPAT_ONLY
-
-#if CONFIG_VFS_FUNNEL
-#define THREAD_SAFE_FS(VP) \
- ((VP)->v_unsafefs ? 0 : 1)
-#endif /* CONFIG_VFS_FUNNEL */
-
#define NATIVE_XATTR(VP) \
((VP)->v_mount ? (VP)->v_mount->mnt_kern_flag & MNTK_EXTENDED_ATTRS : 0)
+#if CONFIG_APPLEDOUBLE
static void xattrfile_remove(vnode_t dvp, const char *basename,
- vfs_context_t ctx, int force);
+ vfs_context_t ctx, int force);
static void xattrfile_setattr(vnode_t dvp, const char * basename,
- struct vnode_attr * vap, vfs_context_t ctx);
+ struct vnode_attr * vap, vfs_context_t ctx);
+#endif /* CONFIG_APPLEDOUBLE */
+
+extern lck_rw_t * rootvnode_rw_lock;
+
+static errno_t post_rename(vnode_t fdvp, vnode_t fvp, vnode_t tdvp, vnode_t tvp);
+
+static ZONE_VIEW_DEFINE(ZV_VFS_CONTEXT, "vfs_context",
+ KHEAP_ID_DEFAULT, sizeof(struct vfs_context));
/*
* vnode_setneedinactive
*
* Description: Indicate that when the last iocount on this vnode goes away,
- * and the usecount is also zero, we should inform the filesystem
- * via VNOP_INACTIVE.
+ * and the usecount is also zero, we should inform the filesystem
+ * via VNOP_INACTIVE.
*
* Parameters: vnode_t vnode to mark
*
* Returns: Nothing
*
- * Notes: Notably used when we're deleting a file--we need not have a
- * usecount, so VNOP_INACTIVE may not get called by anyone. We
- * want it called when we drop our iocount.
+ * Notes: Notably used when we're deleting a file--we need not have a
+ * usecount, so VNOP_INACTIVE may not get called by anyone. We
+ * want it called when we drop our iocount.
*/
void
vnode_setneedinactive(vnode_t vp)
{
- cache_purge(vp);
+ cache_purge(vp);
- vnode_lock_spin(vp);
+ vnode_lock_spin(vp);
vp->v_lflag |= VL_NEEDINACTIVE;
vnode_unlock(vp);
}
-#if CONFIG_VFS_FUNNEL
-int
-lock_fsnode(vnode_t vp, int *funnel_state)
-{
- if (funnel_state)
- *funnel_state = thread_funnel_set(kernel_flock, TRUE);
-
- if (vp->v_unsafefs) {
- if (vp->v_unsafefs->fsnodeowner == current_thread()) {
- vp->v_unsafefs->fsnode_count++;
- } else {
- lck_mtx_lock(&vp->v_unsafefs->fsnodelock);
-
- if (vp->v_lflag & (VL_TERMWANT | VL_TERMINATE | VL_DEAD)) {
- lck_mtx_unlock(&vp->v_unsafefs->fsnodelock);
-
- if (funnel_state)
- (void) thread_funnel_set(kernel_flock, *funnel_state);
- return (ENOENT);
- }
- vp->v_unsafefs->fsnodeowner = current_thread();
- vp->v_unsafefs->fsnode_count = 1;
- }
- }
- return (0);
-}
-
-
-void
-unlock_fsnode(vnode_t vp, int *funnel_state)
-{
- if (vp->v_unsafefs) {
- if (--vp->v_unsafefs->fsnode_count == 0) {
- vp->v_unsafefs->fsnodeowner = NULL;
- lck_mtx_unlock(&vp->v_unsafefs->fsnodelock);
- }
- }
- if (funnel_state)
- (void) thread_funnel_set(kernel_flock, *funnel_state);
-}
-#endif /* CONFIG_VFS_FUNNEL */
-
-
-
/* ====================================================================== */
/* ************ EXTERNAL KERNEL APIS ********************************** */
/* ====================================================================== */
/*
* implementations of exported VFS operations
*/
-int
+int
VFS_MOUNT(mount_t mp, vnode_t devvp, user_addr_t data, vfs_context_t ctx)
{
int error;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
- if ((mp == dead_mountp) || (mp->mnt_op->vfs_mount == 0))
- return(ENOTSUP);
-
-#if CONFIG_VFS_FUNNEL
- thread_safe = (mp->mnt_vtable->vfc_vfsflags & VFC_VFSTHREADSAFE);
- if (!thread_safe) {
- funnel_state = thread_funnel_set(kernel_flock, TRUE);
+ if ((mp == dead_mountp) || (mp->mnt_op->vfs_mount == 0)) {
+ return ENOTSUP;
}
-#endif /* CONFIG_VFS_FUNNEL */
-
+
if (vfs_context_is64bit(ctx)) {
if (vfs_64bitready(mp)) {
error = (*mp->mnt_op->vfs_mount)(mp, devvp, data, ctx);
- }
- else {
+ } else {
error = ENOTSUP;
}
- }
- else {
+ } else {
error = (*mp->mnt_op->vfs_mount)(mp, devvp, data, ctx);
}
-
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- (void) thread_funnel_set(kernel_flock, funnel_state);
- }
-#endif /* CONFIG_VFS_FUNNEL */
- return (error);
+ return error;
}
-int
+int
VFS_START(mount_t mp, int flags, vfs_context_t ctx)
{
int error;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
-
- if ((mp == dead_mountp) || (mp->mnt_op->vfs_start == 0))
- return(ENOTSUP);
-#if CONFIG_VFS_FUNNEL
- thread_safe = (mp->mnt_vtable->vfc_vfsflags & VFC_VFSTHREADSAFE);
- if (!thread_safe) {
- funnel_state = thread_funnel_set(kernel_flock, TRUE);
+ if ((mp == dead_mountp) || (mp->mnt_op->vfs_start == 0)) {
+ return ENOTSUP;
}
-#endif /* CONFIG_VFS_FUNNEL */
error = (*mp->mnt_op->vfs_start)(mp, flags, ctx);
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- (void) thread_funnel_set(kernel_flock, funnel_state);
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
- return (error);
+ return error;
}
-int
+int
VFS_UNMOUNT(mount_t mp, int flags, vfs_context_t ctx)
{
int error;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
- if ((mp == dead_mountp) || (mp->mnt_op->vfs_unmount == 0))
- return(ENOTSUP);
-
-#if CONFIG_VFS_FUNNEL
- thread_safe = (mp->mnt_vtable->vfc_vfsflags & VFC_VFSTHREADSAFE);
- if (!thread_safe) {
- funnel_state = thread_funnel_set(kernel_flock, TRUE);
+ if ((mp == dead_mountp) || (mp->mnt_op->vfs_unmount == 0)) {
+ return ENOTSUP;
}
-#endif /* CONFIG_VFS_FUNNEL */
error = (*mp->mnt_op->vfs_unmount)(mp, flags, ctx);
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- (void) thread_funnel_set(kernel_flock, funnel_state);
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
- return (error);
+ return error;
}
/*
*
* The return codes documented above are those which may currently
* be returned by HFS from hfs_vfs_root, which is a simple wrapper
- * for a call to hfs_vget on the volume mount poit, not including
+ * for a call to hfs_vget on the volume mount point, not including
* additional error codes which may be propagated from underlying
* routines called by hfs_vget.
*/
-int
+int
VFS_ROOT(mount_t mp, struct vnode ** vpp, vfs_context_t ctx)
{
int error;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
- if ((mp == dead_mountp) || (mp->mnt_op->vfs_root == 0))
- return(ENOTSUP);
+ if ((mp == dead_mountp) || (mp->mnt_op->vfs_root == 0)) {
+ return ENOTSUP;
+ }
if (ctx == NULL) {
ctx = vfs_context_current();
}
-#if CONFIG_VFS_FUNNEL
- thread_safe = (mp->mnt_vtable->vfc_vfsflags & VFC_VFSTHREADSAFE);
- if (!thread_safe) {
- funnel_state = thread_funnel_set(kernel_flock, TRUE);
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
error = (*mp->mnt_op->vfs_root)(mp, vpp, ctx);
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- (void) thread_funnel_set(kernel_flock, funnel_state);
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
- return (error);
+ return error;
}
-int
+int
VFS_QUOTACTL(mount_t mp, int cmd, uid_t uid, caddr_t datap, vfs_context_t ctx)
{
int error;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
- if ((mp == dead_mountp) || (mp->mnt_op->vfs_quotactl == 0))
- return(ENOTSUP);
-
-#if CONFIG_VFS_FUNNEL
- thread_safe = (mp->mnt_vtable->vfc_vfsflags & VFC_VFSTHREADSAFE);
- if (!thread_safe) {
- funnel_state = thread_funnel_set(kernel_flock, TRUE);
+ if ((mp == dead_mountp) || (mp->mnt_op->vfs_quotactl == 0)) {
+ return ENOTSUP;
}
-#endif /* CONFIG_VFS_FUNNEL */
error = (*mp->mnt_op->vfs_quotactl)(mp, cmd, uid, datap, ctx);
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- (void) thread_funnel_set(kernel_flock, funnel_state);
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
- return (error);
+ return error;
}
-int
+int
VFS_GETATTR(mount_t mp, struct vfs_attr *vfa, vfs_context_t ctx)
{
int error;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
- if ((mp == dead_mountp) || (mp->mnt_op->vfs_getattr == 0))
- return(ENOTSUP);
+ if ((mp == dead_mountp) || (mp->mnt_op->vfs_getattr == 0)) {
+ return ENOTSUP;
+ }
if (ctx == NULL) {
ctx = vfs_context_current();
}
-#if CONFIG_VFS_FUNNEL
- thread_safe = (mp->mnt_vtable->vfc_vfsflags & VFC_VFSTHREADSAFE);
- if (!thread_safe) {
- funnel_state = thread_funnel_set(kernel_flock, TRUE);
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
error = (*mp->mnt_op->vfs_getattr)(mp, vfa, ctx);
-
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- (void) thread_funnel_set(kernel_flock, funnel_state);
- }
-#endif /* CONFIG_VFS_FUNNEL */
- return(error);
+ return error;
}
-int
+int
VFS_SETATTR(mount_t mp, struct vfs_attr *vfa, vfs_context_t ctx)
{
int error;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
- if ((mp == dead_mountp) || (mp->mnt_op->vfs_setattr == 0))
- return(ENOTSUP);
+ if ((mp == dead_mountp) || (mp->mnt_op->vfs_setattr == 0)) {
+ return ENOTSUP;
+ }
if (ctx == NULL) {
ctx = vfs_context_current();
}
-#if CONFIG_VFS_FUNNEL
- thread_safe = (mp->mnt_vtable->vfc_vfsflags & VFC_VFSTHREADSAFE);
- if (!thread_safe) {
- funnel_state = thread_funnel_set(kernel_flock, TRUE);
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
error = (*mp->mnt_op->vfs_setattr)(mp, vfa, ctx);
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- (void) thread_funnel_set(kernel_flock, funnel_state);
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
- return(error);
+ return error;
}
-int
+int
VFS_SYNC(mount_t mp, int flags, vfs_context_t ctx)
{
int error;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
- if ((mp == dead_mountp) || (mp->mnt_op->vfs_sync == 0))
- return(ENOTSUP);
+ if ((mp == dead_mountp) || (mp->mnt_op->vfs_sync == 0)) {
+ return ENOTSUP;
+ }
if (ctx == NULL) {
ctx = vfs_context_current();
}
-#if CONFIG_VFS_FUNNEL
- thread_safe = (mp->mnt_vtable->vfc_vfsflags & VFC_VFSTHREADSAFE);
- if (!thread_safe) {
- funnel_state = thread_funnel_set(kernel_flock, TRUE);
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
error = (*mp->mnt_op->vfs_sync)(mp, flags, ctx);
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- (void) thread_funnel_set(kernel_flock, funnel_state);
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
- return(error);
+ return error;
}
-int
+int
VFS_VGET(mount_t mp, ino64_t ino, struct vnode **vpp, vfs_context_t ctx)
{
int error;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
- if ((mp == dead_mountp) || (mp->mnt_op->vfs_vget == 0))
- return(ENOTSUP);
+ if ((mp == dead_mountp) || (mp->mnt_op->vfs_vget == 0)) {
+ return ENOTSUP;
+ }
if (ctx == NULL) {
ctx = vfs_context_current();
}
-#if CONFIG_VFS_FUNNEL
- thread_safe = (mp->mnt_vtable->vfc_vfsflags & VFC_VFSTHREADSAFE);
- if (!thread_safe) {
- funnel_state = thread_funnel_set(kernel_flock, TRUE);
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
error = (*mp->mnt_op->vfs_vget)(mp, ino, vpp, ctx);
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- (void) thread_funnel_set(kernel_flock, funnel_state);
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
- return(error);
+ return error;
}
-int
-VFS_FHTOVP(mount_t mp, int fhlen, unsigned char * fhp, vnode_t * vpp, vfs_context_t ctx)
+int
+VFS_FHTOVP(mount_t mp, int fhlen, unsigned char *fhp, vnode_t *vpp, vfs_context_t ctx)
{
int error;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
- if ((mp == dead_mountp) || (mp->mnt_op->vfs_fhtovp == 0))
- return(ENOTSUP);
+ if ((mp == dead_mountp) || (mp->mnt_op->vfs_fhtovp == 0)) {
+ return ENOTSUP;
+ }
if (ctx == NULL) {
ctx = vfs_context_current();
}
-#if CONFIG_VFS_FUNNEL
- thread_safe = (mp->mnt_vtable->vfc_vfsflags & VFC_VFSTHREADSAFE);
- if (!thread_safe) {
- funnel_state = thread_funnel_set(kernel_flock, TRUE);
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
error = (*mp->mnt_op->vfs_fhtovp)(mp, fhlen, fhp, vpp, ctx);
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- (void) thread_funnel_set(kernel_flock, funnel_state);
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
- return(error);
+ return error;
}
-int
-VFS_VPTOFH(struct vnode * vp, int *fhlenp, unsigned char * fhp, vfs_context_t ctx)
+int
+VFS_VPTOFH(struct vnode *vp, int *fhlenp, unsigned char *fhp, vfs_context_t ctx)
{
int error;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
- if ((vp->v_mount == dead_mountp) || (vp->v_mount->mnt_op->vfs_vptofh == 0))
- return(ENOTSUP);
+ if ((vp->v_mount == dead_mountp) || (vp->v_mount->mnt_op->vfs_vptofh == 0)) {
+ return ENOTSUP;
+ }
if (ctx == NULL) {
ctx = vfs_context_current();
}
-#if CONFIG_VFS_FUNNEL
- thread_safe = THREAD_SAFE_FS(vp);
- if (!thread_safe) {
- funnel_state = thread_funnel_set(kernel_flock, TRUE);
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
error = (*vp->v_mount->mnt_op->vfs_vptofh)(vp, fhlenp, fhp, ctx);
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- (void) thread_funnel_set(kernel_flock, funnel_state);
+ return error;
+}
+
+int
+VFS_IOCTL(struct mount *mp, u_long command, caddr_t data,
+ int flags, vfs_context_t context)
+{
+ if (mp == dead_mountp || !mp->mnt_op->vfs_ioctl) {
+ return ENOTSUP;
}
-#endif /* CONFIG_VFS_FUNNEL */
- return(error);
+ return mp->mnt_op->vfs_ioctl(mp, command, data, flags,
+ context ?: vfs_context_current());
}
+int
+VFS_VGET_SNAPDIR(mount_t mp, vnode_t *vpp, vfs_context_t ctx)
+{
+ int error;
+
+ if ((mp == dead_mountp) || (mp->mnt_op->vfs_vget_snapdir == 0)) {
+ return ENOTSUP;
+ }
+
+ if (ctx == NULL) {
+ ctx = vfs_context_current();
+ }
+
+ error = (*mp->mnt_op->vfs_vget_snapdir)(mp, vpp, ctx);
+
+ return error;
+}
/* returns the cached throttle mask for the mount_t */
uint64_t
vfs_throttle_mask(mount_t mp)
{
- return(mp->mnt_throttle_mask);
+ return mp->mnt_throttle_mask;
}
/* returns a copy of vfs type name for the mount_t */
-void
-vfs_name(mount_t mp, char * buffer)
+void
+vfs_name(mount_t mp, char *buffer)
{
- strncpy(buffer, mp->mnt_vtable->vfc_name, MFSNAMELEN);
+ strncpy(buffer, mp->mnt_vtable->vfc_name, MFSNAMELEN);
}
/* returns vfs type number for the mount_t */
-int
+int
vfs_typenum(mount_t mp)
{
- return(mp->mnt_vtable->vfc_typenum);
+ return mp->mnt_vtable->vfc_typenum;
}
/* Safe to cast to "struct label*"; returns "void*" to limit dependence of mount.h on security headers. */
return (void*)mp->mnt_mntlabel;
}
+uint64_t
+vfs_mount_id(mount_t mp)
+{
+ return mp->mnt_mount_id;
+}
+
/* returns command modifier flags of mount_t ie. MNT_CMDFLAGS */
-uint64_t
+uint64_t
vfs_flags(mount_t mp)
{
- return((uint64_t)(mp->mnt_flag & (MNT_CMDFLAGS | MNT_VISFLAGMASK)));
+ return (uint64_t)(mp->mnt_flag & (MNT_CMDFLAGS | MNT_VISFLAGMASK));
}
/* set any of the command modifier flags(MNT_CMDFLAGS) in mount_t */
-void
+void
vfs_setflags(mount_t mp, uint64_t flags)
{
- uint32_t lflags = (uint32_t)(flags & (MNT_CMDFLAGS | MNT_VISFLAGMASK));
+ uint32_t lflags = (uint32_t)(flags & (MNT_CMDFLAGS | MNT_VISFLAGMASK));
mount_lock(mp);
mp->mnt_flag |= lflags;
}
/* clear any of the command modifier flags(MNT_CMDFLAGS) in mount_t */
-void
-vfs_clearflags(mount_t mp , uint64_t flags)
+void
+vfs_clearflags(mount_t mp, uint64_t flags)
{
- uint32_t lflags = (uint32_t)(flags & (MNT_CMDFLAGS | MNT_VISFLAGMASK));
+ uint32_t lflags = (uint32_t)(flags & (MNT_CMDFLAGS | MNT_VISFLAGMASK));
mount_lock(mp);
mp->mnt_flag &= ~lflags;
}
/* Is the mount_t ronly and upgrade read/write requested? */
-int
+int
vfs_iswriteupgrade(mount_t mp) /* ronly && MNTK_WANTRDWR */
{
- return ((mp->mnt_flag & MNT_RDONLY) && (mp->mnt_kern_flag & MNTK_WANTRDWR));
+ return (mp->mnt_flag & MNT_RDONLY) && (mp->mnt_kern_flag & MNTK_WANTRDWR);
}
/* Is the mount_t mounted ronly */
-int
+int
vfs_isrdonly(mount_t mp)
{
- return (mp->mnt_flag & MNT_RDONLY);
+ return mp->mnt_flag & MNT_RDONLY;
}
/* Is the mount_t mounted for filesystem synchronous writes? */
-int
+int
vfs_issynchronous(mount_t mp)
{
- return (mp->mnt_flag & MNT_SYNCHRONOUS);
+ return mp->mnt_flag & MNT_SYNCHRONOUS;
}
/* Is the mount_t mounted read/write? */
-int
+int
vfs_isrdwr(mount_t mp)
{
- return ((mp->mnt_flag & MNT_RDONLY) == 0);
+ return (mp->mnt_flag & MNT_RDONLY) == 0;
}
/* Is mount_t marked for update (ie MNT_UPDATE) */
-int
-vfs_isupdate(mount_t mp)
+int
+vfs_isupdate(mount_t mp)
{
- return (mp->mnt_flag & MNT_UPDATE);
+ return mp->mnt_flag & MNT_UPDATE;
}
/* Is mount_t marked for reload (ie MNT_RELOAD) */
-int
+int
vfs_isreload(mount_t mp)
{
- return ((mp->mnt_flag & MNT_UPDATE) && (mp->mnt_flag & MNT_RELOAD));
+ return (mp->mnt_flag & MNT_UPDATE) && (mp->mnt_flag & MNT_RELOAD);
}
/* Is mount_t marked for forced unmount (ie MNT_FORCE or MNTK_FRCUNMOUNT) */
-int
+int
vfs_isforce(mount_t mp)
{
- if ((mp->mnt_lflag & MNT_LFORCE) || (mp->mnt_kern_flag & MNTK_FRCUNMOUNT))
- return(1);
- else
- return(0);
+ if (mp->mnt_lflag & MNT_LFORCE) {
+ return 1;
+ } else {
+ return 0;
+ }
}
int
int
vfs_64bitready(mount_t mp)
{
- if ((mp->mnt_vtable->vfc_vfsflags & VFC_VFS64BITREADY))
- return(1);
- else
- return(0);
+ if ((mp->mnt_vtable->vfc_vfsflags & VFC_VFS64BITREADY)) {
+ return 1;
+ } else {
+ return 0;
+ }
}
int
vfs_authcache_ttl(mount_t mp)
{
- if ( (mp->mnt_kern_flag & (MNTK_AUTH_OPAQUE | MNTK_AUTH_CACHE_TTL)) )
- return (mp->mnt_authcache_ttl);
- else
- return (CACHED_RIGHT_INFINITE_TTL);
+ if ((mp->mnt_kern_flag & (MNTK_AUTH_OPAQUE | MNTK_AUTH_CACHE_TTL))) {
+ return mp->mnt_authcache_ttl;
+ } else {
+ return CACHED_RIGHT_INFINITE_TTL;
+ }
}
void
mount_unlock(mp);
}
-void
-vfs_markdependency(mount_t mp)
-{
- proc_t p = current_proc();
- mount_lock(mp);
- mp->mnt_dependent_process = p;
- mp->mnt_dependent_pid = proc_pid(p);
- mount_unlock(mp);
-}
-
-
int
vfs_authopaque(mount_t mp)
{
- if ((mp->mnt_kern_flag & MNTK_AUTH_OPAQUE))
- return(1);
- else
- return(0);
+ if ((mp->mnt_kern_flag & MNTK_AUTH_OPAQUE)) {
+ return 1;
+ } else {
+ return 0;
+ }
}
-int
+int
vfs_authopaqueaccess(mount_t mp)
{
- if ((mp->mnt_kern_flag & MNTK_AUTH_OPAQUE_ACCESS))
- return(1);
- else
- return(0);
+ if ((mp->mnt_kern_flag & MNTK_AUTH_OPAQUE_ACCESS)) {
+ return 1;
+ } else {
+ return 0;
+ }
}
void
mount_unlock(mp);
}
-void
+void
vfs_setauthopaqueaccess(mount_t mp)
{
mount_lock(mp);
mount_unlock(mp);
}
-void
+void
vfs_clearauthopaqueaccess(mount_t mp)
{
mount_lock(mp);
mount_unlock(mp);
}
+void
+vfs_setmntsystem(mount_t mp)
+{
+ mount_lock(mp);
+ mp->mnt_kern_flag |= MNTK_SYSTEM;
+ mount_unlock(mp);
+}
+
+void
+vfs_setmntsystemdata(mount_t mp)
+{
+ mount_lock(mp);
+ mp->mnt_kern_flag |= MNTK_SYSTEMDATA;
+ mount_unlock(mp);
+}
+
+void
+vfs_setmntswap(mount_t mp)
+{
+ mount_lock(mp);
+ mp->mnt_kern_flag |= (MNTK_SYSTEM | MNTK_SWAP_MOUNT);
+ mount_unlock(mp);
+}
+
void
vfs_clearextendedsecurity(mount_t mp)
{
mount_unlock(mp);
}
+void
+vfs_setnoswap(mount_t mp)
+{
+ mount_lock(mp);
+ mp->mnt_kern_flag |= MNTK_NOSWAP;
+ mount_unlock(mp);
+}
+
+void
+vfs_clearnoswap(mount_t mp)
+{
+ mount_lock(mp);
+ mp->mnt_kern_flag &= ~MNTK_NOSWAP;
+ mount_unlock(mp);
+}
+
int
vfs_extendedsecurity(mount_t mp)
{
- return(mp->mnt_kern_flag & MNTK_EXTENDED_SECURITY);
+ return mp->mnt_kern_flag & MNTK_EXTENDED_SECURITY;
}
/* returns the max size of short symlink in this mount_t */
-uint32_t
+uint32_t
vfs_maxsymlen(mount_t mp)
{
- return(mp->mnt_maxsymlinklen);
+ return mp->mnt_maxsymlinklen;
}
/* set max size of short symlink on mount_t */
-void
+void
vfs_setmaxsymlen(mount_t mp, uint32_t symlen)
{
mp->mnt_maxsymlinklen = symlen;
}
+boolean_t
+vfs_is_basesystem(mount_t mp)
+{
+ return ((mp->mnt_supl_kern_flag & MNTK_SUPL_BASESYSTEM) == 0) ? false : true;
+}
+
/* return a pointer to the RO vfs_statfs associated with mount_t */
-struct vfsstatfs *
+struct vfsstatfs *
vfs_statfs(mount_t mp)
{
- return(&mp->mnt_vfsstat);
+ return &mp->mnt_vfsstat;
}
int
vfs_getattr(mount_t mp, struct vfs_attr *vfa, vfs_context_t ctx)
{
- int error;
+ int error;
- if ((error = VFS_GETATTR(mp, vfa, ctx)) != 0)
- return(error);
+ if ((error = VFS_GETATTR(mp, vfa, ctx)) != 0) {
+ return error;
+ }
/*
- * If we have a filesystem create time, use it to default some others.
- */
- if (VFSATTR_IS_SUPPORTED(vfa, f_create_time)) {
- if (VFSATTR_IS_ACTIVE(vfa, f_modify_time) && !VFSATTR_IS_SUPPORTED(vfa, f_modify_time))
- VFSATTR_RETURN(vfa, f_modify_time, vfa->f_create_time);
- }
+ * If we have a filesystem create time, use it to default some others.
+ */
+ if (VFSATTR_IS_SUPPORTED(vfa, f_create_time)) {
+ if (VFSATTR_IS_ACTIVE(vfa, f_modify_time) && !VFSATTR_IS_SUPPORTED(vfa, f_modify_time)) {
+ VFSATTR_RETURN(vfa, f_modify_time, vfa->f_create_time);
+ }
+ }
- return(0);
+ return 0;
}
int
vfs_setattr(mount_t mp, struct vfs_attr *vfa, vfs_context_t ctx)
{
int error;
-
- if (vfs_isrdonly(mp))
+
+ /*
+ * with a read-only system volume, we need to allow rename of the root volume
+ * even if it's read-only. Don't return EROFS here if setattr changes only
+ * the volume name
+ */
+ if (vfs_isrdonly(mp) &&
+ !((strcmp(mp->mnt_vfsstat.f_fstypename, "apfs") == 0) && (vfa->f_active == VFSATTR_f_vol_name))) {
return EROFS;
+ }
error = VFS_SETATTR(mp, vfa, ctx);
-
+
/*
* If we had alternate ways of setting vfs attributes, we'd
* fall back here.
void *
vfs_fsprivate(mount_t mp)
{
- return(mp->mnt_data);
+ return mp->mnt_data;
}
/* set the private data handle in mount_t */
-void
+void
vfs_setfsprivate(mount_t mp, void *mntdata)
{
mount_lock(mp);
mount_unlock(mp);
}
+/* query whether the mount point supports native EAs */
+int
+vfs_nativexattrs(mount_t mp)
+{
+ return mp->mnt_kern_flag & MNTK_EXTENDED_ATTRS;
+}
/*
* return the block size of the underlying
* device associated with mount_t
*/
int
-vfs_devblocksize(mount_t mp) {
-
- return(mp->mnt_devblocksize);
+vfs_devblocksize(mount_t mp)
+{
+ return mp->mnt_devblocksize;
}
-/*
- * Returns vnode with an iocount that must be released with vnode_put()
+/*
+ * Returns vnode with an iocount that must be released with vnode_put()
*/
vnode_t
-vfs_vnodecovered(mount_t mp)
+vfs_vnodecovered(mount_t mp)
{
vnode_t vp = mp->mnt_vnodecovered;
if ((vp == NULL) || (vnode_getwithref(vp) != 0)) {
* The iocount must be released with vnode_put(). Note that this KPI is subtle
* with respect to the validity of using this device vnode for anything substantial
* (which is discouraged). If commands are sent to the device driver without
- * taking proper steps to ensure that the device is still open, chaos may ensue.
+ * taking proper steps to ensure that the device is still open, chaos may ensue.
* Similarly, this routine should only be called if there is some guarantee that
* the mount itself is still valid.
*/
void
vfs_ioattr(mount_t mp, struct vfsioattr *ioattrp)
{
- if (mp == NULL) {
- ioattrp->io_maxreadcnt = MAXPHYS;
+ ioattrp->io_reserved[0] = NULL;
+ ioattrp->io_reserved[1] = NULL;
+ if (mp == NULL) {
+ ioattrp->io_maxreadcnt = MAXPHYS;
ioattrp->io_maxwritecnt = MAXPHYS;
ioattrp->io_segreadcnt = 32;
ioattrp->io_segwritecnt = 32;
ioattrp->io_maxsegwritesize = MAXPHYS;
ioattrp->io_devblocksize = DEV_BSIZE;
ioattrp->io_flags = 0;
+ ioattrp->io_max_swappin_available = 0;
} else {
- ioattrp->io_maxreadcnt = mp->mnt_maxreadcnt;
+ ioattrp->io_maxreadcnt = mp->mnt_maxreadcnt;
ioattrp->io_maxwritecnt = mp->mnt_maxwritecnt;
ioattrp->io_segreadcnt = mp->mnt_segreadcnt;
ioattrp->io_segwritecnt = mp->mnt_segwritecnt;
ioattrp->io_maxsegwritesize = mp->mnt_maxsegwritesize;
ioattrp->io_devblocksize = mp->mnt_devblocksize;
ioattrp->io_flags = mp->mnt_ioflags;
+ ioattrp->io_max_swappin_available = mp->mnt_max_swappin_available;
}
- ioattrp->io_reserved[0] = NULL;
- ioattrp->io_reserved[1] = NULL;
}
/*
* set the IO attributes associated with mount_t
*/
-void
+void
vfs_setioattr(mount_t mp, struct vfsioattr * ioattrp)
{
- if (mp == NULL)
- return;
- mp->mnt_maxreadcnt = ioattrp->io_maxreadcnt;
+ if (mp == NULL) {
+ return;
+ }
+ mp->mnt_maxreadcnt = ioattrp->io_maxreadcnt;
mp->mnt_maxwritecnt = ioattrp->io_maxwritecnt;
mp->mnt_segreadcnt = ioattrp->io_segreadcnt;
mp->mnt_segwritecnt = ioattrp->io_segwritecnt;
mp->mnt_maxsegwritesize = ioattrp->io_maxsegwritesize;
mp->mnt_devblocksize = ioattrp->io_devblocksize;
mp->mnt_ioflags = ioattrp->io_flags;
+ mp->mnt_max_swappin_available = ioattrp->io_max_swappin_available;
}
-
+
/*
* Add a new filesystem into the kernel specified in passed in
- * vfstable structure. It fills in the vnode
+ * vfstable structure. It fills in the vnode
* dispatch vector that is to be passed to when vnodes are created.
* It returns a handle which is to be used to when the FS is to be removed
*/
typedef int (*PFI)(void *);
extern int vfs_opv_numops;
errno_t
-vfs_fsadd(struct vfs_fsentry *vfe, vfstable_t * handle)
+vfs_fsadd(struct vfs_fsentry *vfe, vfstable_t *handle)
{
- struct vfstable *newvfstbl = NULL;
- int i,j;
- int (***opv_desc_vector_p)(void *);
- int (**opv_desc_vector)(void *);
- struct vnodeopv_entry_desc *opve_descp;
+ struct vfstable *newvfstbl = NULL;
+ int i, j;
+ int(***opv_desc_vector_p)(void *);
+ int(**opv_desc_vector)(void *);
+ const struct vnodeopv_entry_desc *opve_descp;
int desccount;
int descsize;
PFI *descptr;
* ordinarily be done as part of the system startup;
*/
- if (vfe == (struct vfs_fsentry *)0)
- return(EINVAL);
+ if (vfe == (struct vfs_fsentry *)0) {
+ return EINVAL;
+ }
desccount = vfe->vfe_vopcnt;
- if ((desccount <=0) || ((desccount > 8)) || (vfe->vfe_vfsops == (struct vfsops *)NULL)
- || (vfe->vfe_opvdescs == (struct vnodeopv_desc **)NULL))
- return(EINVAL);
+ if ((desccount <= 0) || ((desccount > 8)) || (vfe->vfe_vfsops == (struct vfsops *)NULL)
+ || (vfe->vfe_opvdescs == (struct vnodeopv_desc **)NULL)) {
+ return EINVAL;
+ }
-#if !CONFIG_VFS_FUNNEL
- /* Non-threadsafe filesystems are not supported e.g. on K64 & iOS */
+ /* Non-threadsafe filesystems are not supported */
if ((vfe->vfe_flags & (VFS_TBLTHREADSAFE | VFS_TBLFSNODELOCK)) == 0) {
- return (EINVAL);
+ return EINVAL;
}
-#endif /* !CONFIG_VFS_FUNNEL */
- MALLOC(newvfstbl, void *, sizeof(struct vfstable), M_TEMP,
- M_WAITOK);
- bzero(newvfstbl, sizeof(struct vfstable));
+ newvfstbl = kheap_alloc(KHEAP_TEMP, sizeof(struct vfstable),
+ Z_WAITOK | Z_ZERO);
newvfstbl->vfc_vfsops = vfe->vfe_vfsops;
strncpy(&newvfstbl->vfc_name[0], vfe->vfe_fsname, MFSNAMELEN);
- if ((vfe->vfe_flags & VFS_TBLNOTYPENUM))
- newvfstbl->vfc_typenum = maxvfsconf++;
- else
+ if ((vfe->vfe_flags & VFS_TBLNOTYPENUM)) {
+ newvfstbl->vfc_typenum = maxvfstypenum++;
+ } else {
newvfstbl->vfc_typenum = vfe->vfe_fstypenum;
-
+ }
+
newvfstbl->vfc_refcount = 0;
newvfstbl->vfc_flags = 0;
newvfstbl->vfc_mountroot = NULL;
newvfstbl->vfc_next = NULL;
newvfstbl->vfc_vfsflags = 0;
- if (vfe->vfe_flags & VFS_TBL64BITREADY)
+ if (vfe->vfe_flags & VFS_TBL64BITREADY) {
newvfstbl->vfc_vfsflags |= VFC_VFS64BITREADY;
- if (vfe->vfe_flags & VFS_TBLVNOP_PAGEINV2)
+ }
+ if (vfe->vfe_flags & VFS_TBLVNOP_PAGEINV2) {
newvfstbl->vfc_vfsflags |= VFC_VFSVNOP_PAGEINV2;
- if (vfe->vfe_flags & VFS_TBLVNOP_PAGEOUTV2)
+ }
+ if (vfe->vfe_flags & VFS_TBLVNOP_PAGEOUTV2) {
newvfstbl->vfc_vfsflags |= VFC_VFSVNOP_PAGEOUTV2;
-#if CONFIG_VFS_FUNNEL
- if (vfe->vfe_flags & VFS_TBLTHREADSAFE)
- newvfstbl->vfc_vfsflags |= VFC_VFSTHREADSAFE;
- if (vfe->vfe_flags & VFS_TBLFSNODELOCK)
- newvfstbl->vfc_vfsflags |= VFC_VFSTHREADSAFE;
-#endif /* CONFIG_VFS_FUNNEL */
- if ((vfe->vfe_flags & VFS_TBLLOCALVOL) == VFS_TBLLOCALVOL)
+ }
+ if ((vfe->vfe_flags & VFS_TBLLOCALVOL) == VFS_TBLLOCALVOL) {
newvfstbl->vfc_flags |= MNT_LOCAL;
- if ((vfe->vfe_flags & VFS_TBLLOCALVOL) && (vfe->vfe_flags & VFS_TBLGENERICMNTARGS) == 0)
+ }
+ if ((vfe->vfe_flags & VFS_TBLLOCALVOL) && (vfe->vfe_flags & VFS_TBLGENERICMNTARGS) == 0) {
newvfstbl->vfc_vfsflags |= VFC_VFSLOCALARGS;
- else
+ } else {
newvfstbl->vfc_vfsflags |= VFC_VFSGENERICARGS;
+ }
- if (vfe->vfe_flags & VFS_TBLNATIVEXATTR)
+ if (vfe->vfe_flags & VFS_TBLNATIVEXATTR) {
newvfstbl->vfc_vfsflags |= VFC_VFSNATIVEXATTR;
- if (vfe->vfe_flags & VFS_TBLUNMOUNT_PREFLIGHT)
+ }
+ if (vfe->vfe_flags & VFS_TBLUNMOUNT_PREFLIGHT) {
newvfstbl->vfc_vfsflags |= VFC_VFSPREFLIGHT;
- if (vfe->vfe_flags & VFS_TBLREADDIR_EXTENDED)
+ }
+ if (vfe->vfe_flags & VFS_TBLREADDIR_EXTENDED) {
newvfstbl->vfc_vfsflags |= VFC_VFSREADDIR_EXTENDED;
- if (vfe->vfe_flags & VFS_TBLNOMACLABEL)
+ }
+ if (vfe->vfe_flags & VFS_TBLNOMACLABEL) {
newvfstbl->vfc_vfsflags |= VFC_VFSNOMACLABEL;
+ }
+ if (vfe->vfe_flags & VFS_TBLVNOP_NOUPDATEID_RENAME) {
+ newvfstbl->vfc_vfsflags |= VFC_VFSVNOP_NOUPDATEID_RENAME;
+ }
+ if (vfe->vfe_flags & VFS_TBLVNOP_SECLUDE_RENAME) {
+ newvfstbl->vfc_vfsflags |= VFC_VFSVNOP_SECLUDE_RENAME;
+ }
+ if (vfe->vfe_flags & VFS_TBLCANMOUNTROOT) {
+ newvfstbl->vfc_vfsflags |= VFC_VFSCANMOUNTROOT;
+ }
/*
* Allocate and init the vectors.
/* XXX - shouldn't be M_TEMP */
descsize = desccount * vfs_opv_numops * sizeof(PFI);
- MALLOC(descptr, PFI *, descsize,
- M_TEMP, M_WAITOK);
- bzero(descptr, descsize);
+ descptr = kheap_alloc(KHEAP_DEFAULT, descsize, Z_WAITOK | Z_ZERO);
newvfstbl->vfc_descptr = descptr;
newvfstbl->vfc_descsize = descsize;
-
-
- for (i= 0; i< desccount; i++ ) {
- opv_desc_vector_p = vfe->vfe_opvdescs[i]->opv_desc_vector_p;
- /*
- * Fill in the caller's pointer to the start of the i'th vector.
- * They'll need to supply it when calling vnode_create.
- */
- opv_desc_vector = descptr + i * vfs_opv_numops;
- *opv_desc_vector_p = opv_desc_vector;
- for (j = 0; vfe->vfe_opvdescs[i]->opv_desc_ops[j].opve_op; j++) {
- opve_descp = &(vfe->vfe_opvdescs[i]->opv_desc_ops[j]);
+ newvfstbl->vfc_sysctl = NULL;
+ for (i = 0; i < desccount; i++) {
+ opv_desc_vector_p = vfe->vfe_opvdescs[i]->opv_desc_vector_p;
/*
- * Sanity check: is this operation listed
- * in the list of operations? We check this
- * by seeing if its offset is zero. Since
- * the default routine should always be listed
- * first, it should be the only one with a zero
- * offset. Any other operation with a zero
- * offset is probably not listed in
- * vfs_op_descs, and so is probably an error.
- *
- * A panic here means the layer programmer
- * has committed the all-too common bug
- * of adding a new operation to the layer's
- * list of vnode operations but
- * not adding the operation to the system-wide
- * list of supported operations.
- */
- if (opve_descp->opve_op->vdesc_offset == 0 &&
- opve_descp->opve_op->vdesc_offset != VOFFSET(vnop_default)) {
- printf("vfs_fsadd: operation %s not listed in %s.\n",
- opve_descp->opve_op->vdesc_name,
- "vfs_op_descs");
- panic("vfs_fsadd: bad operation");
- }
- /*
- * Fill in this entry.
+ * Fill in the caller's pointer to the start of the i'th vector.
+ * They'll need to supply it when calling vnode_create.
*/
- opv_desc_vector[opve_descp->opve_op->vdesc_offset] =
- opve_descp->opve_impl;
- }
-
+ opv_desc_vector = descptr + i * vfs_opv_numops;
+ *opv_desc_vector_p = opv_desc_vector;
- /*
- * Finally, go back and replace unfilled routines
- * with their default. (Sigh, an O(n^3) algorithm. I
- * could make it better, but that'd be work, and n is small.)
- */
- opv_desc_vector_p = vfe->vfe_opvdescs[i]->opv_desc_vector_p;
+ for (j = 0; vfe->vfe_opvdescs[i]->opv_desc_ops[j].opve_op; j++) {
+ opve_descp = &(vfe->vfe_opvdescs[i]->opv_desc_ops[j]);
- /*
- * Force every operations vector to have a default routine.
- */
- opv_desc_vector = *opv_desc_vector_p;
- if (opv_desc_vector[VOFFSET(vnop_default)] == NULL)
- panic("vfs_fsadd: operation vector without default routine.");
- for (j = 0; j < vfs_opv_numops; j++)
- if (opv_desc_vector[j] == NULL)
- opv_desc_vector[j] =
- opv_desc_vector[VOFFSET(vnop_default)];
+ /* Silently skip known-disabled operations */
+ if (opve_descp->opve_op->vdesc_flags & VDESC_DISABLED) {
+ printf("vfs_fsadd: Ignoring reference in %p to disabled operation %s.\n",
+ vfe->vfe_opvdescs[i], opve_descp->opve_op->vdesc_name);
+ continue;
+ }
+
+ /*
+ * Sanity check: is this operation listed
+ * in the list of operations? We check this
+ * by seeing if its offset is zero. Since
+ * the default routine should always be listed
+ * first, it should be the only one with a zero
+ * offset. Any other operation with a zero
+ * offset is probably not listed in
+ * vfs_op_descs, and so is probably an error.
+ *
+ * A panic here means the layer programmer
+ * has committed the all-too common bug
+ * of adding a new operation to the layer's
+ * list of vnode operations but
+ * not adding the operation to the system-wide
+ * list of supported operations.
+ */
+ if (opve_descp->opve_op->vdesc_offset == 0 &&
+ opve_descp->opve_op != VDESC(vnop_default)) {
+ printf("vfs_fsadd: operation %s not listed in %s.\n",
+ opve_descp->opve_op->vdesc_name,
+ "vfs_op_descs");
+ panic("vfs_fsadd: bad operation");
+ }
+ /*
+ * Fill in this entry.
+ */
+ opv_desc_vector[opve_descp->opve_op->vdesc_offset] =
+ opve_descp->opve_impl;
+ }
+
+
+ /*
+ * Finally, go back and replace unfilled routines
+ * with their default. (Sigh, an O(n^3) algorithm. I
+ * could make it better, but that'd be work, and n is small.)
+ */
+ opv_desc_vector_p = vfe->vfe_opvdescs[i]->opv_desc_vector_p;
+
+ /*
+ * Force every operations vector to have a default routine.
+ */
+ opv_desc_vector = *opv_desc_vector_p;
+ if (opv_desc_vector[VOFFSET(vnop_default)] == NULL) {
+ panic("vfs_fsadd: operation vector without default routine.");
+ }
+ for (j = 0; j < vfs_opv_numops; j++) {
+ if (opv_desc_vector[j] == NULL) {
+ opv_desc_vector[j] =
+ opv_desc_vector[VOFFSET(vnop_default)];
+ }
+ }
+ } /* end of each vnodeopv_desc parsing */
- } /* end of each vnodeopv_desc parsing */
-
*handle = vfstable_add(newvfstbl);
- if (newvfstbl->vfc_typenum <= maxvfsconf )
- maxvfsconf = newvfstbl->vfc_typenum + 1;
+ if (newvfstbl->vfc_typenum <= maxvfstypenum) {
+ maxvfstypenum = newvfstbl->vfc_typenum + 1;
+ }
if (newvfstbl->vfc_vfsops->vfs_init) {
struct vfsconf vfsc;
(*newvfstbl->vfc_vfsops->vfs_init)(&vfsc);
}
- FREE(newvfstbl, M_TEMP);
+ kheap_free(KHEAP_TEMP, newvfstbl, sizeof(struct vfstable));
- return(0);
+ return 0;
}
/*
* Removes the filesystem from kernel.
- * The argument passed in is the handle that was given when
+ * The argument passed in is the handle that was given when
* file system was added
*/
-errno_t
-vfs_fsremove(vfstable_t handle)
+errno_t
+vfs_fsremove(vfstable_t handle)
{
struct vfstable * vfstbl = (struct vfstable *)handle;
void *old_desc = NULL;
+ size_t descsize = 0;
errno_t err;
-
+
/* Preflight check for any mounts */
mount_list_lock();
- if ( vfstbl->vfc_refcount != 0 ) {
+ if (vfstbl->vfc_refcount != 0) {
mount_list_unlock();
return EBUSY;
}
-
+
/*
* save the old descriptor; the free cannot occur unconditionally,
* since vfstable_del() may fail.
*/
if (vfstbl->vfc_descptr && vfstbl->vfc_descsize) {
old_desc = vfstbl->vfc_descptr;
+ descsize = vfstbl->vfc_descsize;
}
err = vfstable_del(vfstbl);
mount_list_unlock();
/* free the descriptor if the delete was successful */
- if (err == 0 && old_desc) {
- FREE(old_desc, M_TEMP);
+ if (err == 0) {
+ kheap_free(KHEAP_DEFAULT, old_desc, descsize);
+ }
+
+ return err;
+}
+
+void
+vfs_setowner(mount_t mp, uid_t uid, gid_t gid)
+{
+ mp->mnt_fsowner = uid;
+ mp->mnt_fsgroup = gid;
+}
+
+/*
+ * Callers should be careful how they use this; accessing
+ * mnt_last_write_completed_timestamp is not thread-safe. Writing to
+ * it isn't either. Point is: be prepared to deal with strange values
+ * being returned.
+ */
+uint64_t
+vfs_idle_time(mount_t mp)
+{
+ if (mp->mnt_pending_write_size) {
+ return 0;
}
- return(err);
+ struct timeval now;
+
+ microuptime(&now);
+
+ return (now.tv_sec
+ - mp->mnt_last_write_completed_timestamp.tv_sec) * 1000000
+ + now.tv_usec - mp->mnt_last_write_completed_timestamp.tv_usec;
}
int
vfs_context_pid(vfs_context_t ctx)
{
- return (proc_pid(vfs_context_proc(ctx)));
+ return proc_pid(vfs_context_proc(ctx));
}
int
vfs_context_suser(vfs_context_t ctx)
{
- return (suser(ctx->vc_ucred, NULL));
+ return suser(ctx->vc_ucred, NULL);
}
/*
vfs_context_issignal(vfs_context_t ctx, sigset_t mask)
{
proc_t p = vfs_context_proc(ctx);
- if (p)
- return(proc_pendingsignals(p, mask));
- return(0);
+ if (p) {
+ return proc_pendingsignals(p, mask);
+ }
+ return 0;
}
int
{
proc_t proc = vfs_context_proc(ctx);
- if (proc)
- return(proc_is64bit(proc));
- return(0);
+ if (proc) {
+ return proc_is64bit(proc);
+ }
+ return 0;
}
+boolean_t
+vfs_context_can_resolve_triggers(vfs_context_t ctx)
+{
+ proc_t proc = vfs_context_proc(ctx);
+
+ if (proc) {
+ if (proc->p_vfs_iopolicy &
+ P_VFS_IOPOLICY_TRIGGER_RESOLVE_DISABLE) {
+ return false;
+ }
+ return true;
+ }
+ return false;
+}
/*
* vfs_context_proc
proc_t
vfs_context_proc(vfs_context_t ctx)
{
- proc_t proc = NULL;
+ proc_t proc = NULL;
- if (ctx != NULL && ctx->vc_thread != NULL)
+ if (ctx != NULL && ctx->vc_thread != NULL) {
proc = (proc_t)get_bsdthreadtask_info(ctx->vc_thread);
- if (proc != NULL && (proc->p_fd == NULL || (proc->p_lflag & P_LVFORK)))
+ }
+ if (proc != NULL && (proc->p_fd == NULL || (proc->p_lflag & P_LVFORK))) {
proc = NULL;
+ }
- return(proc == NULL ? current_proc() : proc);
+ return proc == NULL ? current_proc() : proc;
}
/*
* vfs_context_get_special_port
*
* Description: Return the requested special port from the task associated
- * with the given context.
+ * with the given context.
*
* Parameters: vfs_context_t The context to use
- * int Index of special port
- * ipc_port_t * Pointer to returned port
+ * int Index of special port
+ * ipc_port_t * Pointer to returned port
*
* Returns: kern_return_t see task_get_special_port()
*/
kern_return_t
vfs_context_get_special_port(vfs_context_t ctx, int which, ipc_port_t *portp)
{
- task_t task = NULL;
+ task_t task = NULL;
- if (ctx != NULL && ctx->vc_thread != NULL)
+ if (ctx != NULL && ctx->vc_thread != NULL) {
task = get_threadtask(ctx->vc_thread);
+ }
return task_get_special_port(task, which, portp);
}
* vfs_context_set_special_port
*
* Description: Set the requested special port in the task associated
- * with the given context.
+ * with the given context.
*
* Parameters: vfs_context_t The context to use
- * int Index of special port
- * ipc_port_t New special port
+ * int Index of special port
+ * ipc_port_t New special port
*
- * Returns: kern_return_t see task_set_special_port()
+ * Returns: kern_return_t see task_set_special_port_internal()
*/
kern_return_t
vfs_context_set_special_port(vfs_context_t ctx, int which, ipc_port_t port)
{
- task_t task = NULL;
+ task_t task = NULL;
- if (ctx != NULL && ctx->vc_thread != NULL)
+ if (ctx != NULL && ctx->vc_thread != NULL) {
task = get_threadtask(ctx->vc_thread);
+ }
- return task_set_special_port(task, which, port);
+ return task_set_special_port_internal(task, which, port);
}
/*
thread_t
vfs_context_thread(vfs_context_t ctx)
{
- return(ctx->vc_thread);
+ return ctx->vc_thread;
}
{
vnode_t cwd = NULLVP;
- if(ctx != NULL && ctx->vc_thread != NULL) {
+ if (ctx != NULL && ctx->vc_thread != NULL) {
uthread_t uth = get_bsdthread_info(ctx->vc_thread);
proc_t proc;
*/
if ((cwd = uth->uu_cdir) == NULLVP &&
(proc = (proc_t)get_bsdthreadtask_info(ctx->vc_thread)) != NULL &&
- proc->p_fd != NULL)
+ proc->p_fd != NULL) {
cwd = proc->p_fd->fd_cdir;
+ }
}
- return(cwd);
+ return cwd;
}
/*
* vfs_context_create
*
- * Description: Allocate and initialize a new context.
+ * Description: Allocate and initialize a new context.
*
- * Parameters: vfs_context_t: Context to copy, or NULL for new
+ * Parameters: vfs_context_t: Context to copy, or NULL for new
*
* Returns: Pointer to new context
*
- * Notes: Copy cred and thread from argument, if available; else
- * initialize with current thread and new cred. Returns
- * with a reference held on the credential.
+ * Notes: Copy cred and thread from argument, if available; else
+ * initialize with current thread and new cred. Returns
+ * with a reference held on the credential.
*/
vfs_context_t
vfs_context_create(vfs_context_t ctx)
{
vfs_context_t newcontext;
- newcontext = (vfs_context_t)kalloc(sizeof(struct vfs_context));
+ newcontext = zalloc_flags(ZV_VFS_CONTEXT, Z_WAITOK | Z_ZERO);
if (newcontext) {
kauth_cred_t safecred;
newcontext->vc_thread = current_thread();
safecred = kauth_cred_get();
}
- if (IS_VALID_CRED(safecred))
+ if (IS_VALID_CRED(safecred)) {
kauth_cred_ref(safecred);
+ }
newcontext->vc_ucred = safecred;
- return(newcontext);
+ return newcontext;
}
- return(NULL);
+ return NULL;
}
vfs_context_current(void)
{
vfs_context_t ctx = NULL;
- volatile uthread_t ut = (uthread_t)get_bsdthread_info(current_thread());
+ uthread_t ut = (uthread_t)get_bsdthread_info(current_thread());
- if (ut != NULL ) {
+ if (ut != NULL) {
if (ut->uu_context.vc_ucred != NULL) {
ctx = &ut->uu_context;
}
}
- return(ctx == NULL ? vfs_context_kernel() : ctx);
+ return ctx == NULL ? vfs_context_kernel() : ctx;
}
* This is also used by imageboot_setup(), called early from bsd_init() after
* kernproc has been given a credential.
*
- * Note: The use of proc_thread() here is a convenience to avoid inclusion
- * of many Mach headers to do the reference directly rather than indirectly;
- * we will need to forego this convenience when we reture proc_thread().
*/
static struct vfs_context kerncontext;
vfs_context_t
vfs_context_kernel(void)
{
- if (kerncontext.vc_ucred == NOCRED)
- kerncontext.vc_ucred = kernproc->p_ucred;
- if (kerncontext.vc_thread == NULL)
- kerncontext.vc_thread = proc_thread(kernproc);
-
- return(&kerncontext);
+ return &kerncontext;
}
+/*
+ * Called early in bsd_init() when kernproc sets its thread and cred context.
+ */
+void
+vfs_set_context_kernel(vfs_context_t ctx)
+{
+ kerncontext = *ctx;
+}
int
vfs_context_rele(vfs_context_t ctx)
{
if (ctx) {
- if (IS_VALID_CRED(ctx->vc_ucred))
+ if (IS_VALID_CRED(ctx->vc_ucred)) {
kauth_cred_unref(&ctx->vc_ucred);
- kfree(ctx, sizeof(struct vfs_context));
+ }
+ zfree(ZV_VFS_CONTEXT, ctx);
}
- return(0);
+ return 0;
}
kauth_cred_t
vfs_context_ucred(vfs_context_t ctx)
{
- return (ctx->vc_ucred);
+ return ctx->vc_ucred;
}
/*
int
vfs_context_issuser(vfs_context_t ctx)
{
- return(kauth_cred_issuser(vfs_context_ucred(ctx)));
+ return kauth_cred_issuser(vfs_context_ucred(ctx));
+}
+
+int
+vfs_context_iskernel(vfs_context_t ctx)
+{
+ return ctx == &kerncontext;
}
/*
* Given a context, for all fields of vfs_context_t which
* are not held with a reference, set those fields to the
- * values for the current execution context. Currently, this
+ * values for the current execution context. Currently, this
* just means the vc_thread.
*
* Returns: 0 for success, nonzero for failure
*
* The intended use is:
* 1. vfs_context_create() gets the caller a context
- * 2. vfs_context_bind() sets the unrefcounted data
- * 3. vfs_context_rele() releases the context
+ * 2. vfs_context_bind() sets the unrefcounted data
+ * 3. vfs_context_rele() releases the context
*
*/
int
return 0;
}
+int
+vfs_isswapmount(mount_t mnt)
+{
+ return mnt && ISSET(mnt->mnt_kern_flag, MNTK_SWAP_MOUNT) ? 1 : 0;
+}
+
/* XXXXXXXXXXXXXX VNODE KAPIS XXXXXXXXXXXXXXXXXXXXXXXXX */
-
+
/*
* Convert between vnode types and inode formats (since POSIX.1
* defines mode word of stat structure in terms of inode formats).
*/
-enum vtype
+enum vtype
vnode_iftovt(int mode)
{
- return(iftovt_tab[((mode) & S_IFMT) >> 12]);
+ return iftovt_tab[((mode) & S_IFMT) >> 12];
}
-int
+int
vnode_vttoif(enum vtype indx)
{
- return(vttoif_tab[(int)(indx)]);
+ return vttoif_tab[(int)(indx)];
}
-int
+int
vnode_makeimode(int indx, int mode)
{
return (int)(VTTOIF(indx) | (mode));
*/
/* returns system root vnode iocount; It should be released using vnode_put() */
-vnode_t
+vnode_t
vfs_rootvnode(void)
{
int error;
+ lck_rw_lock_shared(rootvnode_rw_lock);
error = vnode_get(rootvnode);
- if (error)
- return ((vnode_t)0);
- else
+ lck_rw_unlock_shared(rootvnode_rw_lock);
+ if (error) {
+ return (vnode_t)0;
+ } else {
return rootvnode;
-}
+ }
+}
-uint32_t
+uint32_t
vnode_vid(vnode_t vp)
{
- return ((uint32_t)(vp->v_id));
-}
+ return (uint32_t)(vp->v_id);
+}
-mount_t
+mount_t
vnode_mount(vnode_t vp)
{
- return (vp->v_mount);
+ return vp->v_mount;
+}
+
+#if CONFIG_IOSCHED
+vnode_t
+vnode_mountdevvp(vnode_t vp)
+{
+ if (vp->v_mount) {
+ return vp->v_mount->mnt_devvp;
+ } else {
+ return (vnode_t)0;
+ }
+}
+#endif
+
+boolean_t
+vnode_isonexternalstorage(vnode_t vp)
+{
+ if (vp) {
+ if (vp->v_mount) {
+ if (vp->v_mount->mnt_ioflags & MNT_IOFLAGS_PERIPHERAL_DRIVE) {
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
}
-mount_t
+mount_t
vnode_mountedhere(vnode_t vp)
{
mount_t mp;
if ((vp->v_type == VDIR) && ((mp = vp->v_mountedhere) != NULL) &&
- (mp->mnt_vnodecovered == vp))
- return (mp);
- else
+ (mp->mnt_vnodecovered == vp)) {
+ return mp;
+ } else {
return (mount_t)NULL;
+ }
}
/* returns vnode type of vnode_t */
-enum vtype
+enum vtype
vnode_vtype(vnode_t vp)
{
- return (vp->v_type);
+ return vp->v_type;
}
/* returns FS specific node saved in vnode */
-void *
+void *
vnode_fsnode(vnode_t vp)
{
- return (vp->v_data);
+ return vp->v_data;
}
-void
+void
vnode_clearfsnode(vnode_t vp)
{
vp->v_data = NULL;
}
-dev_t
+dev_t
vnode_specrdev(vnode_t vp)
{
- return(vp->v_rdev);
+ return vp->v_rdev;
}
/* Accessor functions */
/* is vnode_t a root vnode */
-int
+int
vnode_isvroot(vnode_t vp)
{
- return ((vp->v_flag & VROOT)? 1 : 0);
+ return (vp->v_flag & VROOT)? 1 : 0;
}
/* is vnode_t a system vnode */
-int
+int
vnode_issystem(vnode_t vp)
{
- return ((vp->v_flag & VSYSTEM)? 1 : 0);
+ return (vp->v_flag & VSYSTEM)? 1 : 0;
}
/* is vnode_t a swap file vnode */
-int
+int
vnode_isswap(vnode_t vp)
{
- return ((vp->v_flag & VSWAP)? 1 : 0);
+ return (vp->v_flag & VSWAP)? 1 : 0;
}
/* is vnode_t a tty */
int
vnode_istty(vnode_t vp)
{
- return ((vp->v_flag & VISTTY) ? 1 : 0);
+ return (vp->v_flag & VISTTY) ? 1 : 0;
}
/* if vnode_t mount operation in progress */
-int
+int
vnode_ismount(vnode_t vp)
{
- return ((vp->v_flag & VMOUNT)? 1 : 0);
+ return (vp->v_flag & VMOUNT)? 1 : 0;
}
/* is this vnode under recyle now */
-int
+int
vnode_isrecycled(vnode_t vp)
{
int ret;
vnode_lock_spin(vp);
- ret = (vp->v_lflag & (VL_TERMINATE|VL_DEAD))? 1 : 0;
+ ret = (vp->v_lflag & (VL_TERMINATE | VL_DEAD))? 1 : 0;
vnode_unlock(vp);
- return(ret);
+ return ret;
}
/* vnode was created by background task requesting rapid aging
- and has not since been referenced by a normal task */
+ * and has not since been referenced by a normal task */
int
vnode_israge(vnode_t vp)
{
- return ((vp->v_flag & VRAGE)? 1 : 0);
+ return (vp->v_flag & VRAGE)? 1 : 0;
}
int
vnode_needssnapshots(vnode_t vp)
{
- return ((vp->v_flag & VNEEDSSNAPSHOT)? 1 : 0);
+ return (vp->v_flag & VNEEDSSNAPSHOT)? 1 : 0;
}
/* Check the process/thread to see if we should skip atime updates */
int
-vfs_ctx_skipatime (vfs_context_t ctx) {
+vfs_ctx_skipatime(vfs_context_t ctx)
+{
struct uthread *ut;
proc_t proc;
thread_t thr;
proc = vfs_context_proc(ctx);
- thr = vfs_context_thread (ctx);
+ thr = vfs_context_thread(ctx);
/* Validate pointers in case we were invoked via a kernel context */
if (thr && proc) {
- ut = get_bsdthread_info (thr);
+ ut = get_bsdthread_info(thr);
if (proc->p_lflag & P_LRAGE_VNODES) {
return 1;
}
-
+
if (ut) {
- if (ut->uu_flag & UT_RAGE_VNODES) {
+ if (ut->uu_flag & (UT_RAGE_VNODES | UT_ATIME_UPDATE)) {
return 1;
}
}
+
+ if (proc->p_vfs_iopolicy & P_VFS_IOPOLICY_ATIME_UPDATES) {
+ return 1;
+ }
}
return 0;
}
/* is vnode_t marked to not keep data cached once it's been consumed */
-int
+int
vnode_isnocache(vnode_t vp)
{
- return ((vp->v_flag & VNOCACHE_DATA)? 1 : 0);
+ return (vp->v_flag & VNOCACHE_DATA)? 1 : 0;
}
/*
int
vnode_isnoreadahead(vnode_t vp)
{
- return ((vp->v_flag & VRAOFF)? 1 : 0);
+ return (vp->v_flag & VRAOFF)? 1 : 0;
}
int
vnode_is_openevt(vnode_t vp)
{
- return ((vp->v_flag & VOPENEVT)? 1 : 0);
+ return (vp->v_flag & VOPENEVT)? 1 : 0;
}
/* is vnode_t a standard one? */
-int
+int
vnode_isstandard(vnode_t vp)
{
- return ((vp->v_flag & VSTANDARD)? 1 : 0);
+ return (vp->v_flag & VSTANDARD)? 1 : 0;
}
/* don't vflush() if SKIPSYSTEM */
-int
+int
vnode_isnoflush(vnode_t vp)
{
- return ((vp->v_flag & VNOFLUSH)? 1 : 0);
+ return (vp->v_flag & VNOFLUSH)? 1 : 0;
}
/* is vnode_t a regular file */
-int
+int
vnode_isreg(vnode_t vp)
{
- return ((vp->v_type == VREG)? 1 : 0);
+ return (vp->v_type == VREG)? 1 : 0;
}
/* is vnode_t a directory? */
-int
+int
vnode_isdir(vnode_t vp)
{
- return ((vp->v_type == VDIR)? 1 : 0);
+ return (vp->v_type == VDIR)? 1 : 0;
}
/* is vnode_t a symbolic link ? */
-int
+int
vnode_islnk(vnode_t vp)
{
- return ((vp->v_type == VLNK)? 1 : 0);
+ return (vp->v_type == VLNK)? 1 : 0;
}
int
goto yes;
}
#endif /* CONFIG_TRIGGERS */
-
}
if (vnode_islnk(vp)) {
/* From lookup(): || *ndp->ni_next == '/') No need for this, we know we're NULL-terminated here */
- if (cnp->cn_flags & FOLLOW) {
+ if (cnp->cn_flags & FOLLOW) {
goto yes;
}
if (ndp->ni_flag & NAMEI_TRAILINGSLASH) {
}
/* is vnode_t a fifo ? */
-int
+int
vnode_isfifo(vnode_t vp)
{
- return ((vp->v_type == VFIFO)? 1 : 0);
+ return (vp->v_type == VFIFO)? 1 : 0;
}
/* is vnode_t a block device? */
-int
+int
vnode_isblk(vnode_t vp)
{
- return ((vp->v_type == VBLK)? 1 : 0);
+ return (vp->v_type == VBLK)? 1 : 0;
}
int
vnode_isspec(vnode_t vp)
{
- return (((vp->v_type == VCHR) || (vp->v_type == VBLK)) ? 1 : 0);
+ return ((vp->v_type == VCHR) || (vp->v_type == VBLK)) ? 1 : 0;
}
/* is vnode_t a char device? */
-int
+int
vnode_ischr(vnode_t vp)
{
- return ((vp->v_type == VCHR)? 1 : 0);
+ return (vp->v_type == VCHR)? 1 : 0;
}
/* is vnode_t a socket? */
-int
+int
vnode_issock(vnode_t vp)
{
- return ((vp->v_type == VSOCK)? 1 : 0);
+ return (vp->v_type == VSOCK)? 1 : 0;
}
/* is vnode_t a device with multiple active vnodes referring to it? */
int
vnode_isaliased(vnode_t vp)
-{
+{
enum vtype vt = vp->v_type;
if (!((vt == VCHR) || (vt == VBLK))) {
return 0;
} else {
- return (vp->v_specflags & SI_ALIASED);
+ return vp->v_specflags & SI_ALIASED;
}
}
/* is vnode_t a named stream? */
-int
+int
vnode_isnamedstream(
#if NAMEDSTREAMS
- vnode_t vp
+ vnode_t vp
#else
- __unused vnode_t vp
+ __unused vnode_t vp
#endif
- )
+ )
{
#if NAMEDSTREAMS
- return ((vp->v_flag & VISNAMEDSTREAM) ? 1 : 0);
+ return (vp->v_flag & VISNAMEDSTREAM) ? 1 : 0;
#else
- return (0);
+ return 0;
#endif
}
-int
+int
vnode_isshadow(
#if NAMEDSTREAMS
- vnode_t vp
+ vnode_t vp
#else
- __unused vnode_t vp
+ __unused vnode_t vp
#endif
- )
+ )
{
#if NAMEDSTREAMS
- return ((vp->v_flag & VISSHADOW) ? 1 : 0);
+ return (vp->v_flag & VISSHADOW) ? 1 : 0;
#else
- return (0);
+ return 0;
#endif
}
/* does vnode have associated named stream vnodes ? */
-int
+int
vnode_hasnamedstreams(
#if NAMEDSTREAMS
- vnode_t vp
+ vnode_t vp
#else
- __unused vnode_t vp
+ __unused vnode_t vp
#endif
- )
+ )
{
#if NAMEDSTREAMS
- return ((vp->v_lflag & VL_HASSTREAMS) ? 1 : 0);
+ return (vp->v_lflag & VL_HASSTREAMS) ? 1 : 0;
#else
- return (0);
+ return 0;
#endif
}
/* TBD: set vnode_t to not cache data after it is consumed once; used for quota */
-void
+void
vnode_setnocache(vnode_t vp)
{
vnode_lock_spin(vp);
vnode_unlock(vp);
}
-void
+void
vnode_clearnocache(vnode_t vp)
{
vnode_lock_spin(vp);
}
-void
+void
vnode_setnoreadahead(vnode_t vp)
{
vnode_lock_spin(vp);
vnode_unlock(vp);
}
-void
+void
vnode_clearnoreadahead(vnode_t vp)
{
vnode_lock_spin(vp);
vnode_unlock(vp);
}
+int
+vnode_isfastdevicecandidate(vnode_t vp)
+{
+ return (vp->v_flag & VFASTDEVCANDIDATE)? 1 : 0;
+}
+
+void
+vnode_setfastdevicecandidate(vnode_t vp)
+{
+ vnode_lock_spin(vp);
+ vp->v_flag |= VFASTDEVCANDIDATE;
+ vnode_unlock(vp);
+}
+
+void
+vnode_clearfastdevicecandidate(vnode_t vp)
+{
+ vnode_lock_spin(vp);
+ vp->v_flag &= ~VFASTDEVCANDIDATE;
+ vnode_unlock(vp);
+}
+
+int
+vnode_isautocandidate(vnode_t vp)
+{
+ return (vp->v_flag & VAUTOCANDIDATE)? 1 : 0;
+}
+
+void
+vnode_setautocandidate(vnode_t vp)
+{
+ vnode_lock_spin(vp);
+ vp->v_flag |= VAUTOCANDIDATE;
+ vnode_unlock(vp);
+}
+
+void
+vnode_clearautocandidate(vnode_t vp)
+{
+ vnode_lock_spin(vp);
+ vp->v_flag &= ~VAUTOCANDIDATE;
+ vnode_unlock(vp);
+}
+
+
+
/* mark vnode_t to skip vflush() is SKIPSYSTEM */
-void
+void
vnode_setnoflush(vnode_t vp)
{
vnode_lock_spin(vp);
vnode_unlock(vp);
}
-void
+void
vnode_clearnoflush(vnode_t vp)
{
vnode_lock_spin(vp);
/* is vnode_t a blkdevice and has a FS mounted on it */
-int
+int
vnode_ismountedon(vnode_t vp)
{
- return ((vp->v_specflags & SI_MOUNTEDON)? 1 : 0);
+ return (vp->v_specflags & SI_MOUNTEDON)? 1 : 0;
}
-void
+void
vnode_setmountedon(vnode_t vp)
{
vnode_lock_spin(vp);
vnode_unlock(vp);
}
-void
+void
vnode_clearmountedon(vnode_t vp)
{
vnode_lock_spin(vp);
void
vnode_settag(vnode_t vp, int tag)
{
- vp->v_tag = tag;
-
+ /*
+ * We only assign enum values to v_tag, but add an assert to make sure we
+ * catch it in dev/debug builds if this ever change.
+ */
+ assert(tag >= SHRT_MIN && tag <= SHRT_MAX);
+ vp->v_tag = (uint16_t)tag;
}
int
vnode_tag(vnode_t vp)
{
- return(vp->v_tag);
+ return vp->v_tag;
}
-vnode_t
+vnode_t
vnode_parent(vnode_t vp)
{
-
- return(vp->v_parent);
+ return vp->v_parent;
}
void
vp->v_parent = dvp;
}
-const char *
-vnode_name(vnode_t vp)
-{
- /* we try to keep v_name a reasonable name for the node */
- return(vp->v_name);
-}
-
void
vnode_setname(vnode_t vp, char * name)
{
}
/* return the registered FS name when adding the FS to kernel */
-void
+void
vnode_vfsname(vnode_t vp, char * buf)
{
- strncpy(buf, vp->v_mount->mnt_vtable->vfc_name, MFSNAMELEN);
+ strlcpy(buf, vp->v_mount->mnt_vtable->vfc_name, MFSNAMELEN);
}
/* return the FS type number */
-int
+int
vnode_vfstypenum(vnode_t vp)
{
- return(vp->v_mount->mnt_vtable->vfc_typenum);
+ return vp->v_mount->mnt_vtable->vfc_typenum;
}
int
-vnode_vfs64bitready(vnode_t vp)
+vnode_vfs64bitready(vnode_t vp)
{
-
- /*
+ /*
* Checking for dead_mountp is a bit of a hack for SnowLeopard: <rdar://problem/6269051>
*/
- if ((vp->v_mount != dead_mountp) && (vp->v_mount->mnt_vtable->vfc_vfsflags & VFC_VFS64BITREADY))
- return(1);
- else
- return(0);
+ if ((vp->v_mount != dead_mountp) && (vp->v_mount->mnt_vtable->vfc_vfsflags & VFC_VFS64BITREADY)) {
+ return 1;
+ } else {
+ return 0;
+ }
}
/* return the visible flags on associated mount point of vnode_t */
-uint32_t
+uint32_t
vnode_vfsvisflags(vnode_t vp)
{
- return(vp->v_mount->mnt_flag & MNT_VISFLAGMASK);
+ return vp->v_mount->mnt_flag & MNT_VISFLAGMASK;
}
/* return the command modifier flags on associated mount point of vnode_t */
-uint32_t
+uint32_t
vnode_vfscmdflags(vnode_t vp)
{
- return(vp->v_mount->mnt_flag & MNT_CMDFLAGS);
+ return vp->v_mount->mnt_flag & MNT_CMDFLAGS;
}
/* return the max symlink of short links of vnode_t */
-uint32_t
+uint32_t
vnode_vfsmaxsymlen(vnode_t vp)
{
- return(vp->v_mount->mnt_maxsymlinklen);
+ return vp->v_mount->mnt_maxsymlinklen;
}
/* return a pointer to the RO vfs_statfs associated with vnode_t's mount point */
struct vfsstatfs *
vnode_vfsstatfs(vnode_t vp)
{
- return(&vp->v_mount->mnt_vfsstat);
+ return &vp->v_mount->mnt_vfsstat;
}
/* return a handle to the FSs specific private handle associated with vnode_t's mount point */
void *
vnode_vfsfsprivate(vnode_t vp)
{
- return(vp->v_mount->mnt_data);
+ return vp->v_mount->mnt_data;
}
/* is vnode_t in a rdonly mounted FS */
-int
+int
vnode_vfsisrdonly(vnode_t vp)
{
- return ((vp->v_mount->mnt_flag & MNT_RDONLY)? 1 : 0);
+ return (vp->v_mount->mnt_flag & MNT_RDONLY)? 1 : 0;
}
int
-vnode_compound_rename_available(vnode_t vp)
+vnode_compound_rename_available(vnode_t vp)
{
return vnode_compound_op_available(vp, COMPOUND_VNOP_RENAME);
}
int
-vnode_compound_rmdir_available(vnode_t vp)
+vnode_compound_rmdir_available(vnode_t vp)
{
return vnode_compound_op_available(vp, COMPOUND_VNOP_RMDIR);
}
int
-vnode_compound_mkdir_available(vnode_t vp)
+vnode_compound_mkdir_available(vnode_t vp)
{
return vnode_compound_op_available(vp, COMPOUND_VNOP_MKDIR);
}
int
-vnode_compound_remove_available(vnode_t vp)
+vnode_compound_remove_available(vnode_t vp)
{
return vnode_compound_op_available(vp, COMPOUND_VNOP_REMOVE);
}
int
-vnode_compound_open_available(vnode_t vp)
+vnode_compound_open_available(vnode_t vp)
{
return vnode_compound_op_available(vp, COMPOUND_VNOP_OPEN);
}
int
-vnode_compound_op_available(vnode_t vp, compound_vnop_id_t opid)
+vnode_compound_op_available(vnode_t vp, compound_vnop_id_t opid)
{
- return ((vp->v_mount->mnt_compound_ops & opid) != 0);
+ return (vp->v_mount->mnt_compound_ops & opid) != 0;
}
/*
*
* XXX Published, but not used.
*/
-vnode_t
+vnode_t
current_workingdir(void)
{
return vfs_context_cwd(vfs_context_current());
}
-/* returns vnode ref to current root(chroot) directory */
-vnode_t
-current_rootdir(void)
-{
- proc_t proc = current_proc();
- struct vnode * vp ;
-
- if ( (vp = proc->p_fd->fd_rdir) ) {
- if ( (vnode_getwithref(vp)) )
- return (NULL);
- }
- return vp;
-}
-
/*
* Get a filesec and optional acl contents from an extended attribute.
* Function will attempt to retrive ACL, UUID, and GUID information using a
vnode_get_filesec(vnode_t vp, kauth_filesec_t *fsecp, vfs_context_t ctx)
{
kauth_filesec_t fsec;
- uio_t fsec_uio;
- size_t fsec_size;
- size_t xsize, rsize;
- int error;
- uint32_t host_fsec_magic;
- uint32_t host_acl_entrycount;
+ uio_t fsec_uio;
+ size_t fsec_size;
+ size_t xsize, rsize;
+ int error;
+ uint32_t host_fsec_magic;
+ uint32_t host_acl_entrycount;
fsec = NULL;
fsec_uio = NULL;
- error = 0;
-
+
/* find out how big the EA is */
- if (vn_getxattr(vp, KAUTH_FILESEC_XATTR, NULL, &xsize, XATTR_NOSECURITY, ctx) != 0) {
+ error = vn_getxattr(vp, KAUTH_FILESEC_XATTR, NULL, &xsize, XATTR_NOSECURITY, ctx);
+ if (error != 0) {
/* no EA, no filesec */
- if ((error == ENOATTR) || (error == ENOENT) || (error == EJUSTRETURN))
+ if ((error == ENOATTR) || (error == ENOENT) || (error == EJUSTRETURN)) {
error = 0;
+ }
/* either way, we are done */
goto out;
}
* rather than partial entries. Otherwise, we ignore it.
*/
if (!KAUTH_FILESEC_VALID(xsize)) {
- KAUTH_DEBUG(" ERROR - Bogus kauth_fiilesec_t: %ld bytes", xsize);
+ KAUTH_DEBUG(" ERROR - Bogus kauth_fiilesec_t: %ld bytes", xsize);
error = 0;
goto out;
}
-
+
/* how many entries would fit? */
fsec_size = KAUTH_FILESEC_COUNT(xsize);
+ if (fsec_size > KAUTH_ACL_MAX_ENTRIES) {
+ KAUTH_DEBUG(" ERROR - Bogus (too large) kauth_fiilesec_t: %ld bytes", xsize);
+ error = 0;
+ goto out;
+ }
/* get buffer and uio */
- if (((fsec = kauth_filesec_alloc(fsec_size)) == NULL) ||
+ if (((fsec = kauth_filesec_alloc((int)fsec_size)) == NULL) ||
((fsec_uio = uio_create(1, 0, UIO_SYSSPACE, UIO_READ)) == NULL) ||
uio_addiov(fsec_uio, CAST_USER_ADDR_T(fsec), xsize)) {
- KAUTH_DEBUG(" ERROR - could not allocate iov to read ACL");
+ KAUTH_DEBUG(" ERROR - could not allocate iov to read ACL");
error = ENOMEM;
goto out;
}
/* read security attribute */
rsize = xsize;
if ((error = vn_getxattr(vp,
- KAUTH_FILESEC_XATTR,
- fsec_uio,
- &rsize,
- XATTR_NOSECURITY,
- ctx)) != 0) {
-
+ KAUTH_FILESEC_XATTR,
+ fsec_uio,
+ &rsize,
+ XATTR_NOSECURITY,
+ ctx)) != 0) {
/* no attribute - no security data */
- if ((error == ENOATTR) || (error == ENOENT) || (error == EJUSTRETURN))
+ if ((error == ENOATTR) || (error == ENOENT) || (error == EJUSTRETURN)) {
error = 0;
+ }
/* either way, we are done */
goto out;
}
KAUTH_DEBUG("ACL - BAD ENTRYCOUNT %x", host_acl_entrycount);
goto out;
}
- if (KAUTH_FILESEC_SIZE(host_acl_entrycount) > rsize) {
+ if (KAUTH_FILESEC_SIZE(host_acl_entrycount) > rsize) {
KAUTH_DEBUG("ACL - BUFFER OVERFLOW (%d entries too big for %d)", host_acl_entrycount, rsize);
goto out;
}
fsec = NULL;
error = 0;
out:
- if (fsec != NULL)
+ if (fsec != NULL) {
kauth_filesec_free(fsec);
- if (fsec_uio != NULL)
+ }
+ if (fsec_uio != NULL) {
uio_free(fsec_uio);
- if (error)
+ }
+ if (error) {
*fsecp = NULL;
- return(error);
+ }
+ return error;
}
/*
static int
vnode_set_filesec(vnode_t vp, kauth_filesec_t fsec, kauth_acl_t acl, vfs_context_t ctx)
{
- uio_t fsec_uio;
- int error;
- uint32_t saved_acl_copysize;
+ uio_t fsec_uio;
+ int error;
+ uint32_t saved_acl_copysize;
fsec_uio = NULL;
-
+
if ((fsec_uio = uio_create(2, 0, UIO_SYSSPACE, UIO_WRITE)) == NULL) {
- KAUTH_DEBUG(" ERROR - could not allocate iov to write ACL");
+ KAUTH_DEBUG(" ERROR - could not allocate iov to write ACL");
error = ENOMEM;
goto out;
}
error = vn_setxattr(vp,
KAUTH_FILESEC_XATTR,
fsec_uio,
- XATTR_NOSECURITY, /* we have auth'ed already */
+ XATTR_NOSECURITY, /* we have auth'ed already */
ctx);
VFS_DEBUG(ctx, vp, "SETATTR - set ACL returning %d", error);
kauth_filesec_acl_setendian(KAUTH_ENDIAN_HOST, fsec, acl);
out:
- if (fsec_uio != NULL)
+ if (fsec_uio != NULL) {
uio_free(fsec_uio);
- return(error);
+ }
+ return error;
}
+/*
+ * Handle uid/gid == 99 and MNT_IGNORE_OWNERSHIP here.
+ */
+void
+vnode_attr_handle_mnt_ignore_ownership(struct vnode_attr *vap, mount_t mp, vfs_context_t ctx)
+{
+ uid_t nuid;
+ gid_t ngid;
+
+ if (VATTR_IS_ACTIVE(vap, va_uid)) {
+ if (vfs_context_issuser(ctx) && VATTR_IS_SUPPORTED(vap, va_uid)) {
+ nuid = vap->va_uid;
+ } else if (mp->mnt_flag & MNT_IGNORE_OWNERSHIP) {
+ nuid = mp->mnt_fsowner;
+ if (nuid == KAUTH_UID_NONE) {
+ nuid = 99;
+ }
+ } else if (VATTR_IS_SUPPORTED(vap, va_uid)) {
+ nuid = vap->va_uid;
+ } else {
+ /* this will always be something sensible */
+ nuid = mp->mnt_fsowner;
+ }
+ if ((nuid == 99) && !vfs_context_issuser(ctx)) {
+ nuid = kauth_cred_getuid(vfs_context_ucred(ctx));
+ }
+ VATTR_RETURN(vap, va_uid, nuid);
+ }
+ if (VATTR_IS_ACTIVE(vap, va_gid)) {
+ if (vfs_context_issuser(ctx) && VATTR_IS_SUPPORTED(vap, va_gid)) {
+ ngid = vap->va_gid;
+ } else if (mp->mnt_flag & MNT_IGNORE_OWNERSHIP) {
+ ngid = mp->mnt_fsgroup;
+ if (ngid == KAUTH_GID_NONE) {
+ ngid = 99;
+ }
+ } else if (VATTR_IS_SUPPORTED(vap, va_gid)) {
+ ngid = vap->va_gid;
+ } else {
+ /* this will always be something sensible */
+ ngid = mp->mnt_fsgroup;
+ }
+ if ((ngid == 99) && !vfs_context_issuser(ctx)) {
+ ngid = kauth_cred_getgid(vfs_context_ucred(ctx));
+ }
+ VATTR_RETURN(vap, va_gid, ngid);
+ }
+}
/*
* Returns: 0 Success
* ENOMEM Not enough space [only if has filesec]
+ * EINVAL Requested unknown attributes
* VNOP_GETATTR: ???
* vnode_get_filesec: ???
* kauth_cred_guid2uid: ???
{
kauth_filesec_t fsec;
kauth_acl_t facl;
- int error;
- uid_t nuid;
- gid_t ngid;
+ int error;
+
+ /*
+ * Reject attempts to fetch unknown attributes.
+ */
+ if (vap->va_active & ~VNODE_ATTR_ALL) {
+ return EINVAL;
+ }
/* don't ask for extended security data if the filesystem doesn't support it */
if (!vfs_extendedsecurity(vnode_mount(vp))) {
VATTR_SET_ACTIVE(vap, va_total_size);
VATTR_SET_ACTIVE(vap, va_total_alloc);
}
-
+
+ vap->va_vaflags &= ~VA_USEFSID;
+
error = VNOP_GETATTR(vp, vap, ctx);
if (error) {
KAUTH_DEBUG("ERROR - returning %d", error);
if (VATTR_NOT_RETURNED(vap, va_acl) || VATTR_NOT_RETURNED(vap, va_uuuid) || VATTR_NOT_RETURNED(vap, va_guuid)) {
fsec = NULL;
- if ((vp->v_type == VDIR) || (vp->v_type == VLNK) || (vp->v_type == VREG)) {
+ if (XATTR_VNODE_SUPPORTED(vp)) {
/* try to get the filesec */
- if ((error = vnode_get_filesec(vp, &fsec, ctx)) != 0)
+ if ((error = vnode_get_filesec(vp, &fsec, ctx)) != 0) {
goto out;
+ }
}
/* if no filesec, no attributes */
if (fsec == NULL) {
VATTR_RETURN(vap, va_uuuid, kauth_null_guid);
VATTR_RETURN(vap, va_guuid, kauth_null_guid);
} else {
-
/* looks good, try to return what we were asked for */
VATTR_RETURN(vap, va_uuuid, fsec->fsec_owner);
VATTR_RETURN(vap, va_guuid, fsec->fsec_group);
error = ENOMEM;
goto out;
}
- bcopy(&fsec->fsec_acl, facl, KAUTH_ACL_COPYSIZE(&fsec->fsec_acl));
+ __nochk_bcopy(&fsec->fsec_acl, facl, KAUTH_ACL_COPYSIZE(&fsec->fsec_acl));
VATTR_RETURN(vap, va_acl, facl);
}
}
* only expect what they asked for.
*/
if (VATTR_IS_SUPPORTED(vap, va_acl) && !VATTR_IS_ACTIVE(vap, va_acl)) {
- if (vap->va_acl != NULL)
+ if (vap->va_acl != NULL) {
kauth_acl_free(vap->va_acl);
+ }
VATTR_CLEAR_SUPPORTED(vap, va_acl);
}
-#if 0 /* enable when we have a filesystem only supporting UUIDs */
+#if 0 /* enable when we have a filesystem only supporting UUIDs */
/*
* Handle the case where we need a UID/GID, but only have extended
* security information.
if (VATTR_NOT_RETURNED(vap, va_uid) &&
VATTR_IS_SUPPORTED(vap, va_uuuid) &&
!kauth_guid_equal(&vap->va_uuuid, &kauth_null_guid)) {
- if ((error = kauth_cred_guid2uid(&vap->va_uuuid, &nuid)) == 0)
+ if ((error = kauth_cred_guid2uid(&vap->va_uuuid, &nuid)) == 0) {
VATTR_RETURN(vap, va_uid, nuid);
+ }
}
if (VATTR_NOT_RETURNED(vap, va_gid) &&
VATTR_IS_SUPPORTED(vap, va_guuid) &&
!kauth_guid_equal(&vap->va_guuid, &kauth_null_guid)) {
- if ((error = kauth_cred_guid2gid(&vap->va_guuid, &ngid)) == 0)
+ if ((error = kauth_cred_guid2gid(&vap->va_guuid, &ngid)) == 0) {
VATTR_RETURN(vap, va_gid, ngid);
+ }
}
#endif
-
- /*
- * Handle uid/gid == 99 and MNT_IGNORE_OWNERSHIP here.
- */
- if (VATTR_IS_ACTIVE(vap, va_uid)) {
- if (vfs_context_issuser(ctx) && VATTR_IS_SUPPORTED(vap, va_uid)) {
- nuid = vap->va_uid;
- } else if (vp->v_mount->mnt_flag & MNT_IGNORE_OWNERSHIP) {
- nuid = vp->v_mount->mnt_fsowner;
- if (nuid == KAUTH_UID_NONE)
- nuid = 99;
- } else if (VATTR_IS_SUPPORTED(vap, va_uid)) {
- nuid = vap->va_uid;
- } else {
- /* this will always be something sensible */
- nuid = vp->v_mount->mnt_fsowner;
- }
- if ((nuid == 99) && !vfs_context_issuser(ctx))
- nuid = kauth_cred_getuid(vfs_context_ucred(ctx));
- VATTR_RETURN(vap, va_uid, nuid);
- }
- if (VATTR_IS_ACTIVE(vap, va_gid)) {
- if (vfs_context_issuser(ctx) && VATTR_IS_SUPPORTED(vap, va_gid)) {
- ngid = vap->va_gid;
- } else if (vp->v_mount->mnt_flag & MNT_IGNORE_OWNERSHIP) {
- ngid = vp->v_mount->mnt_fsgroup;
- if (ngid == KAUTH_GID_NONE)
- ngid = 99;
- } else if (VATTR_IS_SUPPORTED(vap, va_gid)) {
- ngid = vap->va_gid;
- } else {
- /* this will always be something sensible */
- ngid = vp->v_mount->mnt_fsgroup;
- }
- if ((ngid == 99) && !vfs_context_issuser(ctx))
- ngid = kauth_cred_getgid(vfs_context_ucred(ctx));
- VATTR_RETURN(vap, va_gid, ngid);
- }
+
+ vnode_attr_handle_mnt_ignore_ownership(vap, vp->v_mount, ctx);
/*
* Synthesise some values that can be reasonably guessed.
*/
- if (!VATTR_IS_SUPPORTED(vap, va_iosize))
- VATTR_RETURN(vap, va_iosize, vp->v_mount->mnt_vfsstat.f_iosize);
-
- if (!VATTR_IS_SUPPORTED(vap, va_flags))
+ if (!VATTR_IS_SUPPORTED(vap, va_iosize)) {
+ assert(vp->v_mount->mnt_vfsstat.f_iosize <= UINT32_MAX);
+ VATTR_RETURN(vap, va_iosize, (uint32_t)vp->v_mount->mnt_vfsstat.f_iosize);
+ }
+
+ if (!VATTR_IS_SUPPORTED(vap, va_flags)) {
VATTR_RETURN(vap, va_flags, 0);
+ }
- if (!VATTR_IS_SUPPORTED(vap, va_filerev))
+ if (!VATTR_IS_SUPPORTED(vap, va_filerev)) {
VATTR_RETURN(vap, va_filerev, 0);
+ }
- if (!VATTR_IS_SUPPORTED(vap, va_gen))
+ if (!VATTR_IS_SUPPORTED(vap, va_gen)) {
VATTR_RETURN(vap, va_gen, 0);
+ }
/*
* Default sizes. Ordering here is important, as later defaults build on earlier ones.
*/
- if (!VATTR_IS_SUPPORTED(vap, va_data_size))
+ if (!VATTR_IS_SUPPORTED(vap, va_data_size)) {
VATTR_RETURN(vap, va_data_size, 0);
+ }
/* do we want any of the possibly-computed values? */
if (VATTR_IS_ACTIVE(vap, va_data_alloc) ||
VATTR_IS_ACTIVE(vap, va_total_size) ||
VATTR_IS_ACTIVE(vap, va_total_alloc)) {
- /* make sure f_bsize is valid */
- if (vp->v_mount->mnt_vfsstat.f_bsize == 0) {
- if ((error = vfs_update_vfsstat(vp->v_mount, ctx, VFS_KERNEL_EVENT)) != 0)
- goto out;
- }
+ /* make sure f_bsize is valid */
+ if (vp->v_mount->mnt_vfsstat.f_bsize == 0) {
+ if ((error = vfs_update_vfsstat(vp->v_mount, ctx, VFS_KERNEL_EVENT)) != 0) {
+ goto out;
+ }
+ }
/* default va_data_alloc from va_data_size */
- if (!VATTR_IS_SUPPORTED(vap, va_data_alloc))
+ if (!VATTR_IS_SUPPORTED(vap, va_data_alloc)) {
VATTR_RETURN(vap, va_data_alloc, roundup(vap->va_data_size, vp->v_mount->mnt_vfsstat.f_bsize));
+ }
/* default va_total_size from va_data_size */
- if (!VATTR_IS_SUPPORTED(vap, va_total_size))
+ if (!VATTR_IS_SUPPORTED(vap, va_total_size)) {
VATTR_RETURN(vap, va_total_size, vap->va_data_size);
+ }
/* default va_total_alloc from va_total_size which is guaranteed at this point */
- if (!VATTR_IS_SUPPORTED(vap, va_total_alloc))
+ if (!VATTR_IS_SUPPORTED(vap, va_total_alloc)) {
VATTR_RETURN(vap, va_total_alloc, roundup(vap->va_total_size, vp->v_mount->mnt_vfsstat.f_bsize));
+ }
}
/*
* If we don't have a change time, pull it from the modtime.
*/
- if (!VATTR_IS_SUPPORTED(vap, va_change_time) && VATTR_IS_SUPPORTED(vap, va_modify_time))
+ if (!VATTR_IS_SUPPORTED(vap, va_change_time) && VATTR_IS_SUPPORTED(vap, va_modify_time)) {
VATTR_RETURN(vap, va_change_time, vap->va_modify_time);
+ }
/*
* This is really only supported for the creation VNOPs, but since the field is there
/*
* The fsid can be obtained from the mountpoint directly.
*/
- VATTR_RETURN(vap, va_fsid, vp->v_mount->mnt_vfsstat.f_fsid.val[0]);
+ if (VATTR_IS_ACTIVE(vap, va_fsid) &&
+ (!VATTR_IS_SUPPORTED(vap, va_fsid) ||
+ vap->va_vaflags & VA_REALFSID || !(vap->va_vaflags & VA_USEFSID))) {
+ VATTR_RETURN(vap, va_fsid, vp->v_mount->mnt_vfsstat.f_fsid.val[0]);
+ }
out:
+ vap->va_vaflags &= ~VA_USEFSID;
+
+ return error;
+}
- return(error);
+/*
+ * Choose 32 bit or 64 bit fsid
+ */
+uint64_t
+vnode_get_va_fsid(struct vnode_attr *vap)
+{
+ if (VATTR_IS_SUPPORTED(vap, va_fsid64)) {
+ return (uint64_t)vap->va_fsid64.val[0] + ((uint64_t)vap->va_fsid64.val[1] << 32);
+ }
+ return vap->va_fsid;
}
/*
int
vnode_setattr(vnode_t vp, struct vnode_attr *vap, vfs_context_t ctx)
{
- int error, is_perm_change=0;
+ int error;
+#if CONFIG_FSE
+ uint64_t active;
+ int is_perm_change = 0;
+ int is_stat_change = 0;
+#endif
+
+ /*
+ * Reject attempts to set unknown attributes.
+ */
+ if (vap->va_active & ~VNODE_ATTR_ALL) {
+ return EINVAL;
+ }
/*
* Make sure the filesystem is mounted R/W.
error = EROFS;
goto out;
}
+
+#if DEVELOPMENT || DEBUG
+ /*
+ * XXX VSWAP: Check for entitlements or special flag here
+ * so we can restrict access appropriately.
+ */
+#else /* DEVELOPMENT || DEBUG */
+
+ if (vnode_isswap(vp) && (ctx != vfs_context_kernel())) {
+ error = EPERM;
+ goto out;
+ }
+#endif /* DEVELOPMENT || DEBUG */
+
#if NAMEDSTREAMS
/* For streams, va_data_size is the only setable attribute. */
if ((vp->v_flag & VISNAMEDSTREAM) && (vap->va_active != VNODE_ATTR_va_data_size)) {
goto out;
}
#endif
-
+ /* Check for truncation */
+ if (VATTR_IS_ACTIVE(vap, va_data_size)) {
+ switch (vp->v_type) {
+ case VREG:
+ /* For regular files it's ok */
+ break;
+ case VDIR:
+ /* Not allowed to truncate directories */
+ error = EISDIR;
+ goto out;
+ default:
+ /* For everything else we will clear the bit and let underlying FS decide on the rest */
+ VATTR_CLEAR_ACTIVE(vap, va_data_size);
+ if (vap->va_active) {
+ break;
+ }
+ /* If it was the only bit set, return success, to handle cases like redirect to /dev/null */
+ return 0;
+ }
+ }
+
/*
* If ownership is being ignored on this volume, we silently discard
* ownership changes.
VATTR_CLEAR_ACTIVE(vap, va_gid);
}
- if ( VATTR_IS_ACTIVE(vap, va_uid) || VATTR_IS_ACTIVE(vap, va_gid)
- || VATTR_IS_ACTIVE(vap, va_mode) || VATTR_IS_ACTIVE(vap, va_acl)) {
- is_perm_change = 1;
- }
-
/*
* Make sure that extended security is enabled if we're going to try
* to set any.
goto out;
}
+ /* Never allow the setting of any unsupported superuser flags. */
+ if (VATTR_IS_ACTIVE(vap, va_flags)) {
+ vap->va_flags &= (SF_SUPPORTED | UF_SETTABLE);
+ }
+
+#if CONFIG_FSE
+ /*
+ * Remember all of the active attributes that we're
+ * attempting to modify.
+ */
+ active = vap->va_active & ~VNODE_ATTR_RDONLY;
+#endif
+
error = VNOP_SETATTR(vp, vap, ctx);
- if ((error == 0) && !VATTR_ALL_SUPPORTED(vap))
+ if ((error == 0) && !VATTR_ALL_SUPPORTED(vap)) {
error = vnode_setattr_fallback(vp, vap, ctx);
+ }
#if CONFIG_FSE
- // only send a stat_changed event if this is more than
- // just an access or backup time update
- if (error == 0 && (vap->va_active != VNODE_ATTR_BIT(va_access_time)) && (vap->va_active != VNODE_ATTR_BIT(va_backup_time))) {
- if (is_perm_change) {
- if (need_fsevent(FSE_CHOWN, vp)) {
- add_fsevent(FSE_CHOWN, ctx, FSE_ARG_VNODE, vp, FSE_ARG_DONE);
+#define PERMISSION_BITS (VNODE_ATTR_BIT(va_uid) | VNODE_ATTR_BIT(va_uuuid) | \
+ VNODE_ATTR_BIT(va_gid) | VNODE_ATTR_BIT(va_guuid) | \
+ VNODE_ATTR_BIT(va_mode) | VNODE_ATTR_BIT(va_acl))
+
+ /*
+ * Now that we've changed them, decide whether to send an
+ * FSevent.
+ */
+ if ((active & PERMISSION_BITS) & vap->va_supported) {
+ is_perm_change = 1;
+ } else {
+ /*
+ * We've already checked the permission bits, and we
+ * also want to filter out access time / backup time
+ * changes.
+ */
+ active &= ~(PERMISSION_BITS |
+ VNODE_ATTR_BIT(va_access_time) |
+ VNODE_ATTR_BIT(va_backup_time));
+
+ /* Anything left to notify about? */
+ if (active & vap->va_supported) {
+ is_stat_change = 1;
+ }
+ }
+
+ if (error == 0) {
+ if (is_perm_change) {
+ if (need_fsevent(FSE_CHOWN, vp)) {
+ add_fsevent(FSE_CHOWN, ctx, FSE_ARG_VNODE, vp, FSE_ARG_DONE);
+ }
+ } else if (is_stat_change && need_fsevent(FSE_STAT_CHANGED, vp)) {
+ add_fsevent(FSE_STAT_CHANGED, ctx, FSE_ARG_VNODE, vp, FSE_ARG_DONE);
}
- } else if(need_fsevent(FSE_STAT_CHANGED, vp)) {
- add_fsevent(FSE_STAT_CHANGED, ctx, FSE_ARG_VNODE, vp, FSE_ARG_DONE);
- }
}
+#undef PERMISSION_BITS
#endif
out:
- return(error);
+ return error;
}
/*
kauth_filesec_t fsec;
kauth_acl_t facl;
struct kauth_filesec lfsec;
- int error;
+ int error;
error = 0;
* Fail for file types that we don't permit extended security
* to be set on.
*/
- if ((vp->v_type != VDIR) && (vp->v_type != VLNK) && (vp->v_type != VREG)) {
+ if (!XATTR_VNODE_SUPPORTED(vp)) {
VFS_DEBUG(ctx, vp, "SETATTR - Can't write ACL to file type %d", vnode_vtype(vp));
error = EINVAL;
goto out;
}
/* find the ACL */
facl = &fsec->fsec_acl;
-
+
/* if we're using the local filesec, we need to initialise it */
if (fsec == &lfsec) {
fsec->fsec_magic = KAUTH_FILESEC_MAGIC;
}
VATTR_SET_SUPPORTED(vap, va_acl);
}
-
+
/*
* If the filesec data is all invalid, we can just remove
* the EA completely.
kauth_guid_equal(&fsec->fsec_group, &kauth_null_guid)) {
error = vn_removexattr(vp, KAUTH_FILESEC_XATTR, XATTR_NOSECURITY, ctx);
/* no attribute is ok, nothing to delete */
- if (error == ENOATTR)
+ if (error == ENOATTR) {
error = 0;
+ }
VFS_DEBUG(ctx, vp, "SETATTR - remove filesec returning %d", error);
} else {
/* write the EA */
}
/* if we fetched a filesec, dispose of the buffer */
- if (fsec != &lfsec)
+ if (fsec != &lfsec) {
kauth_filesec_free(fsec);
+ }
}
out:
- return(error);
+ return error;
}
/*
* event on a vnode.
*/
int
-vnode_notify(vnode_t vp, uint32_t events, struct vnode_attr *vap)
+vnode_notify(vnode_t vp, uint32_t events, struct vnode_attr *vap)
{
/* These are the same as the corresponding knotes, at least for now. Cheating a little. */
- uint32_t knote_mask = (VNODE_EVENT_WRITE | VNODE_EVENT_DELETE | VNODE_EVENT_RENAME
- | VNODE_EVENT_LINK | VNODE_EVENT_EXTEND | VNODE_EVENT_ATTRIB);
- uint32_t dir_contents_mask = (VNODE_EVENT_DIR_CREATED | VNODE_EVENT_FILE_CREATED
- | VNODE_EVENT_DIR_REMOVED | VNODE_EVENT_FILE_REMOVED);
+ uint32_t knote_mask = (VNODE_EVENT_WRITE | VNODE_EVENT_DELETE | VNODE_EVENT_RENAME
+ | VNODE_EVENT_LINK | VNODE_EVENT_EXTEND | VNODE_EVENT_ATTRIB);
+ uint32_t dir_contents_mask = (VNODE_EVENT_DIR_CREATED | VNODE_EVENT_FILE_CREATED
+ | VNODE_EVENT_DIR_REMOVED | VNODE_EVENT_FILE_REMOVED);
uint32_t knote_events = (events & knote_mask);
/* Permissions are not explicitly part of the kqueue model */
if (events & VNODE_EVENT_PERMS) {
knote_events |= NOTE_ATTRIB;
- }
+ }
/* Directory contents information just becomes NOTE_WRITE */
if ((vnode_isdir(vp)) && (events & dir_contents_mask)) {
knote_events |= NOTE_WRITE;
}
-
+
if (knote_events) {
lock_vnode_and_post(vp, knote_events);
#if CONFIG_FSE
#else
(void)vap;
#endif
- }
+ }
return 0;
}
int
vnode_isdyldsharedcache(vnode_t vp)
{
- return ((vp->v_flag & VSHARED_DYLD) ? 1 : 0);
+ return (vp->v_flag & VSHARED_DYLD) ? 1 : 0;
}
* check whether a vnode is being monitored.
*/
int
-vnode_ismonitored(vnode_t vp) {
- return (vp->v_knotes.slh_first != NULL);
+vnode_ismonitored(vnode_t vp)
+{
+ return vp->v_knotes.slh_first != NULL;
+}
+
+int
+vnode_getbackingvnode(vnode_t in_vp, vnode_t* out_vpp)
+{
+ if (out_vpp) {
+ *out_vpp = NULLVP;
+ }
+#if NULLFS
+ return nullfs_getbackingvnode(in_vp, out_vpp);
+#else
+#pragma unused(in_vp)
+ return ENOENT;
+#endif
}
/*
* by the vnode_notify() call.
*/
int
-vfs_get_notify_attributes(struct vnode_attr *vap)
+vfs_get_notify_attributes(struct vnode_attr *vap)
{
- VATTR_INIT(vap);
+ VATTR_INIT(vap);
vap->va_active = VNODE_NOTIFY_ATTRS;
return 0;
}
#if CONFIG_TRIGGERS
-int
+int
vfs_settriggercallback(fsid_t *fsid, vfs_trigger_callback_t vtc, void *data, uint32_t flags __unused, vfs_context_t ctx)
{
int error;
#if 0
/*
- *#
- *#% lookup dvp L ? ?
- *#% lookup vpp - L -
- */
+*#
+*#% lookup dvp L ? ?
+*#% lookup vpp - L -
+*/
struct vnop_lookup_args {
struct vnodeop_desc *a_desc;
vnode_t a_dvp;
* be returned by HFS from hfs_lookup, not including additional
* error code which may be propagated from underlying routines.
*/
-errno_t
+errno_t
VNOP_LOOKUP(vnode_t dvp, vnode_t *vpp, struct componentname *cnp, vfs_context_t ctx)
{
int _err;
struct vnop_lookup_args a;
- vnode_t vp;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
a.a_desc = &vnop_lookup_desc;
a.a_dvp = dvp;
a.a_cnp = cnp;
a.a_context = ctx;
-#if CONFIG_VFS_FUNNEL
- thread_safe = THREAD_SAFE_FS(dvp);
- if (!thread_safe) {
- if ( (_err = lock_fsnode(dvp, &funnel_state)) ) {
- return (_err);
- }
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
_err = (*dvp->v_op[vnop_lookup_desc.vdesc_offset])(&a);
-
- vp = *vpp;
-
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- if ( (cnp->cn_flags & ISLASTCN) ) {
- if ( (cnp->cn_flags & LOCKPARENT) ) {
- if ( !(cnp->cn_flags & FSNODELOCKHELD) ) {
- /*
- * leave the fsnode lock held on
- * the directory, but restore the funnel...
- * also indicate that we need to drop the
- * fsnode_lock when we're done with the
- * system call processing for this path
- */
- cnp->cn_flags |= FSNODELOCKHELD;
-
- (void) thread_funnel_set(kernel_flock, funnel_state);
- return (_err);
- }
- }
- }
- unlock_fsnode(dvp, &funnel_state);
+ if (_err == 0 && *vpp) {
+ DTRACE_FSINFO(lookup, vnode_t, *vpp);
}
-#endif /* CONFIG_VFS_FUNNEL */
- return (_err);
+ return _err;
}
#if 0
uint32_t tmp_status = 0;
struct componentname *cnp = &ndp->ni_cnd;
- want_create = (flags & VNOP_COMPOUND_OPEN_DO_CREATE);
+ want_create = (flags & O_CREAT);
a.a_desc = &vnop_compound_open_desc;
a.a_dvp = dvp;
}
_err = (*dvp->v_op[vnop_compound_open_desc.vdesc_offset])(&a);
+ if (want_create) {
+ if (_err == 0 && *vpp) {
+ DTRACE_FSINFO(compound_open, vnode_t, *vpp);
+ } else {
+ DTRACE_FSINFO(compound_open, vnode_t, dvp);
+ }
+ } else {
+ DTRACE_FSINFO(compound_open, vnode_t, *vpp);
+ }
did_create = (*a.a_status & COMPOUND_OPEN_STATUS_DID_CREATE);
panic("Filesystem did a create, even though none was requested?");
}
- if (did_create) {
+ if (did_create) {
+#if CONFIG_APPLEDOUBLE
if (!NATIVE_XATTR(dvp)) {
- /*
+ /*
* Remove stale Apple Double file (if any).
*/
xattrfile_remove(dvp, cnp->cn_nameptr, ctx, 0);
}
-
+#endif /* CONFIG_APPLEDOUBLE */
/* On create, provide kqueue notification */
post_event_if_success(dvp, _err, NOTE_WRITE);
}
}
#endif /* 0 */
- return (_err);
-
+ return _err;
}
#if 0
vfs_context_t a_context;
};
#endif /* 0*/
-errno_t
+errno_t
VNOP_CREATE(vnode_t dvp, vnode_t * vpp, struct componentname * cnp, struct vnode_attr * vap, vfs_context_t ctx)
{
int _err;
struct vnop_create_args a;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
a.a_desc = &vnop_create_desc;
a.a_dvp = dvp;
a.a_vap = vap;
a.a_context = ctx;
-#if CONFIG_VFS_FUNNEL
- thread_safe = THREAD_SAFE_FS(dvp);
- if (!thread_safe) {
- if ( (_err = lock_fsnode(dvp, &funnel_state)) ) {
- return (_err);
- }
+ _err = (*dvp->v_op[vnop_create_desc.vdesc_offset])(&a);
+ if (_err == 0 && *vpp) {
+ DTRACE_FSINFO(create, vnode_t, *vpp);
}
-#endif /* CONFIG_VFS_FUNNEL */
- _err = (*dvp->v_op[vnop_create_desc.vdesc_offset])(&a);
+#if CONFIG_APPLEDOUBLE
if (_err == 0 && !NATIVE_XATTR(dvp)) {
- /*
+ /*
* Remove stale Apple Double file (if any).
*/
xattrfile_remove(dvp, cnp->cn_nameptr, ctx, 0);
}
-
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- unlock_fsnode(dvp, &funnel_state);
- }
-#endif /* CONFIG_VFS_FUNNEL */
+#endif /* CONFIG_APPLEDOUBLE */
post_event_if_success(dvp, _err, NOTE_WRITE);
- return (_err);
+ return _err;
}
#if 0
/*
- *#
- *#% whiteout dvp L L L
- *#% whiteout cnp - - -
- *#% whiteout flag - - -
- *#
- */
+*#
+*#% whiteout dvp L L L
+*#% whiteout cnp - - -
+*#% whiteout flag - - -
+*#
+*/
struct vnop_whiteout_args {
struct vnodeop_desc *a_desc;
vnode_t a_dvp;
vfs_context_t a_context;
};
#endif /* 0*/
-errno_t
-VNOP_WHITEOUT(vnode_t dvp, struct componentname * cnp, int flags, vfs_context_t ctx)
+errno_t
+VNOP_WHITEOUT(__unused vnode_t dvp, __unused struct componentname *cnp,
+ __unused int flags, __unused vfs_context_t ctx)
{
- int _err;
- struct vnop_whiteout_args a;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
-
- a.a_desc = &vnop_whiteout_desc;
- a.a_dvp = dvp;
- a.a_cnp = cnp;
- a.a_flags = flags;
- a.a_context = ctx;
-
-#if CONFIG_VFS_FUNNEL
- thread_safe = THREAD_SAFE_FS(dvp);
- if (!thread_safe) {
- if ( (_err = lock_fsnode(dvp, &funnel_state)) ) {
- return (_err);
- }
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
- _err = (*dvp->v_op[vnop_whiteout_desc.vdesc_offset])(&a);
-
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- unlock_fsnode(dvp, &funnel_state);
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
- post_event_if_success(dvp, _err, NOTE_WRITE);
-
- return (_err);
+ return ENOTSUP; // XXX OBSOLETE
}
- #if 0
+#if 0
/*
- *#
- *#% mknod dvp L U U
- *#% mknod vpp - X -
- *#
- */
+*#
+*#% mknod dvp L U U
+*#% mknod vpp - X -
+*#
+*/
struct vnop_mknod_args {
- struct vnodeop_desc *a_desc;
- vnode_t a_dvp;
- vnode_t *a_vpp;
- struct componentname *a_cnp;
- struct vnode_attr *a_vap;
- vfs_context_t a_context;
+ struct vnodeop_desc *a_desc;
+ vnode_t a_dvp;
+ vnode_t *a_vpp;
+ struct componentname *a_cnp;
+ struct vnode_attr *a_vap;
+ vfs_context_t a_context;
};
#endif /* 0*/
errno_t
VNOP_MKNOD(vnode_t dvp, vnode_t * vpp, struct componentname * cnp, struct vnode_attr * vap, vfs_context_t ctx)
{
+ int _err;
+ struct vnop_mknod_args a;
- int _err;
- struct vnop_mknod_args a;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
-
- a.a_desc = &vnop_mknod_desc;
- a.a_dvp = dvp;
- a.a_vpp = vpp;
- a.a_cnp = cnp;
- a.a_vap = vap;
- a.a_context = ctx;
-
-#if CONFIG_VFS_FUNNEL
- thread_safe = THREAD_SAFE_FS(dvp);
- if (!thread_safe) {
- if ( (_err = lock_fsnode(dvp, &funnel_state)) ) {
- return (_err);
- }
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
- _err = (*dvp->v_op[vnop_mknod_desc.vdesc_offset])(&a);
+ a.a_desc = &vnop_mknod_desc;
+ a.a_dvp = dvp;
+ a.a_vpp = vpp;
+ a.a_cnp = cnp;
+ a.a_vap = vap;
+ a.a_context = ctx;
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- unlock_fsnode(dvp, &funnel_state);
- }
-#endif /* CONFIG_VFS_FUNNEL */
+ _err = (*dvp->v_op[vnop_mknod_desc.vdesc_offset])(&a);
+ if (_err == 0 && *vpp) {
+ DTRACE_FSINFO(mknod, vnode_t, *vpp);
+ }
- post_event_if_success(dvp, _err, NOTE_WRITE);
+ post_event_if_success(dvp, _err, NOTE_WRITE);
- return (_err);
+ return _err;
}
#if 0
/*
- *#
- *#% open vp L L L
- *#
- */
+*#
+*#% open vp L L L
+*#
+*/
struct vnop_open_args {
struct vnodeop_desc *a_desc;
vnode_t a_vp;
vfs_context_t a_context;
};
#endif /* 0*/
-errno_t
-VNOP_OPEN(vnode_t vp, int mode, vfs_context_t ctx)
+errno_t
+VNOP_OPEN(vnode_t vp, int mode, vfs_context_t ctx)
{
int _err;
struct vnop_open_args a;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
if (ctx == NULL) {
ctx = vfs_context_current();
- }
+ }
a.a_desc = &vnop_open_desc;
a.a_vp = vp;
a.a_mode = mode;
- a.a_context = ctx;
-
-#if CONFIG_VFS_FUNNEL
- thread_safe = THREAD_SAFE_FS(vp);
- if (!thread_safe) {
- funnel_state = thread_funnel_set(kernel_flock, TRUE);
- if (vp->v_type != VCHR && vp->v_type != VFIFO && vp->v_type != VSOCK) {
- if ( (_err = lock_fsnode(vp, NULL)) ) {
- (void) thread_funnel_set(kernel_flock, funnel_state);
- return (_err);
- }
- }
- }
-#endif /* CONFIG_VFS_FUNNEL */
+ a.a_context = ctx;
_err = (*vp->v_op[vnop_open_desc.vdesc_offset])(&a);
+ DTRACE_FSINFO(open, vnode_t, vp);
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- if (vp->v_type != VCHR && vp->v_type != VFIFO && vp->v_type != VSOCK) {
- unlock_fsnode(vp, NULL);
- }
- (void) thread_funnel_set(kernel_flock, funnel_state);
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
- return (_err);
+ return _err;
}
#if 0
/*
- *#
- *#% close vp U U U
- *#
- */
+*#
+*#% close vp U U U
+*#
+*/
struct vnop_close_args {
struct vnodeop_desc *a_desc;
vnode_t a_vp;
vfs_context_t a_context;
};
#endif /* 0*/
-errno_t
+errno_t
VNOP_CLOSE(vnode_t vp, int fflag, vfs_context_t ctx)
{
int _err;
struct vnop_close_args a;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
if (ctx == NULL) {
ctx = vfs_context_current();
a.a_fflag = fflag;
a.a_context = ctx;
-#if CONFIG_VFS_FUNNEL
- thread_safe = THREAD_SAFE_FS(vp);
- if (!thread_safe) {
- funnel_state = thread_funnel_set(kernel_flock, TRUE);
- if (vp->v_type != VCHR && vp->v_type != VFIFO && vp->v_type != VSOCK) {
- if ( (_err = lock_fsnode(vp, NULL)) ) {
- (void) thread_funnel_set(kernel_flock, funnel_state);
- return (_err);
- }
- }
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
_err = (*vp->v_op[vnop_close_desc.vdesc_offset])(&a);
+ DTRACE_FSINFO(close, vnode_t, vp);
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- if (vp->v_type != VCHR && vp->v_type != VFIFO && vp->v_type != VSOCK) {
- unlock_fsnode(vp, NULL);
- }
- (void) thread_funnel_set(kernel_flock, funnel_state);
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
- return (_err);
+ return _err;
}
#if 0
/*
- *#
- *#% access vp L L L
- *#
- */
+*#
+*#% access vp L L L
+*#
+*/
struct vnop_access_args {
struct vnodeop_desc *a_desc;
vnode_t a_vp;
vfs_context_t a_context;
};
#endif /* 0*/
-errno_t
+errno_t
VNOP_ACCESS(vnode_t vp, int action, vfs_context_t ctx)
{
int _err;
struct vnop_access_args a;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
if (ctx == NULL) {
ctx = vfs_context_current();
a.a_action = action;
a.a_context = ctx;
-#if CONFIG_VFS_FUNNEL
- thread_safe = THREAD_SAFE_FS(vp);
- if (!thread_safe) {
- if ( (_err = lock_fsnode(vp, &funnel_state)) ) {
- return (_err);
- }
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
_err = (*vp->v_op[vnop_access_desc.vdesc_offset])(&a);
+ DTRACE_FSINFO(access, vnode_t, vp);
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- unlock_fsnode(vp, &funnel_state);
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
- return (_err);
+ return _err;
}
#if 0
/*
- *#
- *#% getattr vp = = =
- *#
- */
+*#
+*#% getattr vp = = =
+*#
+*/
struct vnop_getattr_args {
struct vnodeop_desc *a_desc;
vnode_t a_vp;
vfs_context_t a_context;
};
#endif /* 0*/
-errno_t
+errno_t
VNOP_GETATTR(vnode_t vp, struct vnode_attr * vap, vfs_context_t ctx)
{
int _err;
struct vnop_getattr_args a;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
a.a_desc = &vnop_getattr_desc;
a.a_vp = vp;
a.a_vap = vap;
a.a_context = ctx;
-#if CONFIG_VFS_FUNNEL
- thread_safe = THREAD_SAFE_FS(vp);
- if (!thread_safe) {
- if ( (_err = lock_fsnode(vp, &funnel_state)) ) {
- return (_err);
- }
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
_err = (*vp->v_op[vnop_getattr_desc.vdesc_offset])(&a);
+ DTRACE_FSINFO(getattr, vnode_t, vp);
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- unlock_fsnode(vp, &funnel_state);
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
- return (_err);
+ return _err;
}
#if 0
/*
- *#
- *#% setattr vp L L L
- *#
- */
+*#
+*#% setattr vp L L L
+*#
+*/
struct vnop_setattr_args {
struct vnodeop_desc *a_desc;
vnode_t a_vp;
vfs_context_t a_context;
};
#endif /* 0*/
-errno_t
+errno_t
VNOP_SETATTR(vnode_t vp, struct vnode_attr * vap, vfs_context_t ctx)
{
int _err;
struct vnop_setattr_args a;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
a.a_desc = &vnop_setattr_desc;
a.a_vp = vp;
a.a_vap = vap;
a.a_context = ctx;
-#if CONFIG_VFS_FUNNEL
- thread_safe = THREAD_SAFE_FS(vp);
- if (!thread_safe) {
- if ( (_err = lock_fsnode(vp, &funnel_state)) ) {
- return (_err);
- }
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
_err = (*vp->v_op[vnop_setattr_desc.vdesc_offset])(&a);
+ DTRACE_FSINFO(setattr, vnode_t, vp);
- /*
+#if CONFIG_APPLEDOUBLE
+ /*
* Shadow uid/gid/mod change to extended attribute file.
*/
if (_err == 0 && !NATIVE_XATTR(vp)) {
change = 1;
}
if (change) {
- vnode_t dvp;
+ vnode_t dvp;
const char *vname;
dvp = vnode_getparent(vp);
vname = vnode_getname(vp);
xattrfile_setattr(dvp, vname, &va, ctx);
- if (dvp != NULLVP)
- vnode_put(dvp);
- if (vname != NULL)
- vnode_putname(vname);
+ if (dvp != NULLVP) {
+ vnode_put(dvp);
+ }
+ if (vname != NULL) {
+ vnode_putname(vname);
+ }
}
}
-
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- unlock_fsnode(vp, &funnel_state);
- }
-#endif /* CONFIG_VFS_FUNNEL */
+#endif /* CONFIG_APPLEDOUBLE */
/*
* If we have changed any of the things about the file that are likely
* cache
*/
if (_err == 0 && (
- VATTR_IS_SUPPORTED(vap, va_mode) ||
- VATTR_IS_SUPPORTED(vap, va_uid) ||
- VATTR_IS_SUPPORTED(vap, va_gid) ||
- VATTR_IS_SUPPORTED(vap, va_flags) ||
- VATTR_IS_SUPPORTED(vap, va_acl) ||
- VATTR_IS_SUPPORTED(vap, va_uuuid) ||
- VATTR_IS_SUPPORTED(vap, va_guuid))) {
- vnode_uncache_authorized_action(vp, KAUTH_INVALIDATE_CACHED_RIGHTS);
+ VATTR_IS_SUPPORTED(vap, va_mode) ||
+ VATTR_IS_SUPPORTED(vap, va_uid) ||
+ VATTR_IS_SUPPORTED(vap, va_gid) ||
+ VATTR_IS_SUPPORTED(vap, va_flags) ||
+ VATTR_IS_SUPPORTED(vap, va_acl) ||
+ VATTR_IS_SUPPORTED(vap, va_uuuid) ||
+ VATTR_IS_SUPPORTED(vap, va_guuid))) {
+ vnode_uncache_authorized_action(vp, KAUTH_INVALIDATE_CACHED_RIGHTS);
#if NAMEDSTREAMS
if (vfs_authopaque(vp->v_mount) && vnode_hasnamedstreams(vp)) {
if (vnode_getnamedstream(vp, &svp, XATTR_RESOURCEFORK_NAME, NS_OPEN, 0, ctx) == 0) {
vnode_uncache_authorized_action(svp, KAUTH_INVALIDATE_CACHED_RIGHTS);
vnode_put(svp);
- }
- }
+ }
+ }
#endif /* NAMEDSTREAMS */
}
post_event_if_success(vp, _err, NOTE_ATTRIB);
- return (_err);
+ return _err;
}
#if 0
/*
- *#
- *#% read vp L L L
- *#
- */
+*#
+*#% read vp L L L
+*#
+*/
struct vnop_read_args {
struct vnodeop_desc *a_desc;
vnode_t a_vp;
vfs_context_t a_context;
};
#endif /* 0*/
-errno_t
+errno_t
VNOP_READ(vnode_t vp, struct uio * uio, int ioflag, vfs_context_t ctx)
{
int _err;
struct vnop_read_args a;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
+#if CONFIG_DTRACE
+ user_ssize_t resid = uio_resid(uio);
+#endif
if (ctx == NULL) {
- ctx = vfs_context_current();
+ return EINVAL;
}
a.a_desc = &vnop_read_desc;
a.a_ioflag = ioflag;
a.a_context = ctx;
-#if CONFIG_VFS_FUNNEL
- thread_safe = THREAD_SAFE_FS(vp);
- if (!thread_safe) {
- funnel_state = thread_funnel_set(kernel_flock, TRUE);
- if (vp->v_type != VCHR && vp->v_type != VFIFO && vp->v_type != VSOCK) {
- if ( (_err = lock_fsnode(vp, NULL)) ) {
- (void) thread_funnel_set(kernel_flock, funnel_state);
- return (_err);
- }
- }
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
_err = (*vp->v_op[vnop_read_desc.vdesc_offset])(&a);
+ DTRACE_FSINFO_IO(read,
+ vnode_t, vp, user_ssize_t, (resid - uio_resid(uio)));
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- if (vp->v_type != VCHR && vp->v_type != VFIFO && vp->v_type != VSOCK) {
- unlock_fsnode(vp, NULL);
- }
- (void) thread_funnel_set(kernel_flock, funnel_state);
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
- return (_err);
+ return _err;
}
#if 0
/*
- *#
- *#% write vp L L L
- *#
- */
+*#
+*#% write vp L L L
+*#
+*/
struct vnop_write_args {
struct vnodeop_desc *a_desc;
vnode_t a_vp;
vfs_context_t a_context;
};
#endif /* 0*/
-errno_t
+errno_t
VNOP_WRITE(vnode_t vp, struct uio * uio, int ioflag, vfs_context_t ctx)
{
struct vnop_write_args a;
int _err;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
+#if CONFIG_DTRACE
+ user_ssize_t resid = uio_resid(uio);
+#endif
if (ctx == NULL) {
- ctx = vfs_context_current();
+ return EINVAL;
}
a.a_desc = &vnop_write_desc;
a.a_ioflag = ioflag;
a.a_context = ctx;
-#if CONFIG_VFS_FUNNEL
- thread_safe = THREAD_SAFE_FS(vp);
- if (!thread_safe) {
- funnel_state = thread_funnel_set(kernel_flock, TRUE);
- if (vp->v_type != VCHR && vp->v_type != VFIFO && vp->v_type != VSOCK) {
- if ( (_err = lock_fsnode(vp, NULL)) ) {
- (void) thread_funnel_set(kernel_flock, funnel_state);
- return (_err);
- }
- }
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
_err = (*vp->v_op[vnop_write_desc.vdesc_offset])(&a);
-
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- if (vp->v_type != VCHR && vp->v_type != VFIFO && vp->v_type != VSOCK) {
- unlock_fsnode(vp, NULL);
- }
- (void) thread_funnel_set(kernel_flock, funnel_state);
- }
-#endif /* CONFIG_VFS_FUNNEL */
+ DTRACE_FSINFO_IO(write,
+ vnode_t, vp, user_ssize_t, (resid - uio_resid(uio)));
post_event_if_success(vp, _err, NOTE_WRITE);
- return (_err);
+ return _err;
}
#if 0
/*
- *#
- *#% ioctl vp U U U
- *#
- */
+*#
+*#% ioctl vp U U U
+*#
+*/
struct vnop_ioctl_args {
struct vnodeop_desc *a_desc;
vnode_t a_vp;
vfs_context_t a_context;
};
#endif /* 0*/
-errno_t
+errno_t
VNOP_IOCTL(vnode_t vp, u_long command, caddr_t data, int fflag, vfs_context_t ctx)
{
int _err;
struct vnop_ioctl_args a;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
if (ctx == NULL) {
ctx = vfs_context_current();
* We have to be able to use the root filesystem's device vnode even when
* devfs isn't mounted (yet/anymore), so we can't go looking at its mount
* structure. If there is no data pointer, it doesn't matter whether
- * the device is 64-bit ready. Any command (like DKIOCSYNCHRONIZECACHE)
+ * the device is 64-bit ready. Any command (like DKIOCSYNCHRONIZE)
* which passes NULL for its data pointer can therefore be used during
* mount or unmount of the root filesystem.
*
*/
if (vfs_context_is64bit(ctx) && !(vnode_ischr(vp) || vnode_isblk(vp))) {
if (data != NULL && !vnode_vfs64bitready(vp)) {
- return(ENOTTY);
+ return ENOTTY;
}
}
+ if ((command == DKIOCISSOLIDSTATE) && (vp == rootvp) && rootvp_is_ssd && data) {
+ *data = 1;
+ return 0;
+ }
+
a.a_desc = &vnop_ioctl_desc;
a.a_vp = vp;
a.a_command = command;
a.a_data = data;
a.a_fflag = fflag;
- a.a_context= ctx;
-
-#if CONFIG_VFS_FUNNEL
- thread_safe = THREAD_SAFE_FS(vp);
- if (!thread_safe) {
- funnel_state = thread_funnel_set(kernel_flock, TRUE);
- if (vp->v_type != VCHR && vp->v_type != VFIFO && vp->v_type != VSOCK) {
- if ( (_err = lock_fsnode(vp, NULL)) ) {
- (void) thread_funnel_set(kernel_flock, funnel_state);
- return (_err);
- }
- }
- }
-#endif /* CONFIG_VFS_FUNNEL */
+ a.a_context = ctx;
_err = (*vp->v_op[vnop_ioctl_desc.vdesc_offset])(&a);
+ DTRACE_FSINFO(ioctl, vnode_t, vp);
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- if (vp->v_type != VCHR && vp->v_type != VFIFO && vp->v_type != VSOCK) {
- unlock_fsnode(vp, NULL);
- }
- (void) thread_funnel_set(kernel_flock, funnel_state);
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
- return (_err);
+ return _err;
}
#if 0
/*
- *#
- *#% select vp U U U
- *#
- */
+*#
+*#% select vp U U U
+*#
+*/
struct vnop_select_args {
struct vnodeop_desc *a_desc;
vnode_t a_vp;
vfs_context_t a_context;
};
#endif /* 0*/
-errno_t
-VNOP_SELECT(vnode_t vp, int which , int fflags, void * wql, vfs_context_t ctx)
+errno_t
+VNOP_SELECT(vnode_t vp, int which, int fflags, void * wql, vfs_context_t ctx)
{
int _err;
struct vnop_select_args a;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
if (ctx == NULL) {
ctx = vfs_context_current();
a.a_context = ctx;
a.a_wql = wql;
-#if CONFIG_VFS_FUNNEL
- thread_safe = THREAD_SAFE_FS(vp);
- if (!thread_safe) {
- funnel_state = thread_funnel_set(kernel_flock, TRUE);
- if (vp->v_type != VCHR && vp->v_type != VFIFO && vp->v_type != VSOCK) {
- if ( (_err = lock_fsnode(vp, NULL)) ) {
- (void) thread_funnel_set(kernel_flock, funnel_state);
- return (_err);
- }
- }
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
_err = (*vp->v_op[vnop_select_desc.vdesc_offset])(&a);
+ DTRACE_FSINFO(select, vnode_t, vp);
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- if (vp->v_type != VCHR && vp->v_type != VFIFO && vp->v_type != VSOCK) {
- unlock_fsnode(vp, NULL);
- }
- (void) thread_funnel_set(kernel_flock, funnel_state);
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
- return (_err);
+ return _err;
}
#if 0
/*
- *#
- *#% exchange fvp L L L
- *#% exchange tvp L L L
- *#
- */
+*#
+*#% exchange fvp L L L
+*#% exchange tvp L L L
+*#
+*/
struct vnop_exchange_args {
struct vnodeop_desc *a_desc;
vnode_t a_fvp;
- vnode_t a_tvp;
- int a_options;
+ vnode_t a_tvp;
+ int a_options;
vfs_context_t a_context;
};
#endif /* 0*/
-errno_t
+errno_t
VNOP_EXCHANGE(vnode_t fvp, vnode_t tvp, int options, vfs_context_t ctx)
{
int _err;
struct vnop_exchange_args a;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
- vnode_t lock_first = NULL, lock_second = NULL;
-#endif /* CONFIG_VFS_FUNNEL */
a.a_desc = &vnop_exchange_desc;
a.a_fvp = fvp;
a.a_options = options;
a.a_context = ctx;
-#if CONFIG_VFS_FUNNEL
- thread_safe = THREAD_SAFE_FS(fvp);
- if (!thread_safe) {
- /*
- * Lock in vnode address order to avoid deadlocks
- */
- if (fvp < tvp) {
- lock_first = fvp;
- lock_second = tvp;
- } else {
- lock_first = tvp;
- lock_second = fvp;
- }
- if ( (_err = lock_fsnode(lock_first, &funnel_state)) ) {
- return (_err);
- }
- if ( (_err = lock_fsnode(lock_second, NULL)) ) {
- unlock_fsnode(lock_first, &funnel_state);
- return (_err);
- }
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
_err = (*fvp->v_op[vnop_exchange_desc.vdesc_offset])(&a);
-
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- unlock_fsnode(lock_second, NULL);
- unlock_fsnode(lock_first, &funnel_state);
- }
-#endif /* CONFIG_VFS_FUNNEL */
+ DTRACE_FSINFO(exchange, vnode_t, fvp);
/* Don't post NOTE_WRITE because file descriptors follow the data ... */
post_event_if_success(fvp, _err, NOTE_ATTRIB);
post_event_if_success(tvp, _err, NOTE_ATTRIB);
- return (_err);
+ return _err;
}
#if 0
/*
- *#
- *#% revoke vp U U U
- *#
- */
+*#
+*#% revoke vp U U U
+*#
+*/
struct vnop_revoke_args {
struct vnodeop_desc *a_desc;
vnode_t a_vp;
vfs_context_t a_context;
};
#endif /* 0*/
-errno_t
+errno_t
VNOP_REVOKE(vnode_t vp, int flags, vfs_context_t ctx)
{
struct vnop_revoke_args a;
int _err;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
a.a_desc = &vnop_revoke_desc;
a.a_vp = vp;
a.a_flags = flags;
a.a_context = ctx;
-#if CONFIG_VFS_FUNNEL
- thread_safe = THREAD_SAFE_FS(vp);
- if (!thread_safe) {
- funnel_state = thread_funnel_set(kernel_flock, TRUE);
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
_err = (*vp->v_op[vnop_revoke_desc.vdesc_offset])(&a);
+ DTRACE_FSINFO(revoke, vnode_t, vp);
+
+ return _err;
+}
+
+
+#if 0
+/*
+*#
+*# mmap_check - vp U U U
+*#
+*/
+struct vnop_mmap_check_args {
+ struct vnodeop_desc *a_desc;
+ vnode_t a_vp;
+ int a_flags;
+ vfs_context_t a_context;
+};
+#endif /* 0 */
+errno_t
+VNOP_MMAP_CHECK(vnode_t vp, int flags, vfs_context_t ctx)
+{
+ int _err;
+ struct vnop_mmap_check_args a;
+
+ a.a_desc = &vnop_mmap_check_desc;
+ a.a_vp = vp;
+ a.a_flags = flags;
+ a.a_context = ctx;
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- (void) thread_funnel_set(kernel_flock, funnel_state);
+ _err = (*vp->v_op[vnop_mmap_check_desc.vdesc_offset])(&a);
+ if (_err == ENOTSUP) {
+ _err = 0;
}
-#endif /* CONFIG_VFS_FUNNEL */
+ DTRACE_FSINFO(mmap_check, vnode_t, vp);
- return (_err);
+ return _err;
}
-
#if 0
/*
- *#
- *# mmap - vp U U U
- *#
- */
+*#
+*# mmap - vp U U U
+*#
+*/
struct vnop_mmap_args {
struct vnodeop_desc *a_desc;
vnode_t a_vp;
vfs_context_t a_context;
};
#endif /* 0*/
-errno_t
+errno_t
VNOP_MMAP(vnode_t vp, int fflags, vfs_context_t ctx)
{
int _err;
struct vnop_mmap_args a;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
a.a_desc = &vnop_mmap_desc;
a.a_vp = vp;
a.a_fflags = fflags;
a.a_context = ctx;
-#if CONFIG_VFS_FUNNEL
- thread_safe = THREAD_SAFE_FS(vp);
- if (!thread_safe) {
- if ( (_err = lock_fsnode(vp, &funnel_state)) ) {
- return (_err);
- }
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
_err = (*vp->v_op[vnop_mmap_desc.vdesc_offset])(&a);
+ DTRACE_FSINFO(mmap, vnode_t, vp);
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- unlock_fsnode(vp, &funnel_state);
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
- return (_err);
+ return _err;
}
#if 0
/*
- *#
- *# mnomap - vp U U U
- *#
- */
+*#
+*# mnomap - vp U U U
+*#
+*/
struct vnop_mnomap_args {
struct vnodeop_desc *a_desc;
vnode_t a_vp;
vfs_context_t a_context;
};
#endif /* 0*/
-errno_t
+errno_t
VNOP_MNOMAP(vnode_t vp, vfs_context_t ctx)
{
int _err;
struct vnop_mnomap_args a;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
a.a_desc = &vnop_mnomap_desc;
a.a_vp = vp;
a.a_context = ctx;
-#if CONFIG_VFS_FUNNEL
- thread_safe = THREAD_SAFE_FS(vp);
- if (!thread_safe) {
- if ( (_err = lock_fsnode(vp, &funnel_state)) ) {
- return (_err);
- }
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
_err = (*vp->v_op[vnop_mnomap_desc.vdesc_offset])(&a);
+ DTRACE_FSINFO(mnomap, vnode_t, vp);
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- unlock_fsnode(vp, &funnel_state);
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
- return (_err);
+ return _err;
}
#if 0
/*
- *#
- *#% fsync vp L L L
- *#
- */
+*#
+*#% fsync vp L L L
+*#
+*/
struct vnop_fsync_args {
struct vnodeop_desc *a_desc;
vnode_t a_vp;
vfs_context_t a_context;
};
#endif /* 0*/
-errno_t
+errno_t
VNOP_FSYNC(vnode_t vp, int waitfor, vfs_context_t ctx)
{
struct vnop_fsync_args a;
int _err;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
a.a_desc = &vnop_fsync_desc;
a.a_vp = vp;
a.a_waitfor = waitfor;
a.a_context = ctx;
-#if CONFIG_VFS_FUNNEL
- thread_safe = THREAD_SAFE_FS(vp);
- if (!thread_safe) {
- if ( (_err = lock_fsnode(vp, &funnel_state)) ) {
- return (_err);
- }
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
_err = (*vp->v_op[vnop_fsync_desc.vdesc_offset])(&a);
+ DTRACE_FSINFO(fsync, vnode_t, vp);
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- unlock_fsnode(vp, &funnel_state);
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
- return (_err);
+ return _err;
}
#if 0
/*
- *#
- *#% remove dvp L U U
- *#% remove vp L U U
- *#
- */
+*#
+*#% remove dvp L U U
+*#% remove vp L U U
+*#
+*/
struct vnop_remove_args {
struct vnodeop_desc *a_desc;
vnode_t a_dvp;
vfs_context_t a_context;
};
#endif /* 0*/
-errno_t
+errno_t
VNOP_REMOVE(vnode_t dvp, vnode_t vp, struct componentname * cnp, int flags, vfs_context_t ctx)
{
int _err;
struct vnop_remove_args a;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
a.a_desc = &vnop_remove_desc;
a.a_dvp = dvp;
a.a_flags = flags;
a.a_context = ctx;
-#if CONFIG_VFS_FUNNEL
- thread_safe = THREAD_SAFE_FS(dvp);
- if (!thread_safe) {
- if ( (_err = lock_fsnode(vp, &funnel_state)) ) {
- return (_err);
- }
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
_err = (*dvp->v_op[vnop_remove_desc.vdesc_offset])(&a);
+ DTRACE_FSINFO(remove, vnode_t, vp);
if (_err == 0) {
- vnode_setneedinactive(vp);
-
- if ( !(NATIVE_XATTR(dvp)) ) {
- /*
+ vnode_setneedinactive(vp);
+#if CONFIG_APPLEDOUBLE
+ if (!(NATIVE_XATTR(dvp))) {
+ /*
* Remove any associated extended attribute file (._ AppleDouble file).
*/
- xattrfile_remove(dvp, cnp->cn_nameptr, ctx, 1);
+ xattrfile_remove(dvp, cnp->cn_nameptr, ctx, 1);
}
+#endif /* CONFIG_APPLEDOUBLE */
}
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- unlock_fsnode(vp, &funnel_state);
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
post_event_if_success(vp, _err, NOTE_DELETE | NOTE_LINK);
post_event_if_success(dvp, _err, NOTE_WRITE);
-
- return (_err);
+
+ return _err;
}
int
a.a_remove_authorizer = vn_authorize_unlink;
_err = (*dvp->v_op[vnop_compound_remove_desc.vdesc_offset])(&a);
+ if (_err == 0 && *vpp) {
+ DTRACE_FSINFO(compound_remove, vnode_t, *vpp);
+ } else {
+ DTRACE_FSINFO(compound_remove, vnode_t, dvp);
+ }
if (_err == 0) {
- vnode_setneedinactive(*vpp);
-
- if ( !(NATIVE_XATTR(dvp)) ) {
- /*
+ vnode_setneedinactive(*vpp);
+#if CONFIG_APPLEDOUBLE
+ if (!(NATIVE_XATTR(dvp))) {
+ /*
* Remove any associated extended attribute file (._ AppleDouble file).
*/
- xattrfile_remove(dvp, ndp->ni_cnd.cn_nameptr, ctx, 1);
+ xattrfile_remove(dvp, ndp->ni_cnd.cn_nameptr, ctx, 1);
}
+#endif /* CONFIG_APPLEDOUBLE */
}
post_event_if_success(*vpp, _err, NOTE_DELETE | NOTE_LINK);
//printf("VNOP_COMPOUND_REMOVE() returning %d\n", _err);
- return (_err);
+ return _err;
}
#if 0
/*
- *#
- *#% link vp U U U
- *#% link tdvp L U U
- *#
- */
+*#
+*#% link vp U U U
+*#% link tdvp L U U
+*#
+*/
struct vnop_link_args {
struct vnodeop_desc *a_desc;
vnode_t a_vp;
vfs_context_t a_context;
};
#endif /* 0*/
-errno_t
+errno_t
VNOP_LINK(vnode_t vp, vnode_t tdvp, struct componentname * cnp, vfs_context_t ctx)
{
int _err;
struct vnop_link_args a;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
+#if CONFIG_APPLEDOUBLE
/*
* For file systems with non-native extended attributes,
* disallow linking to an existing "._" Apple Double file.
*/
- if ( !NATIVE_XATTR(tdvp) && (vp->v_type == VREG)) {
+ if (!NATIVE_XATTR(tdvp) && (vp->v_type == VREG)) {
const char *vname;
vname = vnode_getname(vp);
_err = EPERM;
}
vnode_putname(vname);
- if (_err)
- return (_err);
+ if (_err) {
+ return _err;
+ }
}
}
+#endif /* CONFIG_APPLEDOUBLE */
+
a.a_desc = &vnop_link_desc;
a.a_vp = vp;
a.a_tdvp = tdvp;
a.a_cnp = cnp;
a.a_context = ctx;
-#if CONFIG_VFS_FUNNEL
- thread_safe = THREAD_SAFE_FS(vp);
- if (!thread_safe) {
- if ( (_err = lock_fsnode(vp, &funnel_state)) ) {
- return (_err);
- }
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
_err = (*tdvp->v_op[vnop_link_desc.vdesc_offset])(&a);
-
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- unlock_fsnode(vp, &funnel_state);
- }
-#endif /* CONFIG_VFS_FUNNEL */
+ DTRACE_FSINFO(link, vnode_t, vp);
post_event_if_success(vp, _err, NOTE_LINK);
post_event_if_success(tdvp, _err, NOTE_WRITE);
- return (_err);
+ return _err;
}
errno_t
vn_rename(struct vnode *fdvp, struct vnode **fvpp, struct componentname *fcnp, struct vnode_attr *fvap,
- struct vnode *tdvp, struct vnode **tvpp, struct componentname *tcnp, struct vnode_attr *tvap,
- uint32_t flags, vfs_context_t ctx)
+ struct vnode *tdvp, struct vnode **tvpp, struct componentname *tcnp, struct vnode_attr *tvap,
+ vfs_rename_flags_t flags, vfs_context_t ctx)
{
int _err;
- vnode_t src_attr_vp = NULLVP;
- vnode_t dst_attr_vp = NULLVP;
struct nameidata *fromnd = NULL;
struct nameidata *tond = NULL;
+#if CONFIG_APPLEDOUBLE
+ vnode_t src_attr_vp = NULLVP;
+ vnode_t dst_attr_vp = NULLVP;
char smallname1[48];
char smallname2[48];
char *xfromname = NULL;
char *xtoname = NULL;
+#endif /* CONFIG_APPLEDOUBLE */
int batched;
+ uint32_t tdfflags; // Target directory file flags
batched = vnode_compound_rename_available(fdvp);
-#if CONFIG_VFS_FUNNEL
- vnode_t fdvp_unsafe = (THREAD_SAFE_FS(fdvp) ? NULLVP : fdvp);
-#endif /* CONFIG_VFS_FUNNEL */
-
if (!batched) {
- if (*fvpp == NULLVP)
+ if (*fvpp == NULLVP) {
panic("Not batched, and no fvp?");
+ }
}
- /*
+#if CONFIG_APPLEDOUBLE
+ /*
* We need to preflight any potential AppleDouble file for the source file
* before doing the rename operation, since we could potentially be doing
* this operation on a network filesystem, and would end up duplicating
* the work. Also, save the source and destination names. Skip it if the
* source has a "._" prefix.
*/
-
+
+ size_t xfromname_len = 0;
+ size_t xtoname_len = 0;
if (!NATIVE_XATTR(fdvp) &&
!(fcnp->cn_nameptr[0] == '.' && fcnp->cn_nameptr[1] == '_')) {
- size_t len;
int error;
/* Get source attribute file name. */
- len = fcnp->cn_namelen + 3;
- if (len > sizeof(smallname1)) {
- MALLOC(xfromname, char *, len, M_TEMP, M_WAITOK);
+ xfromname_len = fcnp->cn_namelen + 3;
+ if (xfromname_len > sizeof(smallname1)) {
+ xfromname = kheap_alloc(KHEAP_TEMP, xfromname_len, Z_WAITOK);
} else {
xfromname = &smallname1[0];
}
- strlcpy(xfromname, "._", min(sizeof smallname1, len));
- strncat(xfromname, fcnp->cn_nameptr, fcnp->cn_namelen);
- xfromname[len-1] = '\0';
+ strlcpy(xfromname, "._", xfromname_len);
+ strlcat(xfromname, fcnp->cn_nameptr, xfromname_len);
/* Get destination attribute file name. */
- len = tcnp->cn_namelen + 3;
- if (len > sizeof(smallname2)) {
- MALLOC(xtoname, char *, len, M_TEMP, M_WAITOK);
+ xtoname_len = tcnp->cn_namelen + 3;
+ if (xtoname_len > sizeof(smallname2)) {
+ xtoname = kheap_alloc(KHEAP_TEMP, xtoname_len, Z_WAITOK);
} else {
xtoname = &smallname2[0];
}
- strlcpy(xtoname, "._", min(sizeof smallname2, len));
- strncat(xtoname, tcnp->cn_nameptr, tcnp->cn_namelen);
- xtoname[len-1] = '\0';
-
- /*
+ strlcpy(xtoname, "._", xtoname_len);
+ strlcat(xtoname, tcnp->cn_nameptr, xtoname_len);
+
+ /*
* Look up source attribute file, keep reference on it if exists.
* Note that we do the namei with the nameiop of RENAME, which is different than
* in the rename syscall. It's OK if the source file does not exist, since this
* is only for AppleDouble files.
*/
- if (xfromname != NULL) {
- MALLOC(fromnd, struct nameidata *, sizeof (struct nameidata), M_TEMP, M_WAITOK);
- NDINIT(fromnd, RENAME, OP_RENAME, NOFOLLOW | USEDVP | CN_NBMOUNTLOOK,
- UIO_SYSSPACE, CAST_USER_ADDR_T(xfromname), ctx);
- fromnd->ni_dvp = fdvp;
- error = namei(fromnd);
-
- /*
- * If there was an error looking up source attribute file,
- * we'll behave as if it didn't exist.
- */
+ fromnd = kheap_alloc(KHEAP_TEMP, sizeof(struct nameidata), Z_WAITOK);
+ NDINIT(fromnd, RENAME, OP_RENAME, NOFOLLOW | USEDVP | CN_NBMOUNTLOOK,
+ UIO_SYSSPACE, CAST_USER_ADDR_T(xfromname), ctx);
+ fromnd->ni_dvp = fdvp;
+ error = namei(fromnd);
- if (error == 0) {
- if (fromnd->ni_vp) {
- /* src_attr_vp indicates need to call vnode_put / nameidone later */
- src_attr_vp = fromnd->ni_vp;
-
- if (fromnd->ni_vp->v_type != VREG) {
- src_attr_vp = NULLVP;
- vnode_put(fromnd->ni_vp);
- }
- }
- /*
- * Either we got an invalid vnode type (not a regular file) or the namei lookup
- * suppressed ENOENT as a valid error since we're renaming. Either way, we don't
- * have a vnode here, so we drop our namei buffer for the source attribute file
- */
- if (src_attr_vp == NULLVP) {
- nameidone(fromnd);
+ /*
+ * If there was an error looking up source attribute file,
+ * we'll behave as if it didn't exist.
+ */
+
+ if (error == 0) {
+ if (fromnd->ni_vp) {
+ /* src_attr_vp indicates need to call vnode_put / nameidone later */
+ src_attr_vp = fromnd->ni_vp;
+
+ if (fromnd->ni_vp->v_type != VREG) {
+ src_attr_vp = NULLVP;
+ vnode_put(fromnd->ni_vp);
}
}
+ /*
+ * Either we got an invalid vnode type (not a regular file) or the namei lookup
+ * suppressed ENOENT as a valid error since we're renaming. Either way, we don't
+ * have a vnode here, so we drop our namei buffer for the source attribute file
+ */
+ if (src_attr_vp == NULLVP) {
+ nameidone(fromnd);
+ }
}
}
+#endif /* CONFIG_APPLEDOUBLE */
if (batched) {
_err = VNOP_COMPOUND_RENAME(fdvp, fvpp, fcnp, fvap, tdvp, tvpp, tcnp, tvap, flags, ctx);
if (_err != 0) {
printf("VNOP_COMPOUND_RENAME() returned %d\n", _err);
}
-
} else {
- _err = VNOP_RENAME(fdvp, *fvpp, fcnp, tdvp, *tvpp, tcnp, ctx);
+ if (flags) {
+ _err = VNOP_RENAMEX(fdvp, *fvpp, fcnp, tdvp, *tvpp, tcnp, flags, ctx);
+ if (_err == ENOTSUP && flags == VFS_RENAME_SECLUDE) {
+ // Legacy...
+ if ((*fvpp)->v_mount->mnt_vtable->vfc_vfsflags & VFC_VFSVNOP_SECLUDE_RENAME) {
+ fcnp->cn_flags |= CN_SECLUDE_RENAME;
+ _err = VNOP_RENAME(fdvp, *fvpp, fcnp, tdvp, *tvpp, tcnp, ctx);
+ }
+ }
+ } else {
+ _err = VNOP_RENAME(fdvp, *fvpp, fcnp, tdvp, *tvpp, tcnp, ctx);
+ }
+ }
+
+ /*
+ * If moved to a new directory that is restricted,
+ * set the restricted flag on the item moved.
+ */
+ if (_err == 0) {
+ _err = vnode_flags(tdvp, &tdfflags, ctx);
+ if (_err == 0) {
+ uint32_t inherit_flags = tdfflags & (UF_DATAVAULT | SF_RESTRICTED);
+ if (inherit_flags) {
+ uint32_t fflags;
+ _err = vnode_flags(*fvpp, &fflags, ctx);
+ if (_err == 0 && fflags != (fflags | inherit_flags)) {
+ struct vnode_attr va;
+ VATTR_INIT(&va);
+ VATTR_SET(&va, va_flags, fflags | inherit_flags);
+ _err = vnode_setattr(*fvpp, &va, ctx);
+ }
+ }
+ }
}
+#if CONFIG_MACF
if (_err == 0) {
mac_vnode_notify_rename(ctx, *fvpp, tdvp, tcnp);
+ if (flags & VFS_RENAME_SWAP) {
+ mac_vnode_notify_rename(ctx, *tvpp, fdvp, fcnp);
+ }
}
+#endif
- /*
+#if CONFIG_APPLEDOUBLE
+ /*
* Rename any associated extended attribute file (._ AppleDouble file).
*/
if (_err == 0 && !NATIVE_XATTR(fdvp) && xfromname != NULL) {
int error = 0;
-
+
/*
* Get destination attribute file vnode.
* Note that tdvp already has an iocount reference. Make sure to check that we
* get a valid vnode from namei.
*/
- MALLOC(tond, struct nameidata *, sizeof(struct nameidata), M_TEMP, M_WAITOK);
+ tond = kheap_alloc(KHEAP_TEMP, sizeof(struct nameidata), Z_WAITOK);
NDINIT(tond, RENAME, OP_RENAME,
- NOCACHE | NOFOLLOW | USEDVP | CN_NBMOUNTLOOK, UIO_SYSSPACE,
- CAST_USER_ADDR_T(xtoname), ctx);
+ NOCACHE | NOFOLLOW | USEDVP | CN_NBMOUNTLOOK, UIO_SYSSPACE,
+ CAST_USER_ADDR_T(xtoname), ctx);
tond->ni_dvp = tdvp;
error = namei(tond);
- if (error)
- goto out;
-
+ if (error) {
+ goto ad_error;
+ }
+
if (tond->ni_vp) {
dst_attr_vp = tond->ni_vp;
}
-
+
if (src_attr_vp) {
const char *old_name = src_attr_vp->v_name;
vnode_t old_parent = src_attr_vp->v_parent;
-
+
if (batched) {
error = VNOP_COMPOUND_RENAME(fdvp, &src_attr_vp, &fromnd->ni_cnd, NULL,
- tdvp, &dst_attr_vp, &tond->ni_cnd, NULL,
- 0, ctx);
+ tdvp, &dst_attr_vp, &tond->ni_cnd, NULL,
+ 0, ctx);
} else {
- error = VNOP_RENAME(fdvp, src_attr_vp, &fromnd->ni_cnd,
- tdvp, dst_attr_vp, &tond->ni_cnd, ctx);
+ error = VNOP_RENAME(fdvp, src_attr_vp, &fromnd->ni_cnd,
+ tdvp, dst_attr_vp, &tond->ni_cnd, ctx);
}
if (error == 0 && old_name == src_attr_vp->v_name &&
- old_parent == src_attr_vp->v_parent) {
+ old_parent == src_attr_vp->v_parent) {
int update_flags = VNODE_UPDATE_NAME;
-
- if (fdvp != tdvp)
+
+ if (fdvp != tdvp) {
update_flags |= VNODE_UPDATE_PARENT;
-
- vnode_update_identity(src_attr_vp, tdvp,
- tond->ni_cnd.cn_nameptr,
- tond->ni_cnd.cn_namelen,
- tond->ni_cnd.cn_hash,
- update_flags);
+ }
+
+ if ((src_attr_vp->v_mount->mnt_vtable->vfc_vfsflags & VFC_VFSVNOP_NOUPDATEID_RENAME) == 0) {
+ vnode_update_identity(src_attr_vp, tdvp,
+ tond->ni_cnd.cn_nameptr,
+ tond->ni_cnd.cn_namelen,
+ tond->ni_cnd.cn_hash,
+ update_flags);
+ }
}
-
- /* kevent notifications for moving resource files
+
+ /* kevent notifications for moving resource files
* _err is zero if we're here, so no need to notify directories, code
* below will do that. only need to post the rename on the source and
* possibly a delete on the dest
*/
post_event_if_success(src_attr_vp, error, NOTE_RENAME);
if (dst_attr_vp) {
- post_event_if_success(dst_attr_vp, error, NOTE_DELETE);
+ post_event_if_success(dst_attr_vp, error, NOTE_DELETE);
}
-
} else if (dst_attr_vp) {
/*
* Just delete destination attribute file vnode if it exists, since
*/
struct vnop_remove_args args;
-
+
args.a_desc = &vnop_remove_desc;
args.a_dvp = tdvp;
args.a_vp = dst_attr_vp;
args.a_cnp = &tond->ni_cnd;
args.a_context = ctx;
-#if CONFIG_VFS_FUNNEL
- if (fdvp_unsafe != NULLVP)
- error = lock_fsnode(dst_attr_vp, NULL);
-#endif /* CONFIG_VFS_FUNNEL */
if (error == 0) {
error = (*tdvp->v_op[vnop_remove_desc.vdesc_offset])(&args);
-#if CONFIG_VFS_FUNNEL
- if (fdvp_unsafe != NULLVP)
- unlock_fsnode(dst_attr_vp, NULL);
-#endif /* CONFIG_VFS_FUNNEL */
-
- if (error == 0)
+ if (error == 0) {
vnode_setneedinactive(dst_attr_vp);
+ }
}
-
+
/* kevent notification for deleting the destination's attribute file
* if it existed. Only need to post the delete on the destination, since
- * the code below will handle the directories.
+ * the code below will handle the directories.
*/
- post_event_if_success(dst_attr_vp, error, NOTE_DELETE);
+ post_event_if_success(dst_attr_vp, error, NOTE_DELETE);
}
}
-out:
+ad_error:
if (src_attr_vp) {
vnode_put(src_attr_vp);
nameidone(fromnd);
vnode_put(dst_attr_vp);
nameidone(tond);
}
- if (fromnd) {
- FREE(fromnd, M_TEMP);
- }
- if (tond) {
- FREE(tond, M_TEMP);
- }
if (xfromname && xfromname != &smallname1[0]) {
- FREE(xfromname, M_TEMP);
+ kheap_free(KHEAP_TEMP, xfromname, xfromname_len);
}
if (xtoname && xtoname != &smallname2[0]) {
- FREE(xtoname, M_TEMP);
+ kheap_free(KHEAP_TEMP, xtoname, xtoname_len);
}
-
+#endif /* CONFIG_APPLEDOUBLE */
+ kheap_free(KHEAP_TEMP, fromnd, sizeof(struct nameidata));
+ kheap_free(KHEAP_TEMP, tond, sizeof(struct nameidata));
return _err;
}
#if 0
/*
- *#
- *#% rename fdvp U U U
- *#% rename fvp U U U
- *#% rename tdvp L U U
- *#% rename tvp X U U
- *#
- */
+*#
+*#% rename fdvp U U U
+*#% rename fvp U U U
+*#% rename tdvp L U U
+*#% rename tvp X U U
+*#
+*/
struct vnop_rename_args {
struct vnodeop_desc *a_desc;
vnode_t a_fdvp;
#endif /* 0*/
errno_t
VNOP_RENAME(struct vnode *fdvp, struct vnode *fvp, struct componentname *fcnp,
- struct vnode *tdvp, struct vnode *tvp, struct componentname *tcnp,
- vfs_context_t ctx)
+ struct vnode *tdvp, struct vnode *tvp, struct componentname *tcnp,
+ vfs_context_t ctx)
{
int _err = 0;
- int events;
struct vnop_rename_args a;
-#if CONFIG_VFS_FUNNEL
- int funnel_state = 0;
- vnode_t lock_first = NULL, lock_second = NULL;
- vnode_t fdvp_unsafe = NULLVP;
- vnode_t tdvp_unsafe = NULLVP;
-#endif /* CONFIG_VFS_FUNNEL */
a.a_desc = &vnop_rename_desc;
a.a_fdvp = fdvp;
a.a_tcnp = tcnp;
a.a_context = ctx;
-#if CONFIG_VFS_FUNNEL
- if (!THREAD_SAFE_FS(fdvp))
- fdvp_unsafe = fdvp;
- if (!THREAD_SAFE_FS(tdvp))
- tdvp_unsafe = tdvp;
+ /* do the rename of the main file. */
+ _err = (*fdvp->v_op[vnop_rename_desc.vdesc_offset])(&a);
+ DTRACE_FSINFO(rename, vnode_t, fdvp);
- if (fdvp_unsafe != NULLVP) {
- /*
- * Lock parents in vnode address order to avoid deadlocks
- * note that it's possible for the fdvp to be unsafe,
- * but the tdvp to be safe because tvp could be a directory
- * in the root of a filesystem... in that case, tdvp is the
- * in the filesystem that this root is mounted on
- */
- if (tdvp_unsafe == NULL || fdvp_unsafe == tdvp_unsafe) {
- lock_first = fdvp_unsafe;
- lock_second = NULL;
- } else if (fdvp_unsafe < tdvp_unsafe) {
- lock_first = fdvp_unsafe;
- lock_second = tdvp_unsafe;
- } else {
- lock_first = tdvp_unsafe;
- lock_second = fdvp_unsafe;
- }
- if ( (_err = lock_fsnode(lock_first, &funnel_state)) )
- return (_err);
+ if (_err) {
+ return _err;
+ }
- if (lock_second != NULL && (_err = lock_fsnode(lock_second, NULL))) {
- unlock_fsnode(lock_first, &funnel_state);
- return (_err);
- }
+ return post_rename(fdvp, fvp, tdvp, tvp);
+}
- /*
- * Lock both children in vnode address order to avoid deadlocks
- */
- if (tvp == NULL || tvp == fvp) {
- lock_first = fvp;
- lock_second = NULL;
- } else if (fvp < tvp) {
- lock_first = fvp;
- lock_second = tvp;
- } else {
- lock_first = tvp;
- lock_second = fvp;
- }
- if ( (_err = lock_fsnode(lock_first, NULL)) )
- goto out1;
+static errno_t
+post_rename(vnode_t fdvp, vnode_t fvp, vnode_t tdvp, vnode_t tvp)
+{
+ if (tvp && tvp != fvp) {
+ vnode_setneedinactive(tvp);
+ }
- if (lock_second != NULL && (_err = lock_fsnode(lock_second, NULL))) {
- unlock_fsnode(lock_first, NULL);
- goto out1;
+ /* Wrote at least one directory. If transplanted a dir, also changed link counts */
+ int events = NOTE_WRITE;
+ if (vnode_isdir(fvp)) {
+ /* Link count on dir changed only if we are moving a dir and...
+ * --Moved to new dir, not overwriting there
+ * --Kept in same dir and DID overwrite
+ */
+ if (((fdvp != tdvp) && (!tvp)) || ((fdvp == tdvp) && (tvp))) {
+ events |= NOTE_LINK;
}
}
-#endif /* CONFIG_VFS_FUNNEL */
-
- /* do the rename of the main file. */
- _err = (*fdvp->v_op[vnop_rename_desc.vdesc_offset])(&a);
-#if CONFIG_VFS_FUNNEL
- if (fdvp_unsafe != NULLVP) {
- if (lock_second != NULL)
- unlock_fsnode(lock_second, NULL);
- unlock_fsnode(lock_first, NULL);
+ lock_vnode_and_post(fdvp, events);
+ if (fdvp != tdvp) {
+ lock_vnode_and_post(tdvp, events);
}
-#endif /* CONFIG_VFS_FUNNEL */
- if (_err == 0) {
- if (tvp && tvp != fvp)
- vnode_setneedinactive(tvp);
+ /* If you're replacing the target, post a deletion for it */
+ if (tvp) {
+ lock_vnode_and_post(tvp, NOTE_DELETE);
}
-#if CONFIG_VFS_FUNNEL
-out1:
- if (fdvp_unsafe != NULLVP) {
- if (tdvp_unsafe != NULLVP)
- unlock_fsnode(tdvp_unsafe, NULL);
- unlock_fsnode(fdvp_unsafe, &funnel_state);
- }
-#endif /* CONFIG_VFS_FUNNEL */
+ lock_vnode_and_post(fvp, NOTE_RENAME);
- /* Wrote at least one directory. If transplanted a dir, also changed link counts */
- if (0 == _err) {
- events = NOTE_WRITE;
- if (vnode_isdir(fvp)) {
- /* Link count on dir changed only if we are moving a dir and...
- * --Moved to new dir, not overwriting there
- * --Kept in same dir and DID overwrite
- */
- if (((fdvp != tdvp) && (!tvp)) || ((fdvp == tdvp) && (tvp))) {
- events |= NOTE_LINK;
- }
- }
+ return 0;
+}
- lock_vnode_and_post(fdvp, events);
- if (fdvp != tdvp) {
- lock_vnode_and_post(tdvp, events);
- }
+#if 0
+/*
+*#
+*#% renamex fdvp U U U
+*#% renamex fvp U U U
+*#% renamex tdvp L U U
+*#% renamex tvp X U U
+*#
+*/
+struct vnop_renamex_args {
+ struct vnodeop_desc *a_desc;
+ vnode_t a_fdvp;
+ vnode_t a_fvp;
+ struct componentname *a_fcnp;
+ vnode_t a_tdvp;
+ vnode_t a_tvp;
+ struct componentname *a_tcnp;
+ vfs_rename_flags_t a_flags;
+ vfs_context_t a_context;
+};
+#endif /* 0*/
+errno_t
+VNOP_RENAMEX(struct vnode *fdvp, struct vnode *fvp, struct componentname *fcnp,
+ struct vnode *tdvp, struct vnode *tvp, struct componentname *tcnp,
+ vfs_rename_flags_t flags, vfs_context_t ctx)
+{
+ int _err = 0;
+ struct vnop_renamex_args a;
- /* If you're replacing the target, post a deletion for it */
- if (tvp)
- {
- lock_vnode_and_post(tvp, NOTE_DELETE);
- }
+ a.a_desc = &vnop_renamex_desc;
+ a.a_fdvp = fdvp;
+ a.a_fvp = fvp;
+ a.a_fcnp = fcnp;
+ a.a_tdvp = tdvp;
+ a.a_tvp = tvp;
+ a.a_tcnp = tcnp;
+ a.a_flags = flags;
+ a.a_context = ctx;
- lock_vnode_and_post(fvp, NOTE_RENAME);
+ /* do the rename of the main file. */
+ _err = (*fdvp->v_op[vnop_renamex_desc.vdesc_offset])(&a);
+ DTRACE_FSINFO(renamex, vnode_t, fdvp);
+
+ if (_err) {
+ return _err;
}
- return (_err);
+ return post_rename(fdvp, fvp, tdvp, tvp);
}
+
int
-VNOP_COMPOUND_RENAME(
- struct vnode *fdvp, struct vnode **fvpp, struct componentname *fcnp, struct vnode_attr *fvap,
- struct vnode *tdvp, struct vnode **tvpp, struct componentname *tcnp, struct vnode_attr *tvap,
- uint32_t flags, vfs_context_t ctx)
+VNOP_COMPOUND_RENAME(
+ struct vnode *fdvp, struct vnode **fvpp, struct componentname *fcnp, struct vnode_attr *fvap,
+ struct vnode *tdvp, struct vnode **tvpp, struct componentname *tcnp, struct vnode_attr *tvap,
+ uint32_t flags, vfs_context_t ctx)
{
int _err = 0;
int events;
no_tvp = (*tvpp) == NULLVP;
a.a_desc = &vnop_compound_rename_desc;
-
+
a.a_fdvp = fdvp;
a.a_fvpp = fvpp;
a.a_fcnp = fcnp;
a.a_tvpp = tvpp;
a.a_tcnp = tcnp;
a.a_tvap = tvap;
-
+
a.a_flags = flags;
a.a_context = ctx;
a.a_rename_authorizer = vn_authorize_rename;
/* do the rename of the main file. */
_err = (*fdvp->v_op[vnop_compound_rename_desc.vdesc_offset])(&a);
+ DTRACE_FSINFO(compound_rename, vnode_t, fdvp);
if (_err == 0) {
- if (*tvpp && *tvpp != *fvpp)
- vnode_setneedinactive(*tvpp);
+ if (*tvpp && *tvpp != *fvpp) {
+ vnode_setneedinactive(*tvpp);
+ }
}
/* Wrote at least one directory. If transplanted a dir, also changed link counts */
- if (0 == _err && *fvpp != *tvpp) {
+ if (_err == 0 && *fvpp != *tvpp) {
if (!*fvpp) {
panic("No fvpp after compound rename?");
}
events = NOTE_WRITE;
if (vnode_isdir(*fvpp)) {
/* Link count on dir changed only if we are moving a dir and...
- * --Moved to new dir, not overwriting there
- * --Kept in same dir and DID overwrite
+ * --Moved to new dir, not overwriting there
+ * --Kept in same dir and DID overwrite
*/
if (((fdvp != tdvp) && (!*tvpp)) || ((fdvp == tdvp) && (*tvpp))) {
events |= NOTE_LINK;
lock_vnode_and_post(fdvp, events);
if (fdvp != tdvp) {
- lock_vnode_and_post(tdvp, events);
+ lock_vnode_and_post(tdvp, events);
}
/* If you're replacing the target, post a deletion for it */
- if (*tvpp)
- {
+ if (*tvpp) {
lock_vnode_and_post(*tvpp, NOTE_DELETE);
}
}
if (no_fvp) {
- lookup_compound_vnop_post_hook(_err, fdvp, *fvpp, fcnp->cn_ndp, 0);
+ lookup_compound_vnop_post_hook(_err, fdvp, *fvpp, fcnp->cn_ndp, 0);
}
if (no_tvp && *tvpp != NULLVP) {
lookup_compound_vnop_post_hook(_err, tdvp, *tvpp, tcnp->cn_ndp, 0);
}
}
- return (_err);
+ return _err;
}
int
vn_mkdir(struct vnode *dvp, struct vnode **vpp, struct nameidata *ndp,
- struct vnode_attr *vap, vfs_context_t ctx)
+ struct vnode_attr *vap, vfs_context_t ctx)
{
if (ndp->ni_cnd.cn_nameiop != CREATE) {
panic("Non-CREATE nameiop in vn_mkdir()?");
}
}
- #if 0
+#if 0
/*
- *#
- *#% mkdir dvp L U U
- *#% mkdir vpp - L -
- *#
- */
+*#
+*#% mkdir dvp L U U
+*#% mkdir vpp - L -
+*#
+*/
struct vnop_mkdir_args {
- struct vnodeop_desc *a_desc;
- vnode_t a_dvp;
- vnode_t *a_vpp;
- struct componentname *a_cnp;
- struct vnode_attr *a_vap;
- vfs_context_t a_context;
+ struct vnodeop_desc *a_desc;
+ vnode_t a_dvp;
+ vnode_t *a_vpp;
+ struct componentname *a_cnp;
+ struct vnode_attr *a_vap;
+ vfs_context_t a_context;
};
#endif /* 0*/
errno_t
VNOP_MKDIR(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp,
- struct vnode_attr *vap, vfs_context_t ctx)
-{
- int _err;
- struct vnop_mkdir_args a;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
-
- a.a_desc = &vnop_mkdir_desc;
- a.a_dvp = dvp;
- a.a_vpp = vpp;
- a.a_cnp = cnp;
- a.a_vap = vap;
- a.a_context = ctx;
-
-#if CONFIG_VFS_FUNNEL
- thread_safe = THREAD_SAFE_FS(dvp);
- if (!thread_safe) {
- if ( (_err = lock_fsnode(dvp, &funnel_state)) ) {
- return (_err);
- }
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
- _err = (*dvp->v_op[vnop_mkdir_desc.vdesc_offset])(&a);
+ struct vnode_attr *vap, vfs_context_t ctx)
+{
+ int _err;
+ struct vnop_mkdir_args a;
+
+ a.a_desc = &vnop_mkdir_desc;
+ a.a_dvp = dvp;
+ a.a_vpp = vpp;
+ a.a_cnp = cnp;
+ a.a_vap = vap;
+ a.a_context = ctx;
+
+ _err = (*dvp->v_op[vnop_mkdir_desc.vdesc_offset])(&a);
+ if (_err == 0 && *vpp) {
+ DTRACE_FSINFO(mkdir, vnode_t, *vpp);
+ }
+#if CONFIG_APPLEDOUBLE
if (_err == 0 && !NATIVE_XATTR(dvp)) {
- /*
+ /*
* Remove stale Apple Double file (if any).
*/
xattrfile_remove(dvp, cnp->cn_nameptr, ctx, 0);
}
+#endif /* CONFIG_APPLEDOUBLE */
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- unlock_fsnode(dvp, &funnel_state);
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
- post_event_if_success(dvp, _err, NOTE_LINK | NOTE_WRITE);
+ post_event_if_success(dvp, _err, NOTE_LINK | NOTE_WRITE);
- return (_err);
+ return _err;
}
int
VNOP_COMPOUND_MKDIR(struct vnode *dvp, struct vnode **vpp, struct nameidata *ndp,
- struct vnode_attr *vap, vfs_context_t ctx)
-{
- int _err;
- struct vnop_compound_mkdir_args a;
-
- a.a_desc = &vnop_compound_mkdir_desc;
- a.a_dvp = dvp;
- a.a_vpp = vpp;
- a.a_cnp = &ndp->ni_cnd;
- a.a_vap = vap;
- a.a_flags = 0;
- a.a_context = ctx;
+ struct vnode_attr *vap, vfs_context_t ctx)
+{
+ int _err;
+ struct vnop_compound_mkdir_args a;
+
+ a.a_desc = &vnop_compound_mkdir_desc;
+ a.a_dvp = dvp;
+ a.a_vpp = vpp;
+ a.a_cnp = &ndp->ni_cnd;
+ a.a_vap = vap;
+ a.a_flags = 0;
+ a.a_context = ctx;
#if 0
- a.a_mkdir_authorizer = vn_authorize_mkdir;
+ a.a_mkdir_authorizer = vn_authorize_mkdir;
#endif /* 0 */
- a.a_reserved = NULL;
+ a.a_reserved = NULL;
- _err = (*dvp->v_op[vnop_compound_mkdir_desc.vdesc_offset])(&a);
+ _err = (*dvp->v_op[vnop_compound_mkdir_desc.vdesc_offset])(&a);
+ if (_err == 0 && *vpp) {
+ DTRACE_FSINFO(compound_mkdir, vnode_t, *vpp);
+ }
+#if CONFIG_APPLEDOUBLE
if (_err == 0 && !NATIVE_XATTR(dvp)) {
- /*
+ /*
* Remove stale Apple Double file (if any).
*/
xattrfile_remove(dvp, ndp->ni_cnd.cn_nameptr, ctx, 0);
}
+#endif /* CONFIG_APPLEDOUBLE */
post_event_if_success(dvp, _err, NOTE_LINK | NOTE_WRITE);
*vpp = NULLVP;
}
- return (_err);
+ return _err;
}
int
#if 0
/*
- *#
- *#% rmdir dvp L U U
- *#% rmdir vp L U U
- *#
- */
+*#
+*#% rmdir dvp L U U
+*#% rmdir vp L U U
+*#
+*/
struct vnop_rmdir_args {
struct vnodeop_desc *a_desc;
vnode_t a_dvp;
{
int _err;
struct vnop_rmdir_args a;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
a.a_desc = &vnop_rmdir_desc;
a.a_dvp = dvp;
a.a_cnp = cnp;
a.a_context = ctx;
-#if CONFIG_VFS_FUNNEL
- thread_safe = THREAD_SAFE_FS(dvp);
- if (!thread_safe) {
- if ( (_err = lock_fsnode(vp, &funnel_state)) ) {
- return (_err);
- }
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
_err = (*vp->v_op[vnop_rmdir_desc.vdesc_offset])(&a);
+ DTRACE_FSINFO(rmdir, vnode_t, vp);
if (_err == 0) {
- vnode_setneedinactive(vp);
-
- if ( !(NATIVE_XATTR(dvp)) ) {
- /*
+ vnode_setneedinactive(vp);
+#if CONFIG_APPLEDOUBLE
+ if (!(NATIVE_XATTR(dvp))) {
+ /*
* Remove any associated extended attribute file (._ AppleDouble file).
*/
- xattrfile_remove(dvp, cnp->cn_nameptr, ctx, 1);
+ xattrfile_remove(dvp, cnp->cn_nameptr, ctx, 1);
}
+#endif
}
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- unlock_fsnode(vp, &funnel_state);
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
/* If you delete a dir, it loses its "." reference --> NOTE_LINK */
post_event_if_success(vp, _err, NOTE_DELETE | NOTE_LINK);
post_event_if_success(dvp, _err, NOTE_LINK | NOTE_WRITE);
- return (_err);
+ return _err;
}
int
VNOP_COMPOUND_RMDIR(struct vnode *dvp, struct vnode **vpp, struct nameidata *ndp,
- struct vnode_attr *vap, vfs_context_t ctx)
+ struct vnode_attr *vap, vfs_context_t ctx)
{
- int _err;
- struct vnop_compound_rmdir_args a;
- int no_vp;
+ int _err;
+ struct vnop_compound_rmdir_args a;
+ int no_vp;
- a.a_desc = &vnop_mkdir_desc;
- a.a_dvp = dvp;
- a.a_vpp = vpp;
- a.a_cnp = &ndp->ni_cnd;
- a.a_vap = vap;
- a.a_flags = 0;
- a.a_context = ctx;
- a.a_rmdir_authorizer = vn_authorize_rmdir;
- a.a_reserved = NULL;
+ a.a_desc = &vnop_mkdir_desc;
+ a.a_dvp = dvp;
+ a.a_vpp = vpp;
+ a.a_cnp = &ndp->ni_cnd;
+ a.a_vap = vap;
+ a.a_flags = 0;
+ a.a_context = ctx;
+ a.a_rmdir_authorizer = vn_authorize_rmdir;
+ a.a_reserved = NULL;
- no_vp = (*vpp == NULLVP);
+ no_vp = (*vpp == NULLVP);
- _err = (*dvp->v_op[vnop_compound_rmdir_desc.vdesc_offset])(&a);
+ _err = (*dvp->v_op[vnop_compound_rmdir_desc.vdesc_offset])(&a);
+ if (_err == 0 && *vpp) {
+ DTRACE_FSINFO(compound_rmdir, vnode_t, *vpp);
+ }
+#if CONFIG_APPLEDOUBLE
if (_err == 0 && !NATIVE_XATTR(dvp)) {
- /*
+ /*
* Remove stale Apple Double file (if any).
*/
xattrfile_remove(dvp, ndp->ni_cnd.cn_nameptr, ctx, 0);
}
+#endif
if (*vpp) {
post_event_if_success(*vpp, _err, NOTE_DELETE | NOTE_LINK);
}
post_event_if_success(dvp, _err, NOTE_LINK | NOTE_WRITE);
- if (no_vp) {
- lookup_compound_vnop_post_hook(_err, dvp, *vpp, ndp, 0);
+ if (no_vp) {
+ lookup_compound_vnop_post_hook(_err, dvp, *vpp, ndp, 0);
#if 0 /* Removing orphaned ._ files requires a vp.... */
- if (*vpp && _err && _err != EKEEPLOOKING) {
- vnode_put(*vpp);
- *vpp = NULLVP;
- }
+ if (*vpp && _err && _err != EKEEPLOOKING) {
+ vnode_put(*vpp);
+ *vpp = NULLVP;
+ }
#endif /* 0 */
- }
+ }
- return (_err);
+ return _err;
}
+#if CONFIG_APPLEDOUBLE
/*
* Remove a ._ AppleDouble file
*/
#define AD_STALE_SECS (180)
static void
-xattrfile_remove(vnode_t dvp, const char * basename, vfs_context_t ctx, int force)
+xattrfile_remove(vnode_t dvp, const char * basename, vfs_context_t ctx, int force)
{
vnode_t xvp;
struct nameidata nd;
char smallname[64];
char *filename = NULL;
- size_t len;
+ size_t alloc_len;
+ size_t copy_len;
if ((basename == NULL) || (basename[0] == '\0') ||
(basename[0] == '.' && basename[1] == '_')) {
return;
}
filename = &smallname[0];
- len = snprintf(filename, sizeof(smallname), "._%s", basename);
- if (len >= sizeof(smallname)) {
- len++; /* snprintf result doesn't include '\0' */
- MALLOC(filename, char *, len, M_TEMP, M_WAITOK);
- len = snprintf(filename, len, "._%s", basename);
+ alloc_len = snprintf(filename, sizeof(smallname), "._%s", basename);
+ if (alloc_len >= sizeof(smallname)) {
+ alloc_len++; /* snprintf result doesn't include '\0' */
+ filename = kheap_alloc(KHEAP_TEMP, alloc_len, Z_WAITOK);
+ copy_len = snprintf(filename, alloc_len, "._%s", basename);
}
NDINIT(&nd, DELETE, OP_UNLINK, WANTPARENT | LOCKLEAF | NOFOLLOW | USEDVP, UIO_SYSSPACE,
- CAST_USER_ADDR_T(filename), ctx);
+ CAST_USER_ADDR_T(filename), ctx);
nd.ni_dvp = dvp;
- if (namei(&nd) != 0)
+ if (namei(&nd) != 0) {
goto out2;
+ }
xvp = nd.ni_vp;
nameidone(&nd);
- if (xvp->v_type != VREG)
+ if (xvp->v_type != VREG) {
goto out1;
+ }
/*
* When creating a new object and a "._" file already
VATTR_INIT(&va);
VATTR_WANTED(&va, va_data_size);
VATTR_WANTED(&va, va_modify_time);
- if (VNOP_GETATTR(xvp, &va, ctx) == 0 &&
- VATTR_IS_SUPPORTED(&va, va_data_size) &&
- VATTR_IS_SUPPORTED(&va, va_modify_time) &&
+ if (VNOP_GETATTR(xvp, &va, ctx) == 0 &&
+ VATTR_IS_SUPPORTED(&va, va_data_size) &&
+ VATTR_IS_SUPPORTED(&va, va_modify_time) &&
va.va_data_size != 0) {
struct timeval tv;
}
if (force) {
int error;
-
+
error = VNOP_REMOVE(dvp, xvp, &nd.ni_cnd, 0, ctx);
- if (error == 0)
+ if (error == 0) {
vnode_setneedinactive(xvp);
+ }
post_event_if_success(xvp, error, NOTE_DELETE);
post_event_if_success(dvp, error, NOTE_WRITE);
}
-out1:
+out1:
vnode_put(dvp);
vnode_put(xvp);
out2:
if (filename && filename != &smallname[0]) {
- FREE(filename, M_TEMP);
+ kheap_free(KHEAP_TEMP, filename, alloc_len);
}
}
*/
static void
xattrfile_setattr(vnode_t dvp, const char * basename, struct vnode_attr * vap,
- vfs_context_t ctx)
+ vfs_context_t ctx)
{
vnode_t xvp;
struct nameidata nd;
char smallname[64];
char *filename = NULL;
- size_t len;
+ size_t alloc_len;
+ size_t copy_len;
if ((dvp == NULLVP) ||
(basename == NULL) || (basename[0] == '\0') ||
return;
}
filename = &smallname[0];
- len = snprintf(filename, sizeof(smallname), "._%s", basename);
- if (len >= sizeof(smallname)) {
- len++; /* snprintf result doesn't include '\0' */
- MALLOC(filename, char *, len, M_TEMP, M_WAITOK);
- len = snprintf(filename, len, "._%s", basename);
+ alloc_len = snprintf(filename, sizeof(smallname), "._%s", basename);
+ if (alloc_len >= sizeof(smallname)) {
+ alloc_len++; /* snprintf result doesn't include '\0' */
+ filename = kheap_alloc(KHEAP_TEMP, alloc_len, Z_WAITOK);
+ copy_len = snprintf(filename, alloc_len, "._%s", basename);
}
NDINIT(&nd, LOOKUP, OP_SETATTR, NOFOLLOW | USEDVP, UIO_SYSSPACE,
- CAST_USER_ADDR_T(filename), ctx);
+ CAST_USER_ADDR_T(filename), ctx);
nd.ni_dvp = dvp;
- if (namei(&nd) != 0)
+ if (namei(&nd) != 0) {
goto out2;
+ }
xvp = nd.ni_vp;
nameidone(&nd);
if (xvp->v_type == VREG) {
-#if CONFIG_VFS_FUNNEL
- int thread_safe = THREAD_SAFE_FS(dvp);
-#endif /* CONFIG_VFS_FUNNEL */
struct vnop_setattr_args a;
a.a_desc = &vnop_setattr_desc;
a.a_vap = vap;
a.a_context = ctx;
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- if ( (lock_fsnode(xvp, NULL)) )
- goto out1;
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
(void) (*xvp->v_op[vnop_setattr_desc.vdesc_offset])(&a);
-
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- unlock_fsnode(xvp, NULL);
- }
-#endif /* CONFIG_VFS_FUNNEL */
}
-
-#if CONFIG_VFS_FUNNEL
-out1:
-#endif /* CONFIG_VFS_FUNNEL */
vnode_put(xvp);
-
out2:
if (filename && filename != &smallname[0]) {
- FREE(filename, M_TEMP);
+ kheap_free(KHEAP_TEMP, filename, alloc_len);
}
}
+#endif /* CONFIG_APPLEDOUBLE */
#if 0
/*
- *#
- *#% symlink dvp L U U
- *#% symlink vpp - U -
- *#
- */
+*#
+*#% symlink dvp L U U
+*#% symlink vpp - U -
+*#
+*/
struct vnop_symlink_args {
- struct vnodeop_desc *a_desc;
- vnode_t a_dvp;
- vnode_t *a_vpp;
- struct componentname *a_cnp;
- struct vnode_attr *a_vap;
- char *a_target;
- vfs_context_t a_context;
+ struct vnodeop_desc *a_desc;
+ vnode_t a_dvp;
+ vnode_t *a_vpp;
+ struct componentname *a_cnp;
+ struct vnode_attr *a_vap;
+ char *a_target;
+ vfs_context_t a_context;
};
#endif /* 0*/
errno_t
VNOP_SYMLINK(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp,
- struct vnode_attr *vap, char *target, vfs_context_t ctx)
-{
- int _err;
- struct vnop_symlink_args a;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
-
- a.a_desc = &vnop_symlink_desc;
- a.a_dvp = dvp;
- a.a_vpp = vpp;
- a.a_cnp = cnp;
- a.a_vap = vap;
- a.a_target = target;
- a.a_context = ctx;
-
-#if CONFIG_VFS_FUNNEL
- thread_safe = THREAD_SAFE_FS(dvp);
- if (!thread_safe) {
- if ( (_err = lock_fsnode(dvp, &funnel_state)) ) {
- return (_err);
- }
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
- _err = (*dvp->v_op[vnop_symlink_desc.vdesc_offset])(&a);
+ struct vnode_attr *vap, char *target, vfs_context_t ctx)
+{
+ int _err;
+ struct vnop_symlink_args a;
+
+ a.a_desc = &vnop_symlink_desc;
+ a.a_dvp = dvp;
+ a.a_vpp = vpp;
+ a.a_cnp = cnp;
+ a.a_vap = vap;
+ a.a_target = target;
+ a.a_context = ctx;
+
+ _err = (*dvp->v_op[vnop_symlink_desc.vdesc_offset])(&a);
+ DTRACE_FSINFO(symlink, vnode_t, dvp);
+#if CONFIG_APPLEDOUBLE
if (_err == 0 && !NATIVE_XATTR(dvp)) {
- /*
+ /*
* Remove stale Apple Double file (if any). Posts its own knotes
*/
xattrfile_remove(dvp, cnp->cn_nameptr, ctx, 0);
}
+#endif /* CONFIG_APPLEDOUBLE */
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- unlock_fsnode(dvp, &funnel_state);
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
post_event_if_success(dvp, _err, NOTE_WRITE);
- return (_err);
+ return _err;
}
#if 0
/*
- *#
- *#% readdir vp L L L
- *#
- */
+*#
+*#% readdir vp L L L
+*#
+*/
struct vnop_readdir_args {
struct vnodeop_desc *a_desc;
vnode_t a_vp;
};
#endif /* 0*/
-errno_t
+errno_t
VNOP_READDIR(struct vnode *vp, struct uio *uio, int flags, int *eofflag,
- int *numdirent, vfs_context_t ctx)
+ int *numdirent, vfs_context_t ctx)
{
int _err;
struct vnop_readdir_args a;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
+#if CONFIG_DTRACE
+ user_ssize_t resid = uio_resid(uio);
+#endif
a.a_desc = &vnop_readdir_desc;
a.a_vp = vp;
a.a_eofflag = eofflag;
a.a_numdirent = numdirent;
a.a_context = ctx;
-#if CONFIG_VFS_FUNNEL
- thread_safe = THREAD_SAFE_FS(vp);
-
- if (!thread_safe) {
- if ( (_err = lock_fsnode(vp, &funnel_state)) ) {
- return (_err);
- }
- }
-#endif /* CONFIG_VFS_FUNNEL */
_err = (*vp->v_op[vnop_readdir_desc.vdesc_offset])(&a);
+ DTRACE_FSINFO_IO(readdir,
+ vnode_t, vp, user_ssize_t, (resid - uio_resid(uio)));
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- unlock_fsnode(vp, &funnel_state);
- }
-#endif /* CONFIG_VFS_FUNNEL */
- return (_err);
+ return _err;
}
#if 0
/*
- *#
- *#% readdirattr vp L L L
- *#
- */
+*#
+*#% readdirattr vp L L L
+*#
+*/
struct vnop_readdirattr_args {
struct vnodeop_desc *a_desc;
vnode_t a_vp;
};
#endif /* 0*/
-errno_t
+errno_t
VNOP_READDIRATTR(struct vnode *vp, struct attrlist *alist, struct uio *uio, uint32_t maxcount,
- uint32_t options, uint32_t *newstate, int *eofflag, uint32_t *actualcount, vfs_context_t ctx)
+ uint32_t options, uint32_t *newstate, int *eofflag, uint32_t *actualcount, vfs_context_t ctx)
{
int _err;
struct vnop_readdirattr_args a;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
+#if CONFIG_DTRACE
+ user_ssize_t resid = uio_resid(uio);
+#endif
a.a_desc = &vnop_readdirattr_desc;
a.a_vp = vp;
a.a_actualcount = actualcount;
a.a_context = ctx;
-#if CONFIG_VFS_FUNNEL
- thread_safe = THREAD_SAFE_FS(vp);
- if (!thread_safe) {
- if ( (_err = lock_fsnode(vp, &funnel_state)) ) {
- return (_err);
- }
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
_err = (*vp->v_op[vnop_readdirattr_desc.vdesc_offset])(&a);
+ DTRACE_FSINFO_IO(readdirattr,
+ vnode_t, vp, user_ssize_t, (resid - uio_resid(uio)));
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- unlock_fsnode(vp, &funnel_state);
- }
-#endif /* CONFIG_VFS_FUNNEL */
+ return _err;
+}
+
+#if 0
+struct vnop_getttrlistbulk_args {
+ struct vnodeop_desc *a_desc;
+ vnode_t a_vp;
+ struct attrlist *a_alist;
+ struct vnode_attr *a_vap;
+ struct uio *a_uio;
+ void *a_private
+ uint64_t a_options;
+ int *a_eofflag;
+ uint32_t *a_actualcount;
+ vfs_context_t a_context;
+};
+#endif /* 0*/
+errno_t
+VNOP_GETATTRLISTBULK(struct vnode *vp, struct attrlist *alist,
+ struct vnode_attr *vap, struct uio *uio, void *private, uint64_t options,
+ int32_t *eofflag, int32_t *actualcount, vfs_context_t ctx)
+{
+ int _err;
+ struct vnop_getattrlistbulk_args a;
+#if CONFIG_DTRACE
+ user_ssize_t resid = uio_resid(uio);
+#endif
+
+ a.a_desc = &vnop_getattrlistbulk_desc;
+ a.a_vp = vp;
+ a.a_alist = alist;
+ a.a_vap = vap;
+ a.a_uio = uio;
+ a.a_private = private;
+ a.a_options = options;
+ a.a_eofflag = eofflag;
+ a.a_actualcount = actualcount;
+ a.a_context = ctx;
- return (_err);
+ _err = (*vp->v_op[vnop_getattrlistbulk_desc.vdesc_offset])(&a);
+ DTRACE_FSINFO_IO(getattrlistbulk,
+ vnode_t, vp, user_ssize_t, (resid - uio_resid(uio)));
+
+ return _err;
}
#if 0
/*
- *#
- *#% readlink vp L L L
- *#
- */
+*#
+*#% readlink vp L L L
+*#
+*/
struct vnop_readlink_args {
struct vnodeop_desc *a_desc;
vnode_t a_vp;
* additional error code which may be propagated from underlying
* routines.
*/
-errno_t
+errno_t
VNOP_READLINK(struct vnode *vp, struct uio *uio, vfs_context_t ctx)
{
int _err;
struct vnop_readlink_args a;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
-
+#if CONFIG_DTRACE
+ user_ssize_t resid = uio_resid(uio);
+#endif
a.a_desc = &vnop_readlink_desc;
a.a_vp = vp;
a.a_uio = uio;
a.a_context = ctx;
-#if CONFIG_VFS_FUNNEL
- thread_safe = THREAD_SAFE_FS(vp);
- if (!thread_safe) {
- if ( (_err = lock_fsnode(vp, &funnel_state)) ) {
- return (_err);
- }
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
_err = (*vp->v_op[vnop_readlink_desc.vdesc_offset])(&a);
+ DTRACE_FSINFO_IO(readlink,
+ vnode_t, vp, user_ssize_t, (resid - uio_resid(uio)));
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- unlock_fsnode(vp, &funnel_state);
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
- return (_err);
+ return _err;
}
#if 0
/*
- *#
- *#% inactive vp L U U
- *#
- */
+*#
+*#% inactive vp L U U
+*#
+*/
struct vnop_inactive_args {
struct vnodeop_desc *a_desc;
vnode_t a_vp;
vfs_context_t a_context;
};
#endif /* 0*/
-errno_t
+errno_t
VNOP_INACTIVE(struct vnode *vp, vfs_context_t ctx)
{
int _err;
struct vnop_inactive_args a;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
a.a_desc = &vnop_inactive_desc;
a.a_vp = vp;
a.a_context = ctx;
-
-#if CONFIG_VFS_FUNNEL
- thread_safe = THREAD_SAFE_FS(vp);
- if (!thread_safe) {
- if ( (_err = lock_fsnode(vp, &funnel_state)) ) {
- return (_err);
- }
- }
-#endif /* CONFIG_VFS_FUNNEL */
_err = (*vp->v_op[vnop_inactive_desc.vdesc_offset])(&a);
-
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- unlock_fsnode(vp, &funnel_state);
- }
-#endif /* CONFIG_VFS_FUNNEL */
+ DTRACE_FSINFO(inactive, vnode_t, vp);
#if NAMEDSTREAMS
- /* For file systems that do not support namedstream natively, mark
- * the shadow stream file vnode to be recycled as soon as the last
- * reference goes away. To avoid re-entering reclaim code, do not
+ /* For file systems that do not support namedstream natively, mark
+ * the shadow stream file vnode to be recycled as soon as the last
+ * reference goes away. To avoid re-entering reclaim code, do not
* call recycle on terminating namedstream vnodes.
*/
if (vnode_isnamedstream(vp) &&
}
#endif
- return (_err);
+ return _err;
}
#if 0
/*
- *#
- *#% reclaim vp U U U
- *#
- */
+*#
+*#% reclaim vp U U U
+*#
+*/
struct vnop_reclaim_args {
struct vnodeop_desc *a_desc;
vnode_t a_vp;
{
int _err;
struct vnop_reclaim_args a;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
a.a_desc = &vnop_reclaim_desc;
a.a_vp = vp;
a.a_context = ctx;
-#if CONFIG_VFS_FUNNEL
- thread_safe = THREAD_SAFE_FS(vp);
- if (!thread_safe) {
- funnel_state = thread_funnel_set(kernel_flock, TRUE);
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
_err = (*vp->v_op[vnop_reclaim_desc.vdesc_offset])(&a);
+ DTRACE_FSINFO(reclaim, vnode_t, vp);
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- (void) thread_funnel_set(kernel_flock, funnel_state);
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
- return (_err);
+ return _err;
}
*/
#if 0
/*
- *#
- *#% pathconf vp L L L
- *#
- */
+*#
+*#% pathconf vp L L L
+*#
+*/
struct vnop_pathconf_args {
struct vnodeop_desc *a_desc;
vnode_t a_vp;
vfs_context_t a_context;
};
#endif /* 0*/
-errno_t
+errno_t
VNOP_PATHCONF(struct vnode *vp, int name, int32_t *retval, vfs_context_t ctx)
{
int _err;
struct vnop_pathconf_args a;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
a.a_desc = &vnop_pathconf_desc;
a.a_vp = vp;
a.a_retval = retval;
a.a_context = ctx;
-#if CONFIG_VFS_FUNNEL
- thread_safe = THREAD_SAFE_FS(vp);
- if (!thread_safe) {
- if ( (_err = lock_fsnode(vp, &funnel_state)) ) {
- return (_err);
- }
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
_err = (*vp->v_op[vnop_pathconf_desc.vdesc_offset])(&a);
+ DTRACE_FSINFO(pathconf, vnode_t, vp);
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- unlock_fsnode(vp, &funnel_state);
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
- return (_err);
+ return _err;
}
/*
*/
#if 0
/*
- *#
- *#% advlock vp U U U
- *#
- */
+*#
+*#% advlock vp U U U
+*#
+*/
struct vnop_advlock_args {
struct vnodeop_desc *a_desc;
vnode_t a_vp;
vfs_context_t a_context;
};
#endif /* 0*/
-errno_t
-VNOP_ADVLOCK(struct vnode *vp, caddr_t id, int op, struct flock *fl, int flags, vfs_context_t ctx)
+errno_t
+VNOP_ADVLOCK(struct vnode *vp, caddr_t id, int op, struct flock *fl, int flags, vfs_context_t ctx, struct timespec *timeout)
{
int _err;
struct vnop_advlock_args a;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
a.a_desc = &vnop_advlock_desc;
a.a_vp = vp;
a.a_fl = fl;
a.a_flags = flags;
a.a_context = ctx;
-
-#if CONFIG_VFS_FUNNEL
- thread_safe = THREAD_SAFE_FS(vp);
- if (!thread_safe) {
- funnel_state = thread_funnel_set(kernel_flock, TRUE);
- }
-#endif /* CONFIG_VFS_FUNNEL */
+ a.a_timeout = timeout;
/* Disallow advisory locking on non-seekable vnodes */
if (vnode_isfifo(vp)) {
if ((vp->v_flag & VLOCKLOCAL)) {
/* Advisory locking done at this layer */
_err = lf_advlock(&a);
+ } else if (flags & F_OFD_LOCK) {
+ /* Non-local locking doesn't work for OFD locks */
+ _err = err_advlock(&a);
} else {
/* Advisory locking done by underlying filesystem */
_err = (*vp->v_op[vnop_advlock_desc.vdesc_offset])(&a);
}
+ DTRACE_FSINFO(advlock, vnode_t, vp);
+ if (op == F_UNLCK &&
+ (flags & (F_FLOCK | F_OFD_LOCK)) != 0) {
+ post_event_if_success(vp, _err, NOTE_FUNLOCK);
+ }
}
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- (void) thread_funnel_set(kernel_flock, funnel_state);
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
- return (_err);
+ return _err;
}
#if 0
/*
- *#
- *#% allocate vp L L L
- *#
- */
+*#
+*#% allocate vp L L L
+*#
+*/
struct vnop_allocate_args {
struct vnodeop_desc *a_desc;
vnode_t a_vp;
};
#endif /* 0*/
-errno_t
+errno_t
VNOP_ALLOCATE(struct vnode *vp, off_t length, u_int32_t flags, off_t *bytesallocated, off_t offset, vfs_context_t ctx)
{
int _err;
struct vnop_allocate_args a;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
a.a_desc = &vnop_allocate_desc;
a.a_vp = vp;
a.a_offset = offset;
a.a_context = ctx;
-#if CONFIG_VFS_FUNNEL
- thread_safe = THREAD_SAFE_FS(vp);
- if (!thread_safe) {
- if ( (_err = lock_fsnode(vp, &funnel_state)) ) {
- return (_err);
- }
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
_err = (*vp->v_op[vnop_allocate_desc.vdesc_offset])(&a);
+ DTRACE_FSINFO(allocate, vnode_t, vp);
#if CONFIG_FSE
if (_err == 0) {
add_fsevent(FSE_STAT_CHANGED, ctx, FSE_ARG_VNODE, vp, FSE_ARG_DONE);
}
#endif
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- unlock_fsnode(vp, &funnel_state);
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
- return (_err);
+ return _err;
}
#if 0
/*
- *#
- *#% pagein vp = = =
- *#
- */
+*#
+*#% pagein vp = = =
+*#
+*/
struct vnop_pagein_args {
struct vnodeop_desc *a_desc;
vnode_t a_vp;
vfs_context_t a_context;
};
#endif /* 0*/
-errno_t
+errno_t
VNOP_PAGEIN(struct vnode *vp, upl_t pl, upl_offset_t pl_offset, off_t f_offset, size_t size, int flags, vfs_context_t ctx)
{
int _err;
struct vnop_pagein_args a;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
a.a_desc = &vnop_pagein_desc;
a.a_vp = vp;
a.a_flags = flags;
a.a_context = ctx;
-#if CONFIG_VFS_FUNNEL
- thread_safe = THREAD_SAFE_FS(vp);
- if (!thread_safe) {
- funnel_state = thread_funnel_set(kernel_flock, TRUE);
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
_err = (*vp->v_op[vnop_pagein_desc.vdesc_offset])(&a);
+ DTRACE_FSINFO(pagein, vnode_t, vp);
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- (void) thread_funnel_set(kernel_flock, funnel_state);
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
- return (_err);
+ return _err;
}
#if 0
/*
- *#
- *#% pageout vp = = =
- *#
- */
+*#
+*#% pageout vp = = =
+*#
+*/
struct vnop_pageout_args {
struct vnodeop_desc *a_desc;
vnode_t a_vp;
};
#endif /* 0*/
-errno_t
+errno_t
VNOP_PAGEOUT(struct vnode *vp, upl_t pl, upl_offset_t pl_offset, off_t f_offset, size_t size, int flags, vfs_context_t ctx)
{
int _err;
struct vnop_pageout_args a;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
a.a_desc = &vnop_pageout_desc;
a.a_vp = vp;
a.a_flags = flags;
a.a_context = ctx;
-#if CONFIG_VFS_FUNNEL
- thread_safe = THREAD_SAFE_FS(vp);
- if (!thread_safe) {
- funnel_state = thread_funnel_set(kernel_flock, TRUE);
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
_err = (*vp->v_op[vnop_pageout_desc.vdesc_offset])(&a);
-
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- (void) thread_funnel_set(kernel_flock, funnel_state);
- }
-#endif /* CONFIG_VFS_FUNNEL */
+ DTRACE_FSINFO(pageout, vnode_t, vp);
post_event_if_success(vp, _err, NOTE_WRITE);
- return (_err);
+ return _err;
}
int
#if 0
/*
- *#
- *#% searchfs vp L L L
- *#
- */
+*#
+*#% searchfs vp L L L
+*#
+*/
struct vnop_searchfs_args {
struct vnodeop_desc *a_desc;
vnode_t a_vp;
};
#endif /* 0*/
-errno_t
+errno_t
VNOP_SEARCHFS(struct vnode *vp, void *searchparams1, void *searchparams2, struct attrlist *searchattrs, uint32_t maxmatches, struct timeval *timelimit, struct attrlist *returnattrs, uint32_t *nummatches, uint32_t scriptcode, uint32_t options, struct uio *uio, struct searchstate *searchstate, vfs_context_t ctx)
{
int _err;
struct vnop_searchfs_args a;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
a.a_desc = &vnop_searchfs_desc;
a.a_vp = vp;
a.a_searchstate = searchstate;
a.a_context = ctx;
-#if CONFIG_VFS_FUNNEL
- thread_safe = THREAD_SAFE_FS(vp);
- if (!thread_safe) {
- if ( (_err = lock_fsnode(vp, &funnel_state)) ) {
- return (_err);
- }
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
_err = (*vp->v_op[vnop_searchfs_desc.vdesc_offset])(&a);
+ DTRACE_FSINFO(searchfs, vnode_t, vp);
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- unlock_fsnode(vp, &funnel_state);
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
- return (_err);
+ return _err;
}
#endif /* CONFIG_SEARCHFS */
#if 0
/*
- *#
- *#% copyfile fvp U U U
- *#% copyfile tdvp L U U
- *#% copyfile tvp X U U
- *#
- */
+*#
+*#% copyfile fvp U U U
+*#% copyfile tdvp L U U
+*#% copyfile tvp X U U
+*#
+*/
struct vnop_copyfile_args {
struct vnodeop_desc *a_desc;
vnode_t a_fvp;
vfs_context_t a_context;
};
#endif /* 0*/
-errno_t
+errno_t
VNOP_COPYFILE(struct vnode *fvp, struct vnode *tdvp, struct vnode *tvp, struct componentname *tcnp,
- int mode, int flags, vfs_context_t ctx)
+ int mode, int flags, vfs_context_t ctx)
{
int _err;
struct vnop_copyfile_args a;
a.a_flags = flags;
a.a_context = ctx;
_err = (*fvp->v_op[vnop_copyfile_desc.vdesc_offset])(&a);
- return (_err);
+ DTRACE_FSINFO(copyfile, vnode_t, fvp);
+ return _err;
+}
+
+#if 0
+struct vnop_clonefile_args {
+ struct vnodeop_desc *a_desc;
+ vnode_t a_fvp;
+ vnode_t a_dvp;
+ vnode_t *a_vpp;
+ struct componentname *a_cnp;
+ struct vnode_attr *a_vap;
+ uint32_t a_flags;
+ vfs_context_t a_context;
+ int (*a_dir_clone_authorizer)( /* Authorization callback */
+ struct vnode_attr *vap, /* attribute to be authorized */
+ kauth_action_t action, /* action for which attribute is to be authorized */
+ struct vnode_attr *dvap, /* target directory attributes */
+ vnode_t sdvp, /* source directory vnode pointer (optional) */
+ mount_t mp, /* mount point of filesystem */
+ dir_clone_authorizer_op_t vattr_op, /* specific operation requested : setup, authorization or cleanup */
+ uint32_t flags; /* value passed in a_flags to the VNOP */
+ vfs_context_t ctx, /* As passed to VNOP */
+ void *reserved); /* Always NULL */
+ void *a_reserved; /* Currently unused */
+};
+#endif /* 0 */
+
+errno_t
+VNOP_CLONEFILE(vnode_t fvp, vnode_t dvp, vnode_t *vpp,
+ struct componentname *cnp, struct vnode_attr *vap, uint32_t flags,
+ vfs_context_t ctx)
+{
+ int _err;
+ struct vnop_clonefile_args a;
+ a.a_desc = &vnop_clonefile_desc;
+ a.a_fvp = fvp;
+ a.a_dvp = dvp;
+ a.a_vpp = vpp;
+ a.a_cnp = cnp;
+ a.a_vap = vap;
+ a.a_flags = flags;
+ a.a_context = ctx;
+
+ if (vnode_vtype(fvp) == VDIR) {
+ a.a_dir_clone_authorizer = vnode_attr_authorize_dir_clone;
+ } else {
+ a.a_dir_clone_authorizer = NULL;
+ }
+
+ _err = (*dvp->v_op[vnop_clonefile_desc.vdesc_offset])(&a);
+
+ if (_err == 0 && *vpp) {
+ DTRACE_FSINFO(clonefile, vnode_t, *vpp);
+ if (kdebug_enable) {
+ kdebug_lookup(*vpp, cnp);
+ }
+ }
+
+ post_event_if_success(dvp, _err, NOTE_WRITE);
+
+ return _err;
}
errno_t
{
struct vnop_getxattr_args a;
int error;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
a.a_desc = &vnop_getxattr_desc;
a.a_vp = vp;
a.a_options = options;
a.a_context = ctx;
-#if CONFIG_VFS_FUNNEL
- thread_safe = THREAD_SAFE_FS(vp);
- if (!thread_safe) {
- if ( (error = lock_fsnode(vp, &funnel_state)) ) {
- return (error);
- }
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
error = (*vp->v_op[vnop_getxattr_desc.vdesc_offset])(&a);
+ DTRACE_FSINFO(getxattr, vnode_t, vp);
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- unlock_fsnode(vp, &funnel_state);
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
- return (error);
+ return error;
}
errno_t
{
struct vnop_setxattr_args a;
int error;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
a.a_desc = &vnop_setxattr_desc;
a.a_vp = vp;
a.a_options = options;
a.a_context = ctx;
-#if CONFIG_VFS_FUNNEL
- thread_safe = THREAD_SAFE_FS(vp);
- if (!thread_safe) {
- if ( (error = lock_fsnode(vp, &funnel_state)) ) {
- return (error);
- }
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
error = (*vp->v_op[vnop_setxattr_desc.vdesc_offset])(&a);
+ DTRACE_FSINFO(setxattr, vnode_t, vp);
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- unlock_fsnode(vp, &funnel_state);
+ if (error == 0) {
+ vnode_uncache_authorized_action(vp, KAUTH_INVALIDATE_CACHED_RIGHTS);
}
-#endif /* CONFIG_VFS_FUNNEL */
-
- if (error == 0)
- vnode_uncache_authorized_action(vp, KAUTH_INVALIDATE_CACHED_RIGHTS);
post_event_if_success(vp, error, NOTE_ATTRIB);
- return (error);
+ return error;
}
errno_t
{
struct vnop_removexattr_args a;
int error;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
a.a_desc = &vnop_removexattr_desc;
a.a_vp = vp;
a.a_options = options;
a.a_context = ctx;
-#if CONFIG_VFS_FUNNEL
- thread_safe = THREAD_SAFE_FS(vp);
- if (!thread_safe) {
- if ( (error = lock_fsnode(vp, &funnel_state)) ) {
- return (error);
- }
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
error = (*vp->v_op[vnop_removexattr_desc.vdesc_offset])(&a);
-
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- unlock_fsnode(vp, &funnel_state);
- }
-#endif /* CONFIG_VFS_FUNNEL */
+ DTRACE_FSINFO(removexattr, vnode_t, vp);
post_event_if_success(vp, error, NOTE_ATTRIB);
-
- return (error);
+
+ return error;
}
errno_t
{
struct vnop_listxattr_args a;
int error;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
a.a_desc = &vnop_listxattr_desc;
a.a_vp = vp;
a.a_options = options;
a.a_context = ctx;
-#if CONFIG_VFS_FUNNEL
- thread_safe = THREAD_SAFE_FS(vp);
- if (!thread_safe) {
- if ( (error = lock_fsnode(vp, &funnel_state)) ) {
- return (error);
- }
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
error = (*vp->v_op[vnop_listxattr_desc.vdesc_offset])(&a);
+ DTRACE_FSINFO(listxattr, vnode_t, vp);
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- unlock_fsnode(vp, &funnel_state);
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
- return (error);
+ return error;
}
#if 0
/*
- *#
- *#% blktooff vp = = =
- *#
- */
+*#
+*#% blktooff vp = = =
+*#
+*/
struct vnop_blktooff_args {
struct vnodeop_desc *a_desc;
vnode_t a_vp;
off_t *a_offset;
};
#endif /* 0*/
-errno_t
+errno_t
VNOP_BLKTOOFF(struct vnode *vp, daddr64_t lblkno, off_t *offset)
{
int _err;
struct vnop_blktooff_args a;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
a.a_desc = &vnop_blktooff_desc;
a.a_vp = vp;
a.a_lblkno = lblkno;
a.a_offset = offset;
-#if CONFIG_VFS_FUNNEL
- thread_safe = THREAD_SAFE_FS(vp);
- if (!thread_safe) {
- funnel_state = thread_funnel_set(kernel_flock, TRUE);
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
_err = (*vp->v_op[vnop_blktooff_desc.vdesc_offset])(&a);
+ DTRACE_FSINFO(blktooff, vnode_t, vp);
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- (void) thread_funnel_set(kernel_flock, funnel_state);
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
- return (_err);
+ return _err;
}
#if 0
/*
- *#
- *#% offtoblk vp = = =
- *#
- */
+*#
+*#% offtoblk vp = = =
+*#
+*/
struct vnop_offtoblk_args {
struct vnodeop_desc *a_desc;
vnode_t a_vp;
daddr64_t *a_lblkno;
};
#endif /* 0*/
-errno_t
+errno_t
VNOP_OFFTOBLK(struct vnode *vp, off_t offset, daddr64_t *lblkno)
{
int _err;
struct vnop_offtoblk_args a;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
a.a_desc = &vnop_offtoblk_desc;
a.a_vp = vp;
a.a_offset = offset;
a.a_lblkno = lblkno;
-#if CONFIG_VFS_FUNNEL
- thread_safe = THREAD_SAFE_FS(vp);
- if (!thread_safe) {
- funnel_state = thread_funnel_set(kernel_flock, TRUE);
+ _err = (*vp->v_op[vnop_offtoblk_desc.vdesc_offset])(&a);
+ DTRACE_FSINFO(offtoblk, vnode_t, vp);
+
+ return _err;
+}
+
+#if 0
+/*
+*#
+*#% ap vp L L L
+*#
+*/
+struct vnop_verify_args {
+ struct vnodeop_desc *a_desc;
+ vnode_t a_vp;
+ off_t a_foffset;
+ char *a_buf;
+ size_t a_bufsize;
+ size_t *a_verifyblksize;
+ int a_flags;
+ vfs_context_t a_context;
+};
+#endif
+
+errno_t
+VNOP_VERIFY(struct vnode *vp, off_t foffset, uint8_t *buf, size_t bufsize,
+ size_t *verify_block_size, vnode_verify_flags_t flags, vfs_context_t ctx)
+{
+ int _err;
+ struct vnop_verify_args a;
+
+ if (ctx == NULL) {
+ ctx = vfs_context_current();
}
-#endif /* CONFIG_VFS_FUNNEL */
+ a.a_desc = &vnop_verify_desc;
+ a.a_vp = vp;
+ a.a_foffset = foffset;
+ a.a_buf = buf;
+ a.a_bufsize = bufsize;
+ a.a_verifyblksize = verify_block_size;
+ a.a_flags = flags;
+ a.a_context = ctx;
- _err = (*vp->v_op[vnop_offtoblk_desc.vdesc_offset])(&a);
+ _err = (*vp->v_op[vnop_verify_desc.vdesc_offset])(&a);
+ DTRACE_FSINFO(verify, vnode_t, vp);
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- (void) thread_funnel_set(kernel_flock, funnel_state);
+ /* It is not an error for a filesystem to not support this VNOP */
+ if (_err == ENOTSUP) {
+ if (!buf && verify_block_size) {
+ *verify_block_size = 0;
+ }
+
+ _err = 0;
}
-#endif /* CONFIG_VFS_FUNNEL */
- return (_err);
+ return _err;
}
#if 0
/*
- *#
- *#% blockmap vp L L L
- *#
- */
+*#
+*#% blockmap vp L L L
+*#
+*/
struct vnop_blockmap_args {
struct vnodeop_desc *a_desc;
vnode_t a_vp;
vfs_context_t a_context;
};
#endif /* 0*/
-errno_t
+errno_t
VNOP_BLOCKMAP(struct vnode *vp, off_t foffset, size_t size, daddr64_t *bpn, size_t *run, void *poff, int flags, vfs_context_t ctx)
{
int _err;
struct vnop_blockmap_args a;
size_t localrun = 0;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
if (ctx == NULL) {
ctx = vfs_context_current();
a.a_flags = flags;
a.a_context = ctx;
-#if CONFIG_VFS_FUNNEL
- thread_safe = THREAD_SAFE_FS(vp);
- if (!thread_safe) {
- funnel_state = thread_funnel_set(kernel_flock, TRUE);
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
_err = (*vp->v_op[vnop_blockmap_desc.vdesc_offset])(&a);
-
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- (void) thread_funnel_set(kernel_flock, funnel_state);
- }
-#endif /* CONFIG_VFS_FUNNEL */
+ DTRACE_FSINFO(blockmap, vnode_t, vp);
/*
* We used a local variable to request information from the underlying
}
}
- return (_err);
+ return _err;
}
#if 0
};
#endif /* 0*/
-errno_t
+errno_t
VNOP_STRATEGY(struct buf *bp)
{
int _err;
struct vnop_strategy_args a;
+ vnode_t vp = buf_vnode(bp);
a.a_desc = &vnop_strategy_desc;
a.a_bp = bp;
- _err = (*buf_vnode(bp)->v_op[vnop_strategy_desc.vdesc_offset])(&a);
- return (_err);
+ _err = (*vp->v_op[vnop_strategy_desc.vdesc_offset])(&a);
+ DTRACE_FSINFO(strategy, vnode_t, vp);
+ return _err;
}
#if 0
buf_t a_bp;
};
#endif /* 0*/
-errno_t
+errno_t
VNOP_BWRITE(struct buf *bp)
{
int _err;
struct vnop_bwrite_args a;
+ vnode_t vp = buf_vnode(bp);
a.a_desc = &vnop_bwrite_desc;
a.a_bp = bp;
- _err = (*buf_vnode(bp)->v_op[vnop_bwrite_desc.vdesc_offset])(&a);
- return (_err);
+ _err = (*vp->v_op[vnop_bwrite_desc.vdesc_offset])(&a);
+ DTRACE_FSINFO(bwrite, vnode_t, vp);
+ return _err;
}
#if 0
{
int _err;
struct vnop_kqfilt_add_args a;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
a.a_desc = VDESC(vnop_kqfilt_add);
a.a_vp = vp;
a.a_kn = kn;
a.a_context = ctx;
-#if CONFIG_VFS_FUNNEL
- thread_safe = THREAD_SAFE_FS(vp);
- if (!thread_safe) {
- if ( (_err = lock_fsnode(vp, &funnel_state)) ) {
- return (_err);
- }
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
_err = (*vp->v_op[vnop_kqfilt_add_desc.vdesc_offset])(&a);
-
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- unlock_fsnode(vp, &funnel_state);
- }
-#endif /* CONFIG_VFS_FUNNEL */
+ DTRACE_FSINFO(kqfilt_add, vnode_t, vp);
- return(_err);
+ return _err;
}
#if 0
{
int _err;
struct vnop_kqfilt_remove_args a;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
a.a_desc = VDESC(vnop_kqfilt_remove);
a.a_vp = vp;
a.a_ident = ident;
a.a_context = ctx;
-#if CONFIG_VFS_FUNNEL
- thread_safe = THREAD_SAFE_FS(vp);
- if (!thread_safe) {
- if ( (_err = lock_fsnode(vp, &funnel_state)) ) {
- return (_err);
- }
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
_err = (*vp->v_op[vnop_kqfilt_remove_desc.vdesc_offset])(&a);
+ DTRACE_FSINFO(kqfilt_remove, vnode_t, vp);
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- unlock_fsnode(vp, &funnel_state);
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
- return(_err);
+ return _err;
}
errno_t
{
int _err;
struct vnop_monitor_args a;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
a.a_desc = VDESC(vnop_monitor);
a.a_vp = vp;
a.a_handle = handle;
a.a_context = ctx;
-#if CONFIG_VFS_FUNNEL
- thread_safe = THREAD_SAFE_FS(vp);
- if (!thread_safe) {
- if ( (_err = lock_fsnode(vp, &funnel_state)) ) {
- return (_err);
- }
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
_err = (*vp->v_op[vnop_monitor_desc.vdesc_offset])(&a);
+ DTRACE_FSINFO(monitor, vnode_t, vp);
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- unlock_fsnode(vp, &funnel_state);
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
- return(_err);
+ return _err;
}
#if 0
{
int _err;
struct vnop_setlabel_args a;
-#if CONFIG_VFS_FUNNEL
- int thread_safe;
- int funnel_state = 0;
-#endif /* CONFIG_VFS_FUNNEL */
a.a_desc = VDESC(vnop_setlabel);
a.a_vp = vp;
a.a_vl = label;
a.a_context = ctx;
-#if CONFIG_VFS_FUNNEL
- thread_safe = THREAD_SAFE_FS(vp);
- if (!thread_safe) {
- if ( (_err = lock_fsnode(vp, &funnel_state)) ) {
- return (_err);
- }
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
_err = (*vp->v_op[vnop_setlabel_desc.vdesc_offset])(&a);
+ DTRACE_FSINFO(setlabel, vnode_t, vp);
-#if CONFIG_VFS_FUNNEL
- if (!thread_safe) {
- unlock_fsnode(vp, &funnel_state);
- }
-#endif /* CONFIG_VFS_FUNNEL */
-
- return(_err);
+ return _err;
}
/*
* Get a named streamed
*/
-errno_t
+errno_t
VNOP_GETNAMEDSTREAM(vnode_t vp, vnode_t *svpp, const char *name, enum nsoperation operation, int flags, vfs_context_t ctx)
{
+ int _err;
struct vnop_getnamedstream_args a;
-#if CONFIG_VFS_FUNNEL
- if (!THREAD_SAFE_FS(vp))
- return (ENOTSUP);
-#endif /* CONFIG_VFS_FUNNEL */
-
a.a_desc = &vnop_getnamedstream_desc;
a.a_vp = vp;
a.a_svpp = svpp;
a.a_flags = flags;
a.a_context = ctx;
- return (*vp->v_op[vnop_getnamedstream_desc.vdesc_offset])(&a);
+ _err = (*vp->v_op[vnop_getnamedstream_desc.vdesc_offset])(&a);
+ DTRACE_FSINFO(getnamedstream, vnode_t, vp);
+ return _err;
}
/*
* Create a named streamed
*/
-errno_t
+errno_t
VNOP_MAKENAMEDSTREAM(vnode_t vp, vnode_t *svpp, const char *name, int flags, vfs_context_t ctx)
{
+ int _err;
struct vnop_makenamedstream_args a;
-#if CONFIG_VFS_FUNNEL
- if (!THREAD_SAFE_FS(vp))
- return (ENOTSUP);
-#endif /* CONFIG_VFS_FUNNEL */
-
a.a_desc = &vnop_makenamedstream_desc;
a.a_vp = vp;
a.a_svpp = svpp;
a.a_flags = flags;
a.a_context = ctx;
- return (*vp->v_op[vnop_makenamedstream_desc.vdesc_offset])(&a);
+ _err = (*vp->v_op[vnop_makenamedstream_desc.vdesc_offset])(&a);
+ DTRACE_FSINFO(makenamedstream, vnode_t, vp);
+ return _err;
}
/*
* Remove a named streamed
*/
-errno_t
+errno_t
VNOP_REMOVENAMEDSTREAM(vnode_t vp, vnode_t svp, const char *name, int flags, vfs_context_t ctx)
{
+ int _err;
struct vnop_removenamedstream_args a;
-#if CONFIG_VFS_FUNNEL
- if (!THREAD_SAFE_FS(vp))
- return (ENOTSUP);
-#endif /* CONFIG_VFS_FUNNEL */
-
a.a_desc = &vnop_removenamedstream_desc;
a.a_vp = vp;
a.a_svp = svp;
a.a_flags = flags;
a.a_context = ctx;
- return (*vp->v_op[vnop_removenamedstream_desc.vdesc_offset])(&a);
+ _err = (*vp->v_op[vnop_removenamedstream_desc.vdesc_offset])(&a);
+ DTRACE_FSINFO(removenamedstream, vnode_t, vp);
+ return _err;
}
#endif