+/*
+ * Portions Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
+ */
#include <afsconfig.h>
#include <afs/param.h>
-RCSID("$Header$");
-#include <afs/sysincludes.h> /* Standard vendor system headers */
-#include <afs/afsincludes.h> /* Afs-based standard headers */
-#include <afs/afs_stats.h> /* statistics */
+#include <afs/sysincludes.h> /* Standard vendor system headers */
+#include <afsincludes.h> /* Afs-based standard headers */
+#include <afs/afs_stats.h> /* statistics */
#include <sys/malloc.h>
#include <sys/namei.h>
#include <sys/ubc.h>
+#include <vfs/vfs_support.h>
+#ifdef AFS_DARWIN80_ENV
+#include <sys/vnode_if.h>
+#include <sys/kauth.h>
+#endif
-int afs_vop_lookup(struct vop_lookup_args *);
-int afs_vop_create(struct vop_create_args *);
-int afs_vop_mknod(struct vop_mknod_args *);
-int afs_vop_open(struct vop_open_args *);
-int afs_vop_close(struct vop_close_args *);
-int afs_vop_access(struct vop_access_args *);
-int afs_vop_getattr(struct vop_getattr_args *);
-int afs_vop_setattr(struct vop_setattr_args *);
-int afs_vop_read(struct vop_read_args *);
-int afs_vop_write(struct vop_write_args *);
-int afs_vop_pagein(struct vop_pagein_args *);
-int afs_vop_pageout(struct vop_pageout_args *);
-int afs_vop_ioctl(struct vop_ioctl_args *);
-int afs_vop_select(struct vop_select_args *);
-int afs_vop_mmap(struct vop_mmap_args *);
-int afs_vop_fsync(struct vop_fsync_args *);
-int afs_vop_seek(struct vop_seek_args *);
-int afs_vop_remove(struct vop_remove_args *);
-int afs_vop_link(struct vop_link_args *);
-int afs_vop_rename(struct vop_rename_args *);
-int afs_vop_mkdir(struct vop_mkdir_args *);
-int afs_vop_rmdir(struct vop_rmdir_args *);
-int afs_vop_symlink(struct vop_symlink_args *);
-int afs_vop_readdir(struct vop_readdir_args *);
-int afs_vop_readlink(struct vop_readlink_args *);
-extern int ufs_abortop(struct vop_abortop_args *);
-int afs_vop_inactive(struct vop_inactive_args *);
-int afs_vop_reclaim(struct vop_reclaim_args *);
-int afs_vop_lock(struct vop_lock_args *);
-int afs_vop_unlock(struct vop_unlock_args *);
-int afs_vop_bmap(struct vop_bmap_args *);
-int afs_vop_strategy(struct vop_strategy_args *);
-int afs_vop_print(struct vop_print_args *);
-int afs_vop_islocked(struct vop_islocked_args *);
-int afs_vop_pathconf(struct vop_pathconf_args *);
-int afs_vop_advlock(struct vop_advlock_args *);
-int afs_vop_truncate(struct vop_truncate_args *);
-int afs_vop_update(struct vop_update_args *);
-int afs_vop_blktooff __P((struct vop_blktooff_args *));
-int afs_vop_offtoblk __P((struct vop_offtoblk_args *));
-int afs_vop_cmap __P((struct vop_cmap_args *));
+#ifdef AFS_DARWIN80_ENV
+#define VOPPREF(x) &vnop_ ## x
+#define VOPPROT(x) vnop_ ## x
+#define OSI_UPL_ABORT_RANGE(pl, offset, size, flags) \
+ ubc_upl_abort_range((pl), (offset), (size), (flags))
+#define OSI_UPL_COMMIT_RANGE(pl, offset, size, flags) \
+ ubc_upl_commit_range((pl), (offset), (size), (flags))
+#define OSI_UPL_MAP(upl, offset) ubc_upl_map((upl), (offset))
+#define OSI_UPL_UNMAP(upl) ubc_upl_unmap((upl))
+#define VOP_ABORTOP(x, y)
+#else
+#define VOPPREF(x) &vop_ ## x
+#define VOPPROT(x) vop_ ## x
+#define OSI_UPL_ABORT_RANGE(pl, offset, size, flags) \
+ kernel_upl_abort_range((pl), (offset), (size), (flags))
+#define OSI_UPL_COMMIT_RANGE(pl, offset, size, flags) \
+ kernel_upl_commit_range((pl), (offset), (size), (flags), \
+ UPL_GET_INTERNAL_PAGE_LIST((pl)),\
+ MAX_UPL_TRANSFER)
+#define OSI_UPL_MAP(upl, offset) kernel_upl_map(kernel_map, (upl), (offset))
+#define OSI_UPL_UNMAP(upl) kernel_upl_unmap(kernel_map, (upl))
+#endif
+extern char afs_zeros[AFS_ZEROS];
+
+int afs_vop_lookup(struct VOPPROT(lookup_args) *);
+int afs_vop_create(struct VOPPROT(create_args) *);
+int afs_vop_mknod(struct VOPPROT(mknod_args) *);
+int afs_vop_open(struct VOPPROT(open_args) *);
+int afs_vop_close(struct VOPPROT(close_args) *);
+int afs_vop_access(struct VOPPROT(access_args) *);
+int afs_vop_getattr(struct VOPPROT(getattr_args) *);
+int afs_vop_setattr(struct VOPPROT(setattr_args) *);
+int afs_vop_read(struct VOPPROT(read_args) *);
+int afs_vop_write(struct VOPPROT(write_args) *);
+int afs_vop_pagein(struct VOPPROT(pagein_args) *);
+int afs_vop_pageout(struct VOPPROT(pageout_args) *);
+int afs_vop_ioctl(struct VOPPROT(ioctl_args) *);
+int afs_vop_select(struct VOPPROT(select_args) *);
+int afs_vop_mmap(struct VOPPROT(mmap_args) *);
+int afs_vop_fsync(struct VOPPROT(fsync_args) *);
+int afs_vop_remove(struct VOPPROT(remove_args) *);
+int afs_vop_link(struct VOPPROT(link_args) *);
+int afs_vop_rename(struct VOPPROT(rename_args) *);
+int afs_vop_mkdir(struct VOPPROT(mkdir_args) *);
+int afs_vop_rmdir(struct VOPPROT(rmdir_args) *);
+int afs_vop_symlink(struct VOPPROT(symlink_args) *);
+int afs_vop_readdir(struct VOPPROT(readdir_args) *);
+int afs_vop_readlink(struct VOPPROT(readlink_args) *);
+int afs_vop_inactive(struct VOPPROT(inactive_args) *);
+int afs_vop_reclaim(struct VOPPROT(reclaim_args) *);
+int afs_vop_strategy(struct VOPPROT(strategy_args) *);
+int afs_vop_pathconf(struct VOPPROT(pathconf_args) *);
+int afs_vop_advlock(struct VOPPROT(advlock_args) *);
+int afs_vop_blktooff __P((struct VOPPROT(blktooff_args) *));
+int afs_vop_offtoblk __P((struct VOPPROT(offtoblk_args) *));
+#ifndef AFS_DARWIN80_ENV
+int afs_vop_truncate(struct VOPPROT(truncate_args) *);
+int afs_vop_update(struct VOPPROT(update_args) *);
+int afs_vop_lock(struct VOPPROT(lock_args) *);
+int afs_vop_unlock(struct VOPPROT(unlock_args) *);
+int afs_vop_bmap(struct VOPPROT(bmap_args) *);
+int afs_vop_seek(struct VOPPROT(seek_args) *);
+int afs_vop_cmap __P((struct VOPPROT(cmap_args) *));
+int afs_vop_print(struct VOPPROT(print_args) *);
+int afs_vop_islocked(struct VOPPROT(islocked_args) *);
+#endif
#define afs_vop_opnotsupp \
((int (*) __P((struct vop_reallocblks_args *)))eopnotsupp)
#define afs_vop_reallocblks afs_vop_opnotsupp
/* Global vfs data structures for AFS. */
-int (**afs_vnodeop_p)();
+int (**afs_vnodeop_p) ();
+
+#define VOPFUNC int (*)(void *)
+
struct vnodeopv_entry_desc afs_vnodeop_entries[] = {
- { &vop_default_desc, vn_default_error },
- { &vop_lookup_desc, afs_vop_lookup }, /* lookup */
- { &vop_create_desc, afs_vop_create }, /* create */
- { &vop_mknod_desc, afs_vop_mknod }, /* mknod */
- { &vop_open_desc, afs_vop_open }, /* open */
- { &vop_close_desc, afs_vop_close }, /* close */
- { &vop_access_desc, afs_vop_access }, /* access */
- { &vop_getattr_desc, afs_vop_getattr }, /* getattr */
- { &vop_setattr_desc, afs_vop_setattr }, /* setattr */
- { &vop_read_desc, afs_vop_read }, /* read */
- { &vop_write_desc, afs_vop_write }, /* write */
- { &vop_pagein_desc, afs_vop_pagein }, /* read */
- { &vop_pageout_desc, afs_vop_pageout }, /* write */
- { &vop_ioctl_desc, afs_vop_ioctl }, /* XXX ioctl */
- { &vop_select_desc, afs_vop_select }, /* select */
- { &vop_mmap_desc, afs_vop_mmap }, /* mmap */
- { &vop_fsync_desc, afs_vop_fsync }, /* fsync */
- { &vop_seek_desc, afs_vop_seek }, /* seek */
- { &vop_remove_desc, afs_vop_remove }, /* remove */
- { &vop_link_desc, afs_vop_link }, /* link */
- { &vop_rename_desc, afs_vop_rename }, /* rename */
- { &vop_mkdir_desc, afs_vop_mkdir }, /* mkdir */
- { &vop_rmdir_desc, afs_vop_rmdir }, /* rmdir */
- { &vop_symlink_desc, afs_vop_symlink }, /* symlink */
- { &vop_readdir_desc, afs_vop_readdir }, /* readdir */
- { &vop_readlink_desc, afs_vop_readlink }, /* readlink */
- /* Yes, we use the ufs_abortop call. It just releases the namei
- buffer stuff */
- { &vop_abortop_desc, ufs_abortop }, /* abortop */
- { &vop_inactive_desc, afs_vop_inactive }, /* inactive */
- { &vop_reclaim_desc, afs_vop_reclaim }, /* reclaim */
- { &vop_lock_desc, afs_vop_lock }, /* lock */
- { &vop_unlock_desc, afs_vop_unlock }, /* unlock */
- { &vop_bmap_desc, afs_vop_bmap }, /* bmap */
- { &vop_strategy_desc, afs_vop_strategy }, /* strategy */
- { &vop_print_desc, afs_vop_print }, /* print */
- { &vop_islocked_desc, afs_vop_islocked }, /* islocked */
- { &vop_pathconf_desc, afs_vop_pathconf }, /* pathconf */
- { &vop_advlock_desc, afs_vop_advlock }, /* advlock */
- { &vop_blkatoff_desc, afs_vop_blkatoff }, /* blkatoff */
- { &vop_valloc_desc, afs_vop_valloc }, /* valloc */
- { &vop_reallocblks_desc, afs_vop_reallocblks }, /* reallocblks */
- { &vop_vfree_desc, afs_vop_vfree }, /* vfree */
- { &vop_truncate_desc, afs_vop_truncate }, /* truncate */
- { &vop_update_desc, afs_vop_update }, /* update */
- { &vop_blktooff_desc, afs_vop_blktooff }, /* blktooff */
- { &vop_offtoblk_desc, afs_vop_offtoblk }, /* offtoblk */
- { &vop_cmap_desc, afs_vop_cmap }, /* cmap */
- { &vop_bwrite_desc, vn_bwrite },
- { (struct vnodeop_desc*)NULL, (int(*)())NULL }
+ {VOPPREF(default_desc), (VOPFUNC)vn_default_error},
+ {VOPPREF(lookup_desc), (VOPFUNC)afs_vop_lookup}, /* lookup */
+ {VOPPREF(create_desc), (VOPFUNC)afs_vop_create}, /* create */
+ {VOPPREF(mknod_desc), (VOPFUNC)afs_vop_mknod}, /* mknod */
+ {VOPPREF(open_desc), (VOPFUNC)afs_vop_open}, /* open */
+ {VOPPREF(close_desc), (VOPFUNC)afs_vop_close}, /* close */
+ {VOPPREF(access_desc), (VOPFUNC)afs_vop_access}, /* access */
+ {VOPPREF(getattr_desc), (VOPFUNC)afs_vop_getattr}, /* getattr */
+ {VOPPREF(setattr_desc), (VOPFUNC)afs_vop_setattr}, /* setattr */
+ {VOPPREF(read_desc), (VOPFUNC)afs_vop_read}, /* read */
+ {VOPPREF(write_desc), (VOPFUNC)afs_vop_write}, /* write */
+ {VOPPREF(pagein_desc), (VOPFUNC)afs_vop_pagein}, /* read */
+ {VOPPREF(pageout_desc), (VOPFUNC)afs_vop_pageout}, /* write */
+ {VOPPREF(ioctl_desc), (VOPFUNC)afs_vop_ioctl}, /* XXX ioctl */
+ {VOPPREF(select_desc), (VOPFUNC)afs_vop_select}, /* select */
+ {VOPPREF(mmap_desc), (VOPFUNC)afs_vop_mmap}, /* mmap */
+ {VOPPREF(fsync_desc), (VOPFUNC)afs_vop_fsync}, /* fsync */
+#ifndef AFS_DARWIN80_ENV
+ {VOPPREF(seek_desc), (VOPFUNC)afs_vop_seek}, /* seek */
+#endif
+ {VOPPREF(remove_desc), (VOPFUNC)afs_vop_remove}, /* remove */
+ {VOPPREF(link_desc), (VOPFUNC)afs_vop_link}, /* link */
+ {VOPPREF(rename_desc), (VOPFUNC)afs_vop_rename}, /* rename */
+ {VOPPREF(mkdir_desc), (VOPFUNC)afs_vop_mkdir}, /* mkdir */
+ {VOPPREF(rmdir_desc), (VOPFUNC)afs_vop_rmdir}, /* rmdir */
+ {VOPPREF(symlink_desc), (VOPFUNC)afs_vop_symlink}, /* symlink */
+ {VOPPREF(readdir_desc), (VOPFUNC)afs_vop_readdir}, /* readdir */
+ {VOPPREF(readlink_desc), (VOPFUNC)afs_vop_readlink}, /* readlink */
+#ifndef AFS_DARWIN80_ENV
+ {VOPPREF(abortop_desc), (VOPFUNC)nop_abortop }, /* abortop */
+#endif
+ {VOPPREF(inactive_desc), (VOPFUNC)afs_vop_inactive}, /* inactive */
+ {VOPPREF(reclaim_desc), (VOPFUNC)afs_vop_reclaim}, /* reclaim */
+#ifndef AFS_DARWIN80_ENV
+ {VOPPREF(lock_desc), (VOPFUNC)afs_vop_lock}, /* lock */
+ {VOPPREF(unlock_desc), (VOPFUNC)afs_vop_unlock}, /* unlock */
+ {VOPPREF(bmap_desc), (VOPFUNC)afs_vop_bmap}, /* bmap */
+#endif
+#ifdef AFS_DARWIN80_ENV
+ {VOPPREF(strategy_desc), (VOPFUNC)err_strategy}, /* strategy */
+#else
+ {VOPPREF(strategy_desc), (VOPFUNC)afs_vop_strategy}, /* strategy */
+#endif
+#ifndef AFS_DARWIN80_ENV
+ {VOPPREF(print_desc), (VOPFUNC)afs_vop_print}, /* print */
+ {VOPPREF(islocked_desc), (VOPFUNC)afs_vop_islocked}, /* islocked */
+#endif
+ {VOPPREF(pathconf_desc), (VOPFUNC)afs_vop_pathconf}, /* pathconf */
+ {VOPPREF(advlock_desc), (VOPFUNC)afs_vop_advlock}, /* advlock */
+#ifndef AFS_DARWIN80_ENV
+ {VOPPREF(blkatoff_desc), (VOPFUNC)afs_vop_blkatoff}, /* blkatoff */
+ {VOPPREF(valloc_desc), (VOPFUNC)afs_vop_valloc}, /* valloc */
+ {VOPPREF(reallocblks_desc), (VOPFUNC)afs_vop_reallocblks}, /* reallocblks */
+ {VOPPREF(vfree_desc), (VOPFUNC)afs_vop_vfree}, /* vfree */
+ {VOPPREF(update_desc), (VOPFUNC)afs_vop_update}, /* update */
+ {VOPPREF(cmap_desc), (VOPFUNC)afs_vop_cmap}, /* cmap */
+ {VOPPREF(truncate_desc), (VOPFUNC)afs_vop_truncate}, /* truncate */
+#endif
+ {VOPPREF(blktooff_desc), (VOPFUNC)afs_vop_blktooff}, /* blktooff */
+ {VOPPREF(offtoblk_desc), (VOPFUNC)afs_vop_offtoblk}, /* offtoblk */
+ {VOPPREF(bwrite_desc), (VOPFUNC)vn_bwrite},
+ {(struct vnodeop_desc *)NULL, (void (*)())NULL}
};
struct vnodeopv_desc afs_vnodeop_opv_desc =
- { &afs_vnodeop_p, afs_vnodeop_entries };
+ { &afs_vnodeop_p, afs_vnodeop_entries };
+
+#ifdef AFS_DARWIN80_ENV
+/* vfs structures for incompletely initialized vnodes */
+int (**afs_dead_vnodeop_p) ();
+
+struct vnodeopv_entry_desc afs_dead_vnodeop_entries[] = {
+ {VOPPREF(default_desc), (VOPFUNC)vn_default_error},
+ {VOPPREF(lookup_desc), (VOPFUNC)vn_default_error}, /* lookup */
+ {VOPPREF(create_desc), (VOPFUNC)err_create}, /* create */
+ {VOPPREF(mknod_desc), (VOPFUNC)err_mknod}, /* mknod */
+ {VOPPREF(open_desc), (VOPFUNC)err_open}, /* open */
+ {VOPPREF(close_desc), (VOPFUNC)err_close}, /* close */
+ {VOPPREF(access_desc), (VOPFUNC)err_access}, /* access */
+ {VOPPREF(getattr_desc), (VOPFUNC)err_getattr}, /* getattr */
+ {VOPPREF(setattr_desc), (VOPFUNC)err_setattr}, /* setattr */
+ {VOPPREF(read_desc), (VOPFUNC)err_read}, /* read */
+ {VOPPREF(write_desc), (VOPFUNC)err_write}, /* write */
+ {VOPPREF(pagein_desc), (VOPFUNC)err_pagein}, /* read */
+ {VOPPREF(pageout_desc), (VOPFUNC)err_pageout}, /* write */
+ {VOPPREF(ioctl_desc), (VOPFUNC)err_ioctl}, /* XXX ioctl */
+ {VOPPREF(select_desc), (VOPFUNC)nop_select}, /* select */
+ {VOPPREF(mmap_desc), (VOPFUNC)err_mmap}, /* mmap */
+ {VOPPREF(fsync_desc), (VOPFUNC)err_fsync}, /* fsync */
+ {VOPPREF(remove_desc), (VOPFUNC)err_remove}, /* remove */
+ {VOPPREF(link_desc), (VOPFUNC)err_link}, /* link */
+ {VOPPREF(rename_desc), (VOPFUNC)err_rename}, /* rename */
+ {VOPPREF(mkdir_desc), (VOPFUNC)err_mkdir}, /* mkdir */
+ {VOPPREF(rmdir_desc), (VOPFUNC)err_rmdir}, /* rmdir */
+ {VOPPREF(symlink_desc), (VOPFUNC)err_symlink}, /* symlink */
+ {VOPPREF(readdir_desc), (VOPFUNC)err_readdir}, /* readdir */
+ {VOPPREF(readlink_desc), (VOPFUNC)err_readlink}, /* readlink */
+ {VOPPREF(inactive_desc), (VOPFUNC)afs_vop_inactive}, /* inactive */
+ {VOPPREF(reclaim_desc), (VOPFUNC)afs_vop_reclaim}, /* reclaim */
+ {VOPPREF(strategy_desc), (VOPFUNC)err_strategy}, /* strategy */
+ {VOPPREF(pathconf_desc), (VOPFUNC)err_pathconf}, /* pathconf */
+ {VOPPREF(advlock_desc), (VOPFUNC)err_advlock}, /* advlock */
+ {VOPPREF(blktooff_desc), (VOPFUNC)err_blktooff}, /* blktooff */
+ {VOPPREF(offtoblk_desc), (VOPFUNC)err_offtoblk}, /* offtoblk */
+ {VOPPREF(bwrite_desc), (VOPFUNC)err_bwrite},
+ {(struct vnodeop_desc *)NULL, (void (*)())NULL}
+};
+struct vnodeopv_desc afs_dead_vnodeop_opv_desc =
+ { &afs_dead_vnodeop_p, afs_dead_vnodeop_entries };
+#endif
#define GETNAME() \
struct componentname *cnp = ap->a_cnp; \
name[cnp->cn_namelen] = '\0'
#define DROPNAME() FREE(name, M_TEMP)
-
+void
+darwin_vn_hold(struct vnode *vp)
+{
+ int haveGlock=ISAFS_GLOCK();
+ struct vcache *tvc = VTOAFS(vp);
+#ifndef AFS_DARWIN80_ENV
+ tvc->f.states |= CUBCinit;
+#endif
+#ifdef AFS_DARWIN80_ENV
+ osi_Assert((tvc->f.states & CVInit) == 0);
+ if (tvc->f.states & CDeadVnode)
+ osi_Assert(!vnode_isinuse(vp, 1));
+#endif
+ if (haveGlock) AFS_GUNLOCK();
+
+#ifdef AFS_DARWIN80_ENV
+ if (vnode_get(vp)) {
+ /* being terminated. kernel won't give us a ref. Now what? our
+ callers don't expect us to fail */
+ if (haveGlock) AFS_GLOCK();
+ return;
+ }
+ if (vnode_ref(vp)) {
+ vnode_put(vp);
+ if (haveGlock) AFS_GLOCK();
+ return;
+ }
+ vnode_put(vp);
+#else
+ /* vget needed for 0 ref'd vnode in GetVCache to not panic in vref.
+ vref needed for multiref'd vnode in vnop_remove not to deadlock
+ ourselves during vop_inactive, except we also need to not reinst
+ the ubc... so we just call VREF there now anyway. */
+
+ if (VREFCOUNT_GT(tvc, 0))
+ VREF(((struct vnode *)(vp)));
+ else
+ afs_vget(afs_globalVFS, 0, (vp));
+#endif
+
+#ifndef AFS_DARWIN80_ENV
+ if (UBCINFOMISSING(vp) || UBCINFORECLAIMED(vp)) {
+ ubc_info_init(vp);
+ }
+#endif
+
+ if (haveGlock) AFS_GLOCK();
+#ifndef AFS_DARWIN80_ENV
+ tvc->f.states &= ~CUBCinit;
+#endif
+}
int
afs_vop_lookup(ap)
-struct vop_lookup_args /* {
- struct vnodeop_desc * a_desc;
- struct vnode *a_dvp;
- struct vnode **a_vpp;
- struct componentname *a_cnp;
- } */ *ap;
+ struct VOPPROT(lookup_args)/* {
+ * struct vnodeop_desc * a_desc;
+ * struct vnode *a_dvp;
+ * struct vnode **a_vpp;
+ * struct componentname *a_cnp;
+ * } */ *ap;
{
int error;
struct vcache *vcp;
struct vnode *vp, *dvp;
- register int flags = ap->a_cnp->cn_flags;
- int lockparent; /* 1 => lockparent flag is set */
- int wantparent; /* 1 => wantparent or lockparent flag */
+ int flags = ap->a_cnp->cn_flags;
+ int lockparent; /* 1 => lockparent flag is set */
+ int wantparent; /* 1 => wantparent or lockparent flag */
struct proc *p;
+#ifdef AFS_DARWIN80_ENV
+ vcp = VTOAFS(ap->a_dvp);
+ /*
+ * ._ file attribute mirroring touches this.
+ * we can't flag the vcache as there is none, so fail here.
+ * needed for fsevents support.
+ */
+ if (ap->a_context == afs_osi_ctxtp)
+ return ENOENT;
+ if (vcp->mvstat != 1) {
+ error = cache_lookup(ap->a_dvp, ap->a_vpp, ap->a_cnp);
+ if (error == -1)
+ return 0;
+ if (error == ENOENT)
+ return error;
+ }
+#endif
+
GETNAME();
- p=cnp->cn_proc;
+ p = vop_cn_proc;
+
lockparent = flags & LOCKPARENT;
- wantparent = flags & (LOCKPARENT|WANTPARENT);
+ wantparent = flags & (LOCKPARENT | WANTPARENT);
- if (ap->a_dvp->v_type != VDIR) {
+ if (!vnode_isdir(ap->a_dvp)) {
*ap->a_vpp = 0;
DROPNAME();
return ENOTDIR;
}
dvp = ap->a_dvp;
- if (flags & ISDOTDOT)
- VOP_UNLOCK(dvp, 0, p);
+#ifndef AFS_DARWIN80_ENV
+ if (flags & ISDOTDOT)
+ VOP_UNLOCK(dvp, 0, p);
+#endif
AFS_GLOCK();
- error = afs_lookup(VTOAFS(dvp), name, &vcp, cnp->cn_cred);
+ error = afs_lookup(VTOAFS(dvp), name, &vcp, vop_cn_cred);
AFS_GUNLOCK();
if (error) {
- if (flags & ISDOTDOT)
- VOP_LOCK(dvp, LK_EXCLUSIVE | LK_RETRY, p);
- if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME) &&
- (flags & ISLASTCN) && error == ENOENT)
+#ifndef AFS_DARWIN80_ENV
+ if (flags & ISDOTDOT)
+ VOP_LOCK(dvp, LK_EXCLUSIVE | LK_RETRY, p);
+#endif
+ if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME)
+ && (flags & ISLASTCN) && error == ENOENT)
error = EJUSTRETURN;
+#ifndef AFS_DARWIN80_ENV
if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
cnp->cn_flags |= SAVENAME;
+#endif
DROPNAME();
*ap->a_vpp = 0;
return (error);
}
- vp = AFSTOV(vcp); /* always get a node if no error */
+#ifdef AFS_DARWIN80_ENV
+ if ((error=afs_darwin_finalizevnode(vcp, ap->a_dvp, ap->a_cnp, 0, 0))) {
+ DROPNAME();
+ *ap->a_vpp = 0;
+ return error;
+ }
+#endif
+ vp = AFSTOV(vcp); /* always get a node if no error */
+#ifndef AFS_DARWIN80_ENV /* XXX needed for multi-mount thing, but can't have it yet */
+ vp->v_vfsp = dvp->v_vfsp;
+
+ if (UBCINFOMISSING(vp) ||
+ UBCINFORECLAIMED(vp)) {
+ ubc_info_init(vp);
+ }
+#endif
+#ifndef AFS_DARWIN80_ENV
/* The parent directory comes in locked. We unlock it on return
- unless the caller wants it left locked.
- we also always return the vnode locked. */
+ * unless the caller wants it left locked.
+ * we also always return the vnode locked. */
if (flags & ISDOTDOT) {
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
- /* always return the child locked */
- if (lockparent && (flags & ISLASTCN) &&
- (error = vn_lock(dvp, LK_EXCLUSIVE, p))) {
- vput(vp);
- DROPNAME();
- return (error);
- }
+ /* always return the child locked */
+ if (lockparent && (flags & ISLASTCN)
+ && (error = vn_lock(dvp, LK_EXCLUSIVE, p))) {
+ vput(vp);
+ DROPNAME();
+ return (error);
+ }
} else if (vp == dvp) {
/* they're the same; afs_lookup() already ref'ed the leaf.
- It came in locked, so we don't need to ref OR lock it */
+ * It came in locked, so we don't need to ref OR lock it */
} else {
if (!lockparent || !(flags & ISLASTCN))
- VOP_UNLOCK(dvp, 0, p); /* done with parent. */
+ VOP_UNLOCK(dvp, 0, p); /* done with parent. */
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
- /* always return the child locked */
+ /* always return the child locked */
}
+#endif
*ap->a_vpp = vp;
- if ((cnp->cn_nameiop == RENAME && wantparent && (flags & ISLASTCN) ||
- (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))))
+#ifndef AFS_DARWIN80_ENV
+ if ((cnp->cn_nameiop == RENAME && wantparent && (flags & ISLASTCN)
+ || (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))))
cnp->cn_flags |= SAVENAME;
+#endif
DROPNAME();
return error;
int
afs_vop_create(ap)
- struct vop_create_args /* {
- struct vnode *a_dvp;
- struct vnode **a_vpp;
- struct componentname *a_cnp;
- struct vattr *a_vap;
- } */ *ap;
+ struct VOPPROT(create_args) /* {
+ * struct vnode *a_dvp;
+ * struct vnode **a_vpp;
+ * struct componentname *a_cnp;
+ * struct vattr *a_vap;
+ * } */ *ap;
{
int error = 0;
struct vcache *vcp;
- register struct vnode *dvp = ap->a_dvp;
+ struct vnode *dvp = ap->a_dvp;
struct proc *p;
GETNAME();
- p=cnp->cn_proc;
+ p = vop_cn_proc;
/* vnode layer handles excl/nonexcl */
AFS_GLOCK();
- error = afs_create(VTOAFS(dvp), name, ap->a_vap, NONEXCL,
- ap->a_vap->va_mode, &vcp,
- cnp->cn_cred);
+ error =
+ afs_create(VTOAFS(dvp), name, ap->a_vap, NONEXCL, ap->a_vap->va_mode,
+ &vcp, vop_cn_cred);
AFS_GUNLOCK();
if (error) {
+#ifndef AFS_DARWIN80_ENV
VOP_ABORTOP(dvp, cnp);
vput(dvp);
+#endif
DROPNAME();
- return(error);
+ return (error);
}
if (vcp) {
+#ifdef AFS_DARWIN80_ENV
+ if ((error=afs_darwin_finalizevnode(vcp, ap->a_dvp, ap->a_cnp, 0, 0))) {
+ DROPNAME();
+ *ap->a_vpp=0;
+ return error;
+ }
+#endif
*ap->a_vpp = AFSTOV(vcp);
- vn_lock(*ap->a_vpp, LK_EXCLUSIVE| LK_RETRY, p);
- if (UBCINFOMISSING(*ap->a_vpp) ||
- UBCINFORECLAIMED(*ap->a_vpp))
- ubc_info_init(*ap->a_vpp);
- }
- else *ap->a_vpp = 0;
+#ifndef AFS_DARWIN80_ENV /* XXX needed for multi-mount thing, but can't have it yet */
+ (*ap->a_vpp)->v_vfsp = dvp->v_vfsp;
+ vn_lock(*ap->a_vpp, LK_EXCLUSIVE | LK_RETRY, p);
+ if (UBCINFOMISSING(*ap->a_vpp) || UBCINFORECLAIMED(*ap->a_vpp)) {
+ vcp->f.states |= CUBCinit;
+ ubc_info_init(*ap->a_vpp);
+ vcp->f.states &= ~CUBCinit;
+ }
+#endif
+ } else
+ *ap->a_vpp = 0;
+#ifndef AFS_DARWIN80_ENV
if ((cnp->cn_flags & SAVESTART) == 0)
FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
vput(dvp);
+#endif
DROPNAME();
return error;
}
int
afs_vop_mknod(ap)
- struct vop_mknod_args /* {
- struct vnode *a_dvp;
- struct vnode **a_vpp;
- struct componentname *a_cnp;
- struct vattr *a_vap;
- } */ *ap;
+ struct VOPPROT(mknod_args) /* {
+ * struct vnode *a_dvp;
+ * struct vnode **a_vpp;
+ * struct componentname *a_cnp;
+ * struct vattr *a_vap;
+ * } */ *ap;
{
+#ifndef AFS_DARWIN80_ENV
FREE_ZONE(ap->a_cnp->cn_pnbuf, ap->a_cnp->cn_pnlen, M_NAMEI);
vput(ap->a_dvp);
- return(ENODEV);
+#endif
+ return (ENODEV);
}
int
afs_vop_open(ap)
- struct vop_open_args /* {
- struct vnode *a_vp;
- int a_mode;
- struct ucred *a_cred;
- struct proc *a_p;
- } */ *ap;
+ struct VOPPROT(open_args) /* {
+ * struct vnode *a_vp;
+ * int a_mode;
+ * struct ucred *a_cred;
+ * struct proc *a_p;
+ * } */ *ap;
{
int error;
- struct vcache *vc = VTOAFS(ap->a_vp);
+ struct vnode *vp = ap->a_vp;
+ struct vcache *vc = VTOAFS(vp);
+#if !defined(AFS_DARWIN80_ENV)
+ int didhold = 0;
+ /*----------------------------------------------------------------
+ * osi_VM_TryReclaim() removes the ubcinfo of a vnode, but that vnode
+ * can later be passed to vn_open(), which will skip the call to
+ * ubc_hold(), and when the ubcinfo is later added, the ui_refcount
+ * will be off. So we compensate by calling ubc_hold() ourselves
+ * when ui_refcount is less than 2. If an error occurs in afs_open()
+ * we must call ubc_rele(), which is what vn_open() would do if it
+ * was able to call ubc_hold() in the first place.
+ *----------------------------------------------------------------*/
+ if (vp->v_type == VREG && !(vp->v_flag & VSYSTEM)
+ && vp->v_ubcinfo->ui_refcount < 2)
+ didhold = ubc_hold(vp);
+#endif /* !AFS_DARWIN80_ENV */
AFS_GLOCK();
- error = afs_open(&vc, ap->a_mode, ap->a_cred);
+ error = afs_open(&vc, ap->a_mode, vop_cred);
#ifdef DIAGNOSTIC
- if (AFSTOV(vc) != ap->a_vp)
+ if (AFSTOV(vc) != vp)
panic("AFS open changed vnode!");
#endif
- afs_BozonLock(&vc->pvnLock, vc);
- osi_FlushPages(vc);
- afs_BozonUnlock(&vc->pvnLock, vc);
+ osi_FlushPages(vc, vop_cred);
AFS_GUNLOCK();
+#if !defined(AFS_DARWIN80_ENV)
+ if (error && didhold)
+ ubc_rele(vp);
+#endif /* !AFS_DARWIN80_ENV */
return error;
}
int
afs_vop_close(ap)
- struct vop_close_args /* {
- struct vnode *a_vp;
- int a_fflag;
- struct ucred *a_cred;
- struct proc *a_p;
- } */ *ap;
+ struct VOPPROT(close_args) /* {
+ * struct vnode *a_vp;
+ * int a_fflag;
+ * struct ucred *a_cred;
+ * struct proc *a_p;
+ * } */ *ap;
{
int code;
- struct vcache *avc=ap->a_vp;
+ struct vnode *vp = ap->a_vp;
+ struct vcache *avc = VTOAFS(vp);
+ /* allows faking FSE_CONTENT_MODIFIED */
+ if (afs_osi_ctxtp == ap->a_context)
+ return 0;
AFS_GLOCK();
- if (ap->a_cred)
- code=afs_close(avc, ap->a_fflag, ap->a_cred, ap->a_p);
+ if (vop_cred)
+ code = afs_close(avc, ap->a_fflag, vop_cred);
else
- code=afs_close(avc, ap->a_fflag, &afs_osi_cred, ap->a_p);
- afs_BozonLock(&avc->pvnLock, avc);
- osi_FlushPages(avc); /* hold bozon lock, but not basic vnode lock */
- afs_BozonUnlock(&avc->pvnLock, avc);
+ code = afs_close(avc, ap->a_fflag, &afs_osi_cred);
+ osi_FlushPages(avc, vop_cred); /* hold bozon lock, but not basic vnode lock */
+ /* This is legit; it just forces the fstrace event to happen */
+ code = afs_CheckCode(code, NULL, 60);
AFS_GUNLOCK();
-#ifdef AFS_DARWIN14_ENV
- if (UBCINFOEXISTS(ap->a_vp) && ap->a_vp->v_ubcinfo->ui_refcount < 2) {
- ubc_hold(ap->a_vp);
- if (ap->a_vp->v_ubcinfo->ui_refcount < 2) {
- printf("afs: Imminent ui_refcount panic\n");
- } else {
- printf("afs: WARNING: ui_refcount panic averted\n");
- }
- }
-#endif
return code;
}
+#ifdef AFS_DARWIN80_ENV
+extern int afs_fakestat_enable;
+
int
afs_vop_access(ap)
- struct vop_access_args /* {
- struct vnode *a_vp;
- int a_mode;
- struct ucred *a_cred;
- struct proc *a_p;
- } */ *ap;
+ struct VOPPROT(access_args) /* {
+ * struct vnode *a_vp;
+ * int a_action;
+ * vfs_context_t a_context;
+ * } */ *ap;
{
int code;
+ struct vrequest treq;
+ struct afs_fakestat_state fakestate;
+ struct vcache * tvc = VTOAFS(ap->a_vp);
+ int bits=0;
+ int cmb = CHECK_MODE_BITS;
+#ifdef AFS_DARWIN80_ENV
+ /*
+ * needed for fsevents. ._ file attribute mirroring touches this.
+ * we can't flag the vcache, as there is none, so fail here.
+ */
+ if (ap->a_context == afs_osi_ctxtp)
+ return ENOENT;
+#endif
AFS_GLOCK();
- code=afs_access(VTOAFS(ap->a_vp), ap->a_mode, ap->a_cred);
+ afs_InitFakeStat(&fakestate);
+ if ((code = afs_InitReq(&treq, vop_cred)))
+ goto out2;
+
+ code = afs_TryEvalFakeStat(&tvc, &fakestate, &treq);
+ if (code) {
+ code = afs_CheckCode(code, &treq, 55);
+ goto out;
+ }
+
+ code = afs_VerifyVCache(tvc, &treq);
+ if (code) {
+ code = afs_CheckCode(code, &treq, 56);
+ goto out;
+ }
+ if (afs_fakestat_enable && tvc->mvstat && !(tvc->f.states & CStatd)) {
+ code = 0;
+ goto out;
+ }
+ if (vnode_isdir(ap->a_vp)) {
+ if (ap->a_action & KAUTH_VNODE_LIST_DIRECTORY)
+ bits |= PRSFS_LOOKUP;
+ if (ap->a_action & KAUTH_VNODE_ADD_FILE)
+ bits |= PRSFS_INSERT;
+ if (ap->a_action & KAUTH_VNODE_SEARCH)
+ bits |= PRSFS_LOOKUP;
+ if (ap->a_action & KAUTH_VNODE_DELETE)
+ bits |= PRSFS_DELETE;
+ if (ap->a_action & KAUTH_VNODE_ADD_SUBDIRECTORY)
+ bits |= PRSFS_INSERT;
+ if (ap->a_action & KAUTH_VNODE_DELETE_CHILD)
+ bits |= PRSFS_DELETE;
+#if 0 /* I'd argue this should be enforced on the parent. But that's ugly */
+ if (ap->a_action & KAUTH_VNODE_READ_ATTRIBUTES)
+ bits |= PRSFS_LOOKUP;
+ if (ap->a_action & KAUTH_VNODE_READ_SECURITY) /* mode bits/gid, not afs acl */
+ bits |= PRSFS_LOOKUP;
+#endif
+ } else {
+ if (ap->a_action & KAUTH_VNODE_READ_DATA)
+ bits |= PRSFS_READ;
+ if (ap->a_action & KAUTH_VNODE_WRITE_DATA)
+ bits |= PRSFS_WRITE;
+ if (ap->a_action & KAUTH_VNODE_EXECUTE)
+ bits |= PRSFS_READ; /* and mode bits.... */
+ if (ap->a_action & KAUTH_VNODE_READ_ATTRIBUTES)
+ bits |= PRSFS_LOOKUP;
+ if (ap->a_action & KAUTH_VNODE_READ_SECURITY) /* mode bits/gid, not afs acl */
+ bits |= PRSFS_LOOKUP;
+ if ((ap->a_action & ((1 << 25) - 1)) == KAUTH_VNODE_EXECUTE)
+ /* if only exec, don't check for read mode bit */
+ /* high bits of ap->a_action are not for 'generic rights bits', and
+ so should not be checked (KAUTH_VNODE_ACCESS is often present
+ and needs to be masked off) */
+ cmb |= CMB_ALLOW_EXEC_AS_READ;
+ }
+ if (ap->a_action & KAUTH_VNODE_WRITE_ATTRIBUTES)
+ bits |= PRSFS_WRITE;
+#if 0 /* no extended attributes */
+ if (ap->a_action & KAUTH_VNODE_READ_EXTATTRIBUTES)
+ bits |= PRSFS_READ;
+ if (ap->a_action & KAUTH_VNODE_WRITE_EXTATTRIBUTES)
+ bits |= PRSFS_WRITE;
+#endif
+ if (ap->a_action & KAUTH_VNODE_WRITE_SECURITY)
+ bits |= PRSFS_WRITE;
+ /* we can't check for KAUTH_VNODE_TAKE_OWNERSHIP, so we always permit it */
+
+ code = afs_AccessOK(tvc, bits, &treq, cmb);
+ /*
+ * Special cased dropbox handling:
+ * cp on 10.4 behaves badly, looping on EACCES
+ * Finder may reopen the file. Let it.
+ */
+ if (code == 0 && ((bits &~(PRSFS_READ|PRSFS_WRITE)) == 0))
+ code = afs_AccessOK(tvc, PRSFS_ADMINISTER|PRSFS_INSERT|bits, &treq, cmb);
+ /* Finder also treats dropboxes as insert+delete. fake it out. */
+ if (code == 0 && (bits == (PRSFS_INSERT|PRSFS_DELETE)))
+ code = afs_AccessOK(tvc, PRSFS_INSERT, &treq, cmb);
+
+ if (code == 1 && vnode_vtype(ap->a_vp) == VREG &&
+ ap->a_action & KAUTH_VNODE_EXECUTE &&
+ (tvc->f.m.Mode & 0100) != 0100) {
+ code = 0;
+ }
+ if (code) {
+ code= 0; /* if access is ok */
+ } else {
+ code = afs_CheckCode(EACCES, &treq, 57); /* failure code */
+ }
+out:
+ afs_PutFakeStat(&fakestate);
+out2:
AFS_GUNLOCK();
return code;
}
+#else
int
-afs_vop_getattr(ap)
- struct vop_getattr_args /* {
- struct vnode *a_vp;
- struct vattr *a_vap;
- struct ucred *a_cred;
- struct proc *a_p;
- } */ *ap;
+afs_vop_access(ap)
+ struct VOPPROT(access_args) /* {
+ * struct vnode *a_vp;
+ * int a_mode;
+ * struct ucred *a_cred;
+ * struct proc *a_p;
+ * } */ *ap;
{
int code;
AFS_GLOCK();
- code=afs_getattr(VTOAFS(ap->a_vp), ap->a_vap, ap->a_cred);
+ code = afs_access(VTOAFS(ap->a_vp), ap->a_mode, vop_cred);
AFS_GUNLOCK();
return code;
}
+#endif
+
int
-afs_vop_setattr(ap)
- struct vop_setattr_args /* {
- struct vnode *a_vp;
- struct vattr *a_vap;
- struct ucred *a_cred;
- struct proc *a_p;
- } */ *ap;
+afs_vop_getattr(ap)
+ struct VOPPROT(getattr_args) /* {
+ * struct vnode *a_vp;
+ * struct vattr *a_vap;
+ * struct ucred *a_cred;
+ * struct proc *a_p;
+ * } */ *ap;
{
int code;
+
+#ifdef AFS_DARWIN80_ENV
+ /* CEvent excludes the fsevent. our context excludes the ._ */
+ if ((VTOAFS(ap->a_vp)->f.states & CEvent) ||
+ (ap->a_context == afs_osi_ctxtp)){
+ struct vcache *avc = VTOAFS(ap->a_vp);
+ int isglock = ISAFS_GLOCK();
+
+ /* this is needed because of how and when we re-enter */
+ if (!isglock)
+ AFS_GLOCK();
+ /* do minimal work to return fake result for fsevents */
+ if (afs_fakestat_enable && VTOAFS(ap->a_vp)->mvstat == 1) {
+ struct afs_fakestat_state fakestat;
+ struct vrequest treq;
+
+ code = afs_InitReq(&treq, vop_cred);
+ if (code) {
+ if (!isglock)
+ AFS_GUNLOCK();
+ return code;
+ }
+ afs_InitFakeStat(&fakestat);
+ /* expects GLOCK */
+ code = afs_TryEvalFakeStat(&avc, &fakestat, &treq);
+ if (code) {
+ if (!isglock)
+ AFS_GUNLOCK();
+ afs_PutFakeStat(&fakestat);
+ return code;
+ }
+ }
+ code = afs_CopyOutAttrs(avc, ap->a_vap);
+ if (!isglock)
+ AFS_GUNLOCK();
+ if (0 && !code) {
+ /* tweak things so finder will recheck */
+ (ap->a_vap)->va_gid = ((ap->a_vap)->va_gid == 1) ? 2 : 1;
+ (ap->a_vap)->va_mode &= ~(VSGID);
+ }
+ } else
+#endif
+ {
+ AFS_GLOCK();
+ code = afs_getattr(VTOAFS(ap->a_vp), ap->a_vap, vop_cred);
+ /* This is legit; it just forces the fstrace event to happen */
+ code = afs_CheckCode(code, NULL, 58);
+ AFS_GUNLOCK();
+ }
+#ifdef AFS_DARWIN80_ENV
+ VATTR_SET_SUPPORTED(ap->a_vap, va_type);
+ VATTR_SET_SUPPORTED(ap->a_vap, va_mode);
+ VATTR_SET_SUPPORTED(ap->a_vap, va_uid);
+ VATTR_SET_SUPPORTED(ap->a_vap, va_gid);
+ VATTR_SET_SUPPORTED(ap->a_vap, va_fsid);
+ VATTR_SET_SUPPORTED(ap->a_vap, va_fileid);
+ VATTR_SET_SUPPORTED(ap->a_vap, va_nlink);
+ VATTR_SET_SUPPORTED(ap->a_vap, va_data_size);
+ VATTR_SET_SUPPORTED(ap->a_vap, va_access_time);
+ VATTR_SET_SUPPORTED(ap->a_vap, va_modify_time);
+ VATTR_SET_SUPPORTED(ap->a_vap, va_change_time);
+ VATTR_SET_SUPPORTED(ap->a_vap, va_gen);
+ VATTR_SET_SUPPORTED(ap->a_vap, va_flags);
+ VATTR_SET_SUPPORTED(ap->a_vap, va_iosize);
+ VATTR_SET_SUPPORTED(ap->a_vap, va_total_alloc);
+#endif
+ return code;
+}
+
+int
+afs_vop_setattr(ap)
+ struct VOPPROT(setattr_args) /* {
+ * struct vnode *a_vp;
+ * struct vattr *a_vap;
+ * struct ucred *a_cred;
+ * struct proc *a_p;
+ * } */ *ap;
+{
+ int code, pass = 0;
+ struct vcache *avc = VTOAFS(ap->a_vp);
+#ifdef AFS_DARWIN80_ENV
+ /* fsevents tries to set attributes. drop it. */
+ if (ap->a_context == afs_osi_ctxtp)
+ return 0;
+#endif
AFS_GLOCK();
- code=afs_setattr(VTOAFS(ap->a_vp), ap->a_vap, ap->a_cred);
+retry:
+ code = afs_setattr(avc, ap->a_vap, vop_cred);
+ /* This is legit; it just forces the fstrace event to happen */
+ code = afs_CheckCode(code, NULL, 59);
+ if (!pass && code == EINVAL && (VATTR_IS_ACTIVE(ap->a_vap, va_mode) &&
+ (vType(avc) == VLNK))) {
+ VATTR_CLEAR_ACTIVE(ap->a_vap, va_mode);
+ pass++;
+ goto retry;
+ }
AFS_GUNLOCK();
return code;
}
+
int
afs_vop_read(ap)
- struct vop_read_args /* {
- struct vnode *a_vp;
- struct uio *a_uio;
- int a_ioflag;
- struct ucred *a_cred;
- } */ *ap;
+ struct VOPPROT(read_args) /* {
+ * struct vnode *a_vp;
+ * struct uio *a_uio;
+ * int a_ioflag;
+ * struct ucred *a_cred;
+ * } */ *ap;
{
int code;
- struct vcache *avc=VTOAFS(ap->a_vp);
+ struct vnode *vp = ap->a_vp;
+ struct vcache *avc = VTOAFS(vp);
+
+ if (vnode_isdir(ap->a_vp))
+ return EISDIR;
+#ifdef AFS_DARWIN80_ENV
+ ubc_msync_range(ap->a_vp, AFS_UIO_OFFSET(ap->a_uio), AFS_UIO_OFFSET(ap->a_uio) + AFS_UIO_RESID(ap->a_uio), UBC_PUSHDIRTY);
+#else
+ if (UBCINFOEXISTS(ap->a_vp)) {
+ ubc_clean(ap->a_vp, 0);
+ }
+#endif
AFS_GLOCK();
- afs_BozonLock(&avc->pvnLock, avc);
- osi_FlushPages(avc); /* hold bozon lock, but not basic vnode lock */
- code=afs_read(avc, ap->a_uio, ap->a_cred, 0, 0, 0);
- afs_BozonUnlock(&avc->pvnLock, avc);
+ osi_FlushPages(avc, vop_cred); /* hold bozon lock, but not basic vnode lock */
+ code = afs_read(avc, ap->a_uio, vop_cred, 0);
AFS_GUNLOCK();
return code;
}
+
int
afs_vop_pagein(ap)
- struct vop_pagein_args /* {
- struct vnode *a_vp;
- upl_t a_pl;
- vm_offset_t a_pl_offset;
- off_t a_f_offset;
- size_t a_size;
- struct ucred *a_cred;
- int a_flags;
- } */ *ap;
+ struct VOPPROT(pagein_args) /* {
+ * struct vnode *a_vp;
+ * upl_t a_pl;
+ * vm_offset_t a_pl_offset;
+ * off_t a_f_offset;
+ * size_t a_size;
+ * struct ucred *a_cred;
+ * int a_flags;
+ * } */ *ap;
{
- register struct vnode *vp = ap->a_vp;
+ struct vnode *vp = ap->a_vp;
upl_t pl = ap->a_pl;
- size_t size= ap->a_size;
+ size_t size = ap->a_size;
off_t f_offset = ap->a_f_offset;
vm_offset_t pl_offset = ap->a_pl_offset;
- int flags = ap->a_flags;
+ int flags = ap->a_flags;
struct ucred *cred;
vm_offset_t ioaddr;
- struct uio auio;
- struct iovec aiov;
- struct uio * uio = &auio;
+#ifdef AFS_DARWIN80_ENV
+ struct uio *uio;
+#else
+ struct uio auio;
+ struct iovec aiov;
+ struct uio *uio = &auio;
+#endif
int nocommit = flags & UPL_NOCOMMIT;
int code;
- struct vcache *tvc=VTOAFS(vp);
-
+ struct vcache *tvc = VTOAFS(vp);
+#ifndef AFS_DARWIN80_ENV
if (UBCINVALID(vp)) {
#if DIAGNOSTIC
- panic("afs_vop_pagein: invalid vp");
+ panic("afs_vop_pagein: invalid vp");
#endif /* DIAGNOSTIC */
- return (EPERM);
+ return (EPERM);
}
UBCINFOCHECK("afs_vop_pagein", vp);
- if(pl == (upl_t)NULL) {
- panic("afs_vop_pagein: no upl");
+#endif
+ if (pl == (upl_t) NULL) {
+ panic("afs_vop_pagein: no upl");
}
cred = ubc_getcred(vp);
if (cred == NOCRED)
- cred = ap->a_cred;
+ cred = vop_cred;
if (size == 0) {
- if (!nocommit)
- kernel_upl_abort_range(pl, pl_offset, size,
- UPL_ABORT_ERROR | UPL_ABORT_FREE_ON_EMPTY);
- return (0);
+ if (!nocommit)
+ OSI_UPL_ABORT_RANGE(pl, pl_offset, size,
+ UPL_ABORT_ERROR | UPL_ABORT_FREE_ON_EMPTY);
+ return (0);
}
if (f_offset < 0) {
- if (!nocommit)
- kernel_upl_abort_range(pl, pl_offset, size,
- UPL_ABORT_ERROR | UPL_ABORT_FREE_ON_EMPTY);
- return (EINVAL);
+ if (!nocommit)
+ OSI_UPL_ABORT_RANGE(pl, pl_offset, size,
+ UPL_ABORT_ERROR | UPL_ABORT_FREE_ON_EMPTY);
+ return (EINVAL);
}
if (f_offset & PAGE_MASK)
- panic("afs_vop_pagein: offset not page aligned");
+ panic("afs_vop_pagein: offset not page aligned");
+ OSI_UPL_MAP(pl, &ioaddr);
+ ioaddr += pl_offset;
+#ifdef AFS_DARWIN80_ENV
+ uio = uio_create(1, f_offset, UIO_SYSSPACE32, UIO_READ);
+ uio_addiov(uio, CAST_USER_ADDR_T(ioaddr), size);
+#else
auio.uio_iov = &aiov;
auio.uio_iovcnt = 1;
auio.uio_offset = f_offset;
auio.uio_segflg = UIO_SYSSPACE;
auio.uio_rw = UIO_READ;
auio.uio_procp = NULL;
- kernel_upl_map(kernel_map, pl, &ioaddr);
- ioaddr += pl_offset;
auio.uio_resid = aiov.iov_len = size;
- aiov.iov_base = (caddr_t)ioaddr;
+ aiov.iov_base = (caddr_t) ioaddr;
+#endif
AFS_GLOCK();
- afs_BozonLock(&tvc->pvnLock, tvc);
- osi_FlushPages(tvc); /* hold bozon lock, but not basic vnode lock */
- code=afs_read(tvc, uio, cred, 0, 0, 0);
+ osi_FlushPages(tvc, vop_cred); /* hold bozon lock, but not basic vnode lock */
+ code = afs_read(tvc, uio, cred, 0);
if (code == 0) {
- ObtainWriteLock(&tvc->lock, 2);
- tvc->states |= CMAPPED;
- ReleaseWriteLock(&tvc->lock);
+ ObtainWriteLock(&tvc->lock, 2);
+ tvc->f.states |= CMAPPED;
+ ReleaseWriteLock(&tvc->lock);
}
- afs_BozonUnlock(&tvc->pvnLock, tvc);
AFS_GUNLOCK();
- kernel_upl_unmap(kernel_map, pl);
+
+ /* Zero out rest of last page if there wasn't enough data in the file */
+ if (code == 0 && AFS_UIO_RESID(uio) > 0) {
+#ifdef AFS_DARWIN80_ENV
+ memset(((caddr_t)ioaddr) + (size - AFS_UIO_RESID(uio)), 0,
+ AFS_UIO_RESID(uio));
+#else
+ memset(aiov.iov_base, 0, auio.uio_resid);
+#endif
+ }
+
+ OSI_UPL_UNMAP(pl);
if (!nocommit) {
- if (code)
- kernel_upl_abort_range(pl, pl_offset, size,
- UPL_ABORT_ERROR | UPL_ABORT_FREE_ON_EMPTY);
- else
- kernel_upl_commit_range(pl, pl_offset, size,
- UPL_COMMIT_CLEAR_DIRTY | UPL_COMMIT_FREE_ON_EMPTY,
- UPL_GET_INTERNAL_PAGE_LIST(pl), MAX_UPL_TRANSFER);
+ if (code)
+ OSI_UPL_ABORT_RANGE(pl, pl_offset, size,
+ UPL_ABORT_ERROR | UPL_ABORT_FREE_ON_EMPTY);
+ else
+ OSI_UPL_COMMIT_RANGE(pl, pl_offset, size,
+ UPL_COMMIT_CLEAR_DIRTY |
+ UPL_COMMIT_FREE_ON_EMPTY);
}
+#ifdef AFS_DARWIN80_ENV
+ uio_free(uio);
+#endif
return code;
}
int
afs_vop_write(ap)
- struct vop_write_args /* {
- struct vnode *a_vp;
- struct uio *a_uio;
- int a_ioflag;
- struct ucred *a_cred;
- } */ *ap;
+ struct VOPPROT(write_args) /* {
+ * struct vnode *a_vp;
+ * struct uio *a_uio;
+ * int a_ioflag;
+ * struct ucred *a_cred;
+ * } */ *ap;
{
int code;
- struct vcache *avc=VTOAFS(ap->a_vp);
+ struct vcache *avc = VTOAFS(ap->a_vp);
void *object;
- AFS_GLOCK();
- afs_BozonLock(&avc->pvnLock, avc);
- osi_FlushPages(avc); /* hold bozon lock, but not basic vnode lock */
- if (UBCINFOEXISTS(ap->a_vp))
- ubc_clean(ap->a_vp, 1);
+#ifdef AFS_DARWIN80_ENV
+ ubc_msync_range(ap->a_vp, AFS_UIO_OFFSET(ap->a_uio), AFS_UIO_OFFSET(ap->a_uio) + AFS_UIO_RESID(ap->a_uio), UBC_INVALIDATE);
+#else
+ if (UBCINFOEXISTS(ap->a_vp)) {
+ ubc_clean(ap->a_vp, 1);
+ }
if (UBCINFOEXISTS(ap->a_vp))
- osi_VM_NukePages(ap->a_vp, ap->a_uio->uio_offset, ap->a_uio->uio_resid);
- code=afs_write(VTOAFS(ap->a_vp), ap->a_uio, ap->a_ioflag, ap->a_cred, 0);
- afs_BozonUnlock(&avc->pvnLock, avc);
+ osi_VM_NukePages(ap->a_vp, AFS_UIO_OFFSET(ap->a_uio),
+ AFS_UIO_RESID(ap->a_uio));
+#endif
+ AFS_GLOCK();
+ osi_FlushPages(avc, vop_cred); /* hold bozon lock, but not basic vnode lock */
+ code =
+ afs_write(VTOAFS(ap->a_vp), ap->a_uio, ap->a_ioflag, vop_cred, 0);
AFS_GUNLOCK();
return code;
}
int
afs_vop_pageout(ap)
- struct vop_pageout_args /* {
- struct vnode *a_vp;
- upl_t a_pl,
- vm_offset_t a_pl_offset,
- off_t a_f_offset,
- size_t a_size,
- struct ucred *a_cred,
- int a_flags
- } */ *ap;
+ struct VOPPROT(pageout_args) /* {
+ * struct vnode *a_vp;
+ * upl_t a_pl,
+ * vm_offset_t a_pl_offset,
+ * off_t a_f_offset,
+ * size_t a_size,
+ * struct ucred *a_cred,
+ * int a_flags
+ * } */ *ap;
{
- register struct vnode *vp = ap->a_vp;
+ struct vnode *vp = ap->a_vp;
upl_t pl = ap->a_pl;
- size_t size= ap->a_size;
+ size_t size = ap->a_size;
off_t f_offset = ap->a_f_offset;
vm_offset_t pl_offset = ap->a_pl_offset;
- int flags = ap->a_flags;
+ int flags = ap->a_flags;
struct ucred *cred;
vm_offset_t ioaddr;
- struct uio auio;
- struct iovec aiov;
- struct uio * uio = &auio;
+#ifdef AFS_DARWIN80_ENV
+ struct uio *uio;
+#else
+ struct uio auio;
+ struct iovec aiov;
+ struct uio *uio = &auio;
+#endif
int nocommit = flags & UPL_NOCOMMIT;
+ int iosize;
int code;
- struct vcache *tvc=VTOAFS(vp);
-
+ struct vcache *tvc = VTOAFS(vp);
+#ifndef AFS_DARWIN80_ENV
if (UBCINVALID(vp)) {
#if DIAGNOSTIC
- panic("afs_vop_pageout: invalid vp");
+ panic("afs_vop_pageout: invalid vp");
#endif /* DIAGNOSTIC */
- return (EPERM);
+ return (EPERM);
}
UBCINFOCHECK("afs_vop_pageout", vp);
- if(pl == (upl_t)NULL) {
- panic("afs_vop_pageout: no upl");
+#endif
+ if (pl == (upl_t) NULL) {
+ panic("afs_vop_pageout: no upl");
}
-#if 1
- { int lbn, iosize, s;
- struct buf *bp;
- int biosize = DEV_BSIZE;
-
- lbn = f_offset / DEV_BSIZE;
-
- for (iosize = size; iosize > 0; iosize -= biosize, lbn++) {
-
- s = splbio();
- if (bp = incore(vp, lbn)) {
- if (ISSET(bp->b_flags, B_BUSY))
- panic("nfs_pageout: found BUSY buffer incore\n")
-;
-
- bremfree(bp);
- SET(bp->b_flags, (B_BUSY | B_INVAL));
- brelse(bp);
- }
- splx(s);
- }
+#if !defined(AFS_DARWIN80_ENV) /* XXX nfs now uses it's own bufs (struct nfsbuf)
+ maybe the generic
+ layer doesn't have them anymore? In any case,
+ we can't just copy code from nfs... */
+ {
+ int lbn, s;
+ struct buf *bp;
+ int biosize = DEV_BSIZE;
+
+ lbn = f_offset / DEV_BSIZE;
+
+ for (iosize = size; iosize > 0; iosize -= biosize, lbn++) {
+
+ s = splbio();
+ if (bp = incore(vp, lbn)) {
+ if (ISSET(bp->b_flags, B_BUSY))
+ panic("nfs_pageout: found BUSY buffer incore\n");
+
+ bremfree(bp);
+ SET(bp->b_flags, (B_BUSY | B_INVAL));
+ brelse(bp);
+ }
+ splx(s);
+ }
}
#endif
cred = ubc_getcred(vp);
if (cred == NOCRED)
- cred = ap->a_cred;
+ cred = vop_cred;
if (size == 0) {
- if (!nocommit)
- kernel_upl_abort_range(pl, pl_offset, size,
- UPL_ABORT_FREE_ON_EMPTY);
- return (0);
+ if (!nocommit)
+ OSI_UPL_ABORT_RANGE(pl, pl_offset, size,
+ UPL_ABORT_FREE_ON_EMPTY);
+ return (0);
}
if (flags & (IO_APPEND | IO_SYNC))
- panic("nfs_pageout: (IO_APPEND | IO_SYNC)");
+ panic("nfs_pageout: (IO_APPEND | IO_SYNC)");
if (f_offset < 0) {
- if (!nocommit)
- kernel_upl_abort_range(pl, pl_offset, size,
- UPL_ABORT_FREE_ON_EMPTY);
- return (EINVAL);
+ if (!nocommit)
+ OSI_UPL_ABORT_RANGE(pl, pl_offset, size,
+ UPL_ABORT_FREE_ON_EMPTY);
+ return (EINVAL);
}
- if (f_offset >= tvc->m.Length) {
- if (!nocommit)
- kernel_upl_abort_range(pl, pl_offset, size,
- UPL_ABORT_FREE_ON_EMPTY);
- return (EINVAL);
+ if (f_offset >= tvc->f.m.Length) {
+ if (!nocommit)
+ OSI_UPL_ABORT_RANGE(pl, pl_offset, size,
+ UPL_ABORT_FREE_ON_EMPTY);
+ return (EINVAL);
}
if (f_offset & PAGE_MASK)
- panic("afs_vop_pageout: offset not page aligned");
+ panic("afs_vop_pageout: offset not page aligned");
+
+ /* size will always be a multiple of PAGE_SIZE */
+ /* pageout isn't supposed to extend files */
+ if (f_offset + size > tvc->f.m.Length)
+ iosize = tvc->f.m.Length - f_offset;
+ else
+ iosize = size;
+ if (size > (iosize + (PAGE_SIZE - 1)) & ~PAGE_MASK && !nocommit) {
+ int iosize_rnd=(iosize + (PAGE_SIZE - 1)) & ~PAGE_MASK;
+ OSI_UPL_ABORT_RANGE(pl, pl_offset + iosize_rnd,
+ size - iosize_rnd,
+ UPL_ABORT_FREE_ON_EMPTY);
+ }
+ OSI_UPL_MAP(pl, &ioaddr);
+ ioaddr += pl_offset;
+#ifdef AFS_DARWIN80_ENV
+ uio = uio_create(1, f_offset, UIO_SYSSPACE32, UIO_READ);
+ uio_addiov(uio, CAST_USER_ADDR_T(ioaddr), size);
+#else
auio.uio_iov = &aiov;
auio.uio_iovcnt = 1;
auio.uio_offset = f_offset;
auio.uio_segflg = UIO_SYSSPACE;
auio.uio_rw = UIO_WRITE;
auio.uio_procp = NULL;
- kernel_upl_map(kernel_map, pl, &ioaddr);
- ioaddr += pl_offset;
- auio.uio_resid = aiov.iov_len = size;
- aiov.iov_base = (caddr_t)ioaddr;
-#if 1 /* USV [ */
- {
- /*
- * check for partial page and clear the
- * contents past end of the file before
- * releasing it in the VM page cache
- */
- if ((f_offset < tvc->m.Length) && (f_offset + size) > tvc->m.Length) {
- size_t io = tvc->m.Length - f_offset;
-
- memset((caddr_t)(ioaddr + pl_offset + io), 0, size - io);
- }
- }
-#endif /* ] USV */
+ auio.uio_resid = aiov.iov_len = iosize;
+ aiov.iov_base = (caddr_t) ioaddr;
+#endif
+ {
+ /* USV?
+ * check for partial page and clear the
+ * contents past end of the file before
+ * releasing it in the VM page cache
+ */
+ if ((f_offset < tvc->f.m.Length) && (f_offset + size) > tvc->f.m.Length) {
+ size_t io = tvc->f.m.Length - f_offset;
+
+ memset((caddr_t) (ioaddr + pl_offset + io), 0, size - io);
+ }
+ }
AFS_GLOCK();
- afs_BozonLock(&tvc->pvnLock, tvc);
- osi_FlushPages(tvc); /* hold bozon lock, but not basic vnode lock */
+ osi_FlushPages(tvc, vop_cred); /* hold bozon lock, but not basic vnode lock */
ObtainWriteLock(&tvc->lock, 1);
afs_FakeOpen(tvc);
ReleaseWriteLock(&tvc->lock);
- code=afs_write(tvc, uio, flags, cred, 0);
+ code = afs_write(tvc, uio, flags, cred, 0);
ObtainWriteLock(&tvc->lock, 1);
afs_FakeClose(tvc, cred);
ReleaseWriteLock(&tvc->lock);
- afs_BozonUnlock(&tvc->pvnLock, tvc);
AFS_GUNLOCK();
- kernel_upl_unmap(kernel_map, pl);
+ OSI_UPL_UNMAP(pl);
if (!nocommit) {
- if(code)
- kernel_upl_abort_range(pl, pl_offset, size,
- UPL_ABORT_FREE_ON_EMPTY);
- else
- kernel_upl_commit_range(pl, pl_offset, size,
- UPL_COMMIT_CLEAR_DIRTY | UPL_COMMIT_FREE_ON_EMPTY,
- UPL_GET_INTERNAL_PAGE_LIST(pl), MAX_UPL_TRANSFER);
+ if (code)
+ OSI_UPL_ABORT_RANGE(pl, pl_offset, size,
+ UPL_ABORT_FREE_ON_EMPTY);
+ else
+ OSI_UPL_COMMIT_RANGE(pl, pl_offset, size,
+ UPL_COMMIT_CLEAR_DIRTY |
+ UPL_COMMIT_FREE_ON_EMPTY);
}
+#ifdef AFS_DARWIN80_ENV
+ uio_free(uio);
+#endif
return code;
}
+
int
afs_vop_ioctl(ap)
- struct vop_ioctl_args /* {
- struct vnode *a_vp;
- int a_command;
- caddr_t a_data;
- int a_fflag;
- struct ucred *a_cred;
- struct proc *a_p;
- } */ *ap;
+ struct VOPPROT(ioctl_args) /* {
+ * struct vnode *a_vp;
+ * int a_command;
+ * caddr_t a_data;
+ * int a_fflag;
+ * struct ucred *a_cred;
+ * struct proc *a_p;
+ * } */ *ap;
{
struct vcache *tvc = VTOAFS(ap->a_vp);
struct afs_ioctl data;
int error = 0;
-
+
/* in case we ever get in here... */
AFS_STATCNT(afs_ioctl);
if (((ap->a_command >> 8) & 0xff) == 'V') {
/* This is a VICEIOCTL call */
- AFS_GLOCK();
- error = HandleIoctl(tvc, (struct file *)0/*Not used*/,
- ap->a_command, ap->a_data);
- AFS_GUNLOCK();
- return(error);
+ AFS_GLOCK();
+ error = HandleIoctl(tvc, ap->a_command, ap->a_data);
+ AFS_GUNLOCK();
+ return (error);
} else {
/* No-op call; just return. */
- return(ENOTTY);
+ return (ENOTTY);
}
}
/* ARGSUSED */
int
afs_vop_select(ap)
- struct vop_select_args /* {
- struct vnode *a_vp;
- int a_which;
- int a_fflags;
- struct ucred *a_cred;
- struct proc *a_p;
- } */ *ap;
+ struct VOPPROT(select_args) /* {
+ * struct vnode *a_vp;
+ * int a_which;
+ * int a_fflags;
+ * struct ucred *a_cred;
+ * struct proc *a_p;
+ * } */ *ap;
{
- /*
- * We should really check to see if I/O is possible.
- */
- return (1);
+ /*
+ * We should really check to see if I/O is possible.
+ */
+ return (1);
}
+
/*
* Mmap a file
*
/* ARGSUSED */
int
afs_vop_mmap(ap)
- struct vop_mmap_args /* {
- struct vnode *a_vp;
- int a_fflags;
- struct ucred *a_cred;
- struct proc *a_p;
- } */ *ap;
+ struct VOPPROT(mmap_args) /* {
+ * struct vnode *a_vp;
+ * int a_fflags;
+ * struct ucred *a_cred;
+ * struct proc *a_p;
+ * } */ *ap;
{
- return (EINVAL);
+ return (EINVAL);
}
int
afs_vop_fsync(ap)
- struct vop_fsync_args /* {
- struct vnode *a_vp;
- struct ucred *a_cred;
- int a_waitfor;
- struct proc *a_p;
- } */ *ap;
+ struct VOPPROT(fsync_args) /* {
+ * struct vnode *a_vp;
+ * struct ucred *a_cred;
+ * int a_waitfor;
+ * struct proc *a_p;
+ * } */ *ap;
{
int wait = ap->a_waitfor == MNT_WAIT;
int error;
- register struct vnode *vp = ap->a_vp;
+ struct vnode *vp = ap->a_vp;
+ int haveGlock = ISAFS_GLOCK();
- AFS_GLOCK();
- /*vflushbuf(vp, wait);*/
- if (ap->a_cred)
- error=afs_fsync(VTOAFS(vp), ap->a_cred);
+ /* in order to recycle faked vnodes for bulkstat */
+ if (VTOAFS(vp) == NULL)
+ return ENOTSUP;
+
+ /* afs_vop_lookup glocks, can call us through vinvalbuf from GetVCache */
+ if (!haveGlock) AFS_GLOCK();
+ if (vop_cred)
+ error = afs_fsync(VTOAFS(vp), vop_cred);
else
- error=afs_fsync(VTOAFS(vp), &afs_osi_cred);
- AFS_GUNLOCK();
+ error = afs_fsync(VTOAFS(vp), &afs_osi_cred);
+ if (!haveGlock) AFS_GUNLOCK();
return error;
}
+#ifndef AFS_DARWIN80_ENV
int
afs_vop_seek(ap)
- struct vop_seek_args /* {
- struct vnode *a_vp;
- off_t a_oldoff;
- off_t a_newoff;
- struct ucred *a_cred;
- } */ *ap;
+ struct VOPPROT(seek_args) /* {
+ * struct vnode *a_vp;
+ * off_t a_oldoff;
+ * off_t a_newoff;
+ * struct ucred *a_cred;
+ * } */ *ap;
{
- if (ap->a_newoff > ULONG_MAX) /* AFS doesn't support 64-bit offsets */
+ if (ap->a_newoff > ULONG_MAX) /* AFS doesn't support 64-bit offsets */
return EINVAL;
return (0);
}
+#endif
int
afs_vop_remove(ap)
- struct vop_remove_args /* {
- struct vnode *a_dvp;
- struct vnode *a_vp;
- struct componentname *a_cnp;
- } */ *ap;
+ struct VOPPROT(remove_args) /* {
+ * struct vnode *a_dvp;
+ * struct vnode *a_vp;
+ * struct componentname *a_cnp;
+ * } */ *ap;
{
int error = 0;
- register struct vnode *vp = ap->a_vp;
- register struct vnode *dvp = ap->a_dvp;
+ struct vnode *vp = ap->a_vp;
+ struct vnode *dvp = ap->a_dvp;
+
+#ifdef AFS_DARWIN80_ENV
+ if (ap->a_flags & VNODE_REMOVE_NODELETEBUSY) {
+ /* Caller requested Carbon delete semantics */
+ if (vnode_isinuse(vp, 0)) {
+ return EBUSY;
+ }
+ }
+#endif
GETNAME();
AFS_GLOCK();
- error = afs_remove(VTOAFS(dvp), name, cnp->cn_cred);
+ error = afs_remove(VTOAFS(dvp), name, vop_cn_cred);
+ error = afs_CheckCode(error, NULL, 61);
AFS_GUNLOCK();
cache_purge(vp);
- if (!error && UBCINFOEXISTS(vp)) {
-#ifdef AFS_DARWIN14_ENV
- (void) ubc_uncache(vp);
+ if (!error) {
+#ifdef AFS_DARWIN80_ENV
+ struct vcache *tvc = VTOAFS(vp);
+
+ if (!(tvc->f.states & CUnlinked)) {
+ ubc_setsize(vp, (off_t)0);
+ vnode_recycle(vp);
+ }
#else
- int wasmapped=ubc_issetflags(vp, UI_WASMAPPED);
- int hasobjref=ubc_issetflags(vp, UI_HASOBJREF);
- if (wasmapped)
- (void) ubc_uncache(vp);
- if (hasobjref)
- ubc_release(vp);
- /* WARNING vp may not be valid after this */
+ /* necessary so we don't deadlock ourselves in vclean */
+ VOP_UNLOCK(vp, 0, cnp->cn_proc);
+
+ /* If crashes continue in ubc_hold, comment this out */
+ (void)ubc_uncache(vp);
#endif
+ } else {
+ /* should check for PRSFS_INSERT and not PRSFS_DELETE, but the
+ goal here is to deal with Finder's unhappiness with resource
+ forks that have no resources in a dropbox setting */
+ if (name[0] == '.' && name[1] == '_' && error == EACCES)
+ error = 0;
}
+
+#ifndef AFS_DARWIN80_ENV
+ vput(dvp);
if (dvp == vp)
vrele(vp);
else
vput(vp);
- vput(dvp);
+#endif
+#ifndef AFS_DARWIN80_ENV
FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
+#endif
DROPNAME();
return error;
}
int
afs_vop_link(ap)
- struct vop_link_args /* {
- struct vnode *a_vp;
- struct vnode *a_tdvp;
- struct componentname *a_cnp;
- } */ *ap;
+ struct VOPPROT(link_args) /* {
+ * struct vnode *a_vp;
+ * struct vnode *a_tdvp;
+ * struct componentname *a_cnp;
+ * } */ *ap;
{
int error = 0;
- register struct vnode *dvp = ap->a_tdvp;
- register struct vnode *vp = ap->a_vp;
+ struct vnode *dvp = ap->a_tdvp;
+ struct vnode *vp = ap->a_vp;
struct proc *p;
GETNAME();
- p=cnp->cn_proc;
- if (dvp->v_mount != vp->v_mount) {
- VOP_ABORTOP(vp, cnp);
- error = EXDEV;
- goto out;
- }
- if (vp->v_type == VDIR) {
+ p = vop_cn_proc;
+ if (vnode_isdir(vp)) {
VOP_ABORTOP(vp, cnp);
error = EISDIR;
goto out;
}
+#ifndef AFS_DARWIN80_ENV
if (error = vn_lock(vp, LK_EXCLUSIVE, p)) {
VOP_ABORTOP(dvp, cnp);
goto out;
}
+#endif
AFS_GLOCK();
- error = afs_link(VTOAFS(vp), VTOAFS(dvp), name, cnp->cn_cred);
+ error = afs_link(VTOAFS(vp), VTOAFS(dvp), name, vop_cn_cred);
AFS_GUNLOCK();
+#ifndef AFS_DARWIN80_ENV
FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
+#endif
+#ifndef AFS_DARWIN80_ENV
if (dvp != vp)
- VOP_UNLOCK(vp,0, p);
-out:
+ VOP_UNLOCK(vp, 0, p);
+#endif
+ out:
+#ifndef AFS_DARWIN80_ENV
vput(dvp);
+#endif
DROPNAME();
return error;
}
int
afs_vop_rename(ap)
- struct vop_rename_args /* {
- struct vnode *a_fdvp;
- struct vnode *a_fvp;
- struct componentname *a_fcnp;
- struct vnode *a_tdvp;
- struct vnode *a_tvp;
- struct componentname *a_tcnp;
- } */ *ap;
+ struct VOPPROT(rename_args) /* {
+ * struct vnode *a_fdvp;
+ * struct vnode *a_fvp;
+ * struct componentname *a_fcnp;
+ * struct vnode *a_tdvp;
+ * struct vnode *a_tvp;
+ * struct componentname *a_tcnp;
+ * } */ *ap;
{
int error = 0;
struct componentname *fcnp = ap->a_fcnp;
struct componentname *tcnp = ap->a_tcnp;
char *tname;
struct vnode *tvp = ap->a_tvp;
- register struct vnode *tdvp = ap->a_tdvp;
+ struct vnode *tdvp = ap->a_tdvp;
struct vnode *fvp = ap->a_fvp;
- register struct vnode *fdvp = ap->a_fdvp;
- struct proc *p=fcnp->cn_proc;
+ struct vnode *fdvp = ap->a_fdvp;
+ struct proc *p;
+
+ p = cn_proc(fcnp);
+#ifdef AFS_DARWIN80_ENV
/*
- * Check for cross-device rename.
+ * generic code tests for v_mount equality, so we don't have to, but we
+ * don't get the multiple-mount "benefits" of the old behavior
+ * the generic code doesn't do this, so we really should, but all the
+ * vrele's are wrong...
+ */
+#else
+ /* Check for cross-device rename.
+ * For AFS, this means anything not in AFS-space
*/
- if ((fvp->v_mount != tdvp->v_mount) ||
- (tvp && (fvp->v_mount != tvp->v_mount))) {
+ if ((0 != strcmp(tdvp->v_mount->mnt_stat.f_fstypename, "afs")) ||
+ (tvp && (0 != strcmp(tvp->v_mount->mnt_stat.f_fstypename, "afs")))) {
error = EXDEV;
-abortit:
- VOP_ABORTOP(tdvp, tcnp); /* XXX, why not in NFS? */
- if (tdvp == tvp)
- vrele(tdvp);
- else
- vput(tdvp);
- if (tvp)
- vput(tvp);
- VOP_ABORTOP(fdvp, fcnp); /* XXX, why not in NFS? */
- vrele(fdvp);
- vrele(fvp);
- return (error);
+ goto abortit;
}
+
/*
* if fvp == tvp, we're just removing one name of a pair of
* directory entries for the same element. convert call into rename.
( (pinched from NetBSD 1.0's ufs_rename())
*/
if (fvp == tvp) {
- if (fvp->v_type == VDIR) {
+ if (vnode_isdir(fvp)) {
error = EINVAL;
- goto abortit;
+ abortit:
+ VOP_ABORTOP(tdvp, tcnp); /* XXX, why not in NFS? */
+ if (tdvp == tvp)
+ vrele(tdvp);
+ else
+ vput(tdvp);
+ if (tvp)
+ vput(tvp);
+ VOP_ABORTOP(fdvp, fcnp); /* XXX, why not in NFS? */
+ vrele(fdvp);
+ vrele(fvp);
+ return (error);
}
/* Release destination completely. */
VOP_ABORTOP(tdvp, tcnp);
vput(tdvp);
vput(tvp);
-
/* Delete source. */
vrele(fdvp);
vrele(fvp);
if ((fcnp->cn_flags & SAVESTART) == 0)
panic("afs_rename: lost from startdir");
fcnp->cn_nameiop = DELETE;
- (void) relookup(fdvp, &fvp, fcnp);
- return (VOP_REMOVE(fdvp, fvp, fcnp));
+
+ VREF(fdvp);
+ error=relookup(fdvp, &fvp, fcnp);
+ if (error == 0)
+ vrele(fdvp);
+ if (fvp == NULL) {
+ return (ENOENT);
+ }
+ error=VOP_REMOVE(fdvp, fvp, fcnp);
+
+ if (fdvp == fvp)
+ vrele(fdvp);
+ else
+ vput(fdvp);
+ vput(fvp);
+ return (error);
}
if (error = vn_lock(fvp, LK_EXCLUSIVE, p))
goto abortit;
+#endif
- MALLOC(fname, char *, fcnp->cn_namelen+1, M_TEMP, M_WAITOK);
+ MALLOC(fname, char *, fcnp->cn_namelen + 1, M_TEMP, M_WAITOK);
memcpy(fname, fcnp->cn_nameptr, fcnp->cn_namelen);
fname[fcnp->cn_namelen] = '\0';
- MALLOC(tname, char *, tcnp->cn_namelen+1, M_TEMP, M_WAITOK);
+ MALLOC(tname, char *, tcnp->cn_namelen + 1, M_TEMP, M_WAITOK);
memcpy(tname, tcnp->cn_nameptr, tcnp->cn_namelen);
tname[tcnp->cn_namelen] = '\0';
AFS_GLOCK();
/* XXX use "from" or "to" creds? NFS uses "to" creds */
- error = afs_rename(VTOAFS(fdvp), fname, VTOAFS(tdvp), tname, tcnp->cn_cred);
- AFS_GUNLOCK();
+ error =
+ afs_rename(VTOAFS(fdvp), fname, VTOAFS(tdvp), tname, cn_cred(tcnp));
+#if !defined(AFS_DARWIN80_ENV)
+ AFS_GUNLOCK();
VOP_UNLOCK(fvp, 0, p);
- FREE(fname, M_TEMP);
- FREE(tname, M_TEMP);
if (error)
- goto abortit; /* XXX */
+ goto abortit; /* XXX */
if (tdvp == tvp)
vrele(tdvp);
else
vput(tvp);
vrele(fdvp);
vrele(fvp);
+#else
+ if (error == EXDEV) {
+ struct brequest *tb;
+ struct afs_uspc_param mvReq;
+ struct vcache *tvc;
+ struct vcache *fvc = VTOAFS(fdvp);
+ int code = 0;
+ struct afs_fakestat_state fakestate;
+ int fakestatdone = 0;
+
+ tvc = VTOAFS(tdvp);
+
+ /* unrewritten mount point? */
+ if (tvc->mvstat == 1) {
+ if (tvc->mvid && (tvc->f.states & CMValid)) {
+ struct vrequest treq;
+
+ afs_InitFakeStat(&fakestate);
+ code = afs_InitReq(&treq, vop_cred);
+ if (!code) {
+ fakestatdone = 1;
+ code = afs_EvalFakeStat(&tvc, &fakestate, &treq);
+ } else
+ afs_PutFakeStat(&fakestate);
+ }
+ }
+
+ if (!code) {
+ /* at some point in the future we should allow other types */
+ mvReq.reqtype = AFS_USPC_UMV;
+ mvReq.req.umv.id = afs_cr_uid(cn_cred(tcnp));
+ mvReq.req.umv.idtype = IDTYPE_UID;
+ mvReq.req.umv.sCell = fvc->f.fid.Cell;
+ mvReq.req.umv.sVolume = fvc->f.fid.Fid.Volume;
+ mvReq.req.umv.sVnode = fvc->f.fid.Fid.Vnode;
+ mvReq.req.umv.sUnique = fvc->f.fid.Fid.Unique;
+ mvReq.req.umv.dCell = tvc->f.fid.Cell;
+ mvReq.req.umv.dVolume = tvc->f.fid.Fid.Volume;
+ mvReq.req.umv.dVnode = tvc->f.fid.Fid.Vnode;
+ mvReq.req.umv.dUnique = tvc->f.fid.Fid.Unique;
+
+ /*
+ * su %d -c mv /afs/.:mount/%d:%d:%d:%d/%s
+ * /afs/.:mount/%d:%d:%d:%d/%s where:
+ * mvReq.req.umv.id, fvc->f.fid.Cell, fvc->f.fid.Fid.Volume,
+ * fvc->f.fid.Fid.Vnode, fvc->f.fid.Fid.Unique, fname,
+ * tvc->f.fid.Cell, tvc->f.fid.Fid.Volume, tvc->f.fid.Fid.Vnode,
+ * tvc->f.fid.Fid.Unique, tname
+ */
+
+ tb = afs_BQueue(BOP_MOVE, NULL, 0, 1, cn_cred(tcnp),
+ 0L, 0L, &mvReq, fname, tname);
+ /* wait to collect result */
+ while ((tb->flags & BUVALID) == 0) {
+ tb->flags |= BUWAIT;
+ afs_osi_Sleep(tb);
+ }
+ /* if we succeeded, clear the error. otherwise, EXDEV */
+ if (mvReq.retval == 0)
+ error = 0;
+
+ afs_BRelease(tb);
+ }
+
+ if (fakestatdone)
+ afs_PutFakeStat(&fakestate);
+ }
+ AFS_GUNLOCK();
+
+ cache_purge(fdvp);
+ cache_purge(fvp);
+ cache_purge(tdvp);
+ if (tvp) {
+ cache_purge(tvp);
+ if (!error) {
+ vnode_recycle(tvp);
+ }
+ }
+ if (!error)
+ cache_enter(tdvp, fvp, tcnp);
+#endif
+ FREE(fname, M_TEMP);
+ FREE(tname, M_TEMP);
return error;
}
int
afs_vop_mkdir(ap)
- struct vop_mkdir_args /* {
- struct vnode *a_dvp;
- struct vnode **a_vpp;
- struct componentname *a_cnp;
- struct vattr *a_vap;
- } */ *ap;
+ struct VOPPROT(mkdir_args) /* {
+ * struct vnode *a_dvp;
+ * struct vnode **a_vpp;
+ * struct componentname *a_cnp;
+ * struct vattr *a_vap;
+ * } */ *ap;
{
- register struct vnode *dvp = ap->a_dvp;
- register struct vattr *vap = ap->a_vap;
+ struct vnode *dvp = ap->a_dvp;
+ struct vattr *vap = ap->a_vap;
int error = 0;
struct vcache *vcp;
struct proc *p;
GETNAME();
- p=cnp->cn_proc;
-#ifdef DIAGNOSTIC
+ p = vop_cn_proc;
+#if defined(DIAGNOSTIC) && !defined(AFS_DARWIN80_ENV)
if ((cnp->cn_flags & HASBUF) == 0)
panic("afs_vop_mkdir: no name");
#endif
AFS_GLOCK();
- error = afs_mkdir(VTOAFS(dvp), name, vap, &vcp, cnp->cn_cred);
+ error = afs_mkdir(VTOAFS(dvp), name, vap, &vcp, vop_cn_cred);
AFS_GUNLOCK();
if (error) {
+#ifndef AFS_DARWIN80_ENV
VOP_ABORTOP(dvp, cnp);
vput(dvp);
+#endif
DROPNAME();
- return(error);
+ return (error);
}
if (vcp) {
+#ifdef AFS_DARWIN80_ENV
+ afs_darwin_finalizevnode(vcp, ap->a_dvp, ap->a_cnp, 0, 0);
+#endif
*ap->a_vpp = AFSTOV(vcp);
- vn_lock(*ap->a_vpp, LK_EXCLUSIVE|LK_RETRY, p);
+#ifndef AFS_DARWIN80_ENV /* XXX needed for multi-mount thing, but can't have it yet */
+ (*ap->a_vpp)->v_vfsp = dvp->v_vfsp;
+ vn_lock(*ap->a_vpp, LK_EXCLUSIVE | LK_RETRY, p);
+#endif
} else
*ap->a_vpp = 0;
DROPNAME();
+#ifndef AFS_DARWIN80_ENV
FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
vput(dvp);
+#endif
return error;
}
int
afs_vop_rmdir(ap)
- struct vop_rmdir_args /* {
- struct vnode *a_dvp;
- struct vnode *a_vp;
- struct componentname *a_cnp;
- } */ *ap;
+ struct VOPPROT(rmdir_args) /* {
+ * struct vnode *a_dvp;
+ * struct vnode *a_vp;
+ * struct componentname *a_cnp;
+ * } */ *ap;
{
int error = 0;
- register struct vnode *vp = ap->a_vp;
- register struct vnode *dvp = ap->a_dvp;
+ struct vnode *vp = ap->a_vp;
+ struct vnode *dvp = ap->a_dvp;
GETNAME();
if (dvp == vp) {
+#ifndef AFS_DARWIN80_ENV
vrele(dvp);
vput(vp);
FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
+#endif
DROPNAME();
return (EINVAL);
}
AFS_GLOCK();
- error = afs_rmdir(VTOAFS(dvp), name, cnp->cn_cred);
+ error = afs_rmdir(VTOAFS(dvp), name, vop_cn_cred);
AFS_GUNLOCK();
DROPNAME();
+ cache_purge(dvp);
+ cache_purge(vp);
+#ifndef AFS_DARWIN80_ENV
vput(dvp);
vput(vp);
+#endif
return error;
}
int
afs_vop_symlink(ap)
- struct vop_symlink_args /* {
- struct vnode *a_dvp;
- struct vnode **a_vpp;
- struct componentname *a_cnp;
- struct vattr *a_vap;
- char *a_target;
- } */ *ap;
+ struct VOPPROT(symlink_args) /* {
+ * struct vnode *a_dvp;
+ * struct vnode **a_vpp;
+ * struct componentname *a_cnp;
+ * struct vattr *a_vap;
+ * char *a_target;
+ * } */ *ap;
{
- register struct vnode *dvp = ap->a_dvp;
+ struct vnode *dvp = ap->a_dvp;
int error = 0;
/* NFS ignores a_vpp; so do we. */
GETNAME();
AFS_GLOCK();
- error = afs_symlink(VTOAFS(dvp), name, ap->a_vap, ap->a_target,
- cnp->cn_cred);
+ error =
+ afs_symlink(VTOAFS(dvp), name, ap->a_vap, ap->a_target, vop_cn_cred);
AFS_GUNLOCK();
DROPNAME();
+#ifndef AFS_DARWIN80_ENV
FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
vput(dvp);
+#endif
return error;
}
int
afs_vop_readdir(ap)
- struct vop_readdir_args /* {
- struct vnode *a_vp;
- struct uio *a_uio;
- struct ucred *a_cred;
- int *a_eofflag;
- u_long *a_cookies;
- int ncookies;
- } */ *ap;
+ struct VOPPROT(readdir_args) /* {
+ * struct vnode *a_vp;
+ * struct uio *a_uio;
+ * struct ucred *a_cred;
+ * int *a_eofflag;
+ * u_long *a_cookies;
+ * int ncookies;
+ * } */ *ap;
{
int error;
off_t off;
/* printf("readdir %x cookies %x ncookies %d\n", ap->a_vp, ap->a_cookies,
ap->a_ncookies); */
- off=ap->a_uio->uio_offset;
+#ifdef AFS_DARWIN80_ENV
+ /* too much work for now */
+ /* should only break nfs exports */
+ if (ap->a_flags & (VNODE_READDIR_EXTENDED | VNODE_READDIR_REQSEEKOFF))
+ return (EINVAL);
+#endif
+ off = AFS_UIO_OFFSET(ap->a_uio);
AFS_GLOCK();
- error= afs_readdir(VTOAFS(ap->a_vp), ap->a_uio, ap->a_cred,
- ap->a_eofflag);
+ error =
+ afs_readdir(VTOAFS(ap->a_vp), ap->a_uio, vop_cred, ap->a_eofflag);
AFS_GUNLOCK();
+#ifndef AFS_DARWIN80_ENV
if (!error && ap->a_ncookies != NULL) {
struct uio *uio = ap->a_uio;
const struct dirent *dp, *dp_start, *dp_end;
dp = (const struct dirent *)
((const char *)uio->uio_iov->iov_base - (uio->uio_offset - off));
- dp_end = (const struct dirent *) uio->uio_iov->iov_base;
- for (dp_start = dp, ncookies = 0;
- dp < dp_end;
- dp = (const struct dirent *)((const char *) dp + dp->d_reclen))
+ dp_end = (const struct dirent *)uio->uio_iov->iov_base;
+ for (dp_start = dp, ncookies = 0; dp < dp_end;
+ dp = (const struct dirent *)((const char *)dp + dp->d_reclen))
ncookies++;
- MALLOC(cookies, u_long *, ncookies * sizeof(u_long),
- M_TEMP, M_WAITOK);
- for (dp = dp_start, cookiep = cookies;
- dp < dp_end;
- dp = (const struct dirent *)((const char *) dp + dp->d_reclen)) {
+ MALLOC(cookies, u_long *, ncookies * sizeof(u_long), M_TEMP,
+ M_WAITOK);
+ for (dp = dp_start, cookiep = cookies; dp < dp_end;
+ dp = (const struct dirent *)((const char *)dp + dp->d_reclen)) {
off += dp->d_reclen;
*cookiep++ = off;
}
*ap->a_cookies = cookies;
*ap->a_ncookies = ncookies;
}
+#endif
return error;
}
int
afs_vop_readlink(ap)
- struct vop_readlink_args /* {
- struct vnode *a_vp;
- struct uio *a_uio;
- struct ucred *a_cred;
- } */ *ap;
+ struct VOPPROT(readlink_args) /* {
+ * struct vnode *a_vp;
+ * struct uio *a_uio;
+ * struct ucred *a_cred;
+ * } */ *ap;
{
int error;
/* printf("readlink %x\n", ap->a_vp);*/
AFS_GLOCK();
- error= afs_readlink(VTOAFS(ap->a_vp), ap->a_uio, ap->a_cred);
+ error = afs_readlink(VTOAFS(ap->a_vp), ap->a_uio, vop_cred);
AFS_GUNLOCK();
return error;
}
int
afs_vop_inactive(ap)
- struct vop_inactive_args /* {
- struct vnode *a_vp;
- struct proc *a_p;
- } */ *ap;
+ struct VOPPROT(inactive_args) /* {
+ * struct vnode *a_vp;
+ * struct proc *a_p;
+ * } */ *ap;
{
- register struct vnode *vp = ap->a_vp;
-
+ struct vnode *vp = ap->a_vp;
+ struct vcache *tvc = VTOAFS(vp);
+#ifndef AFS_DARWIN80_ENV
if (prtactive && vp->v_usecount != 0)
vprint("afs_vop_inactive(): pushing active", vp);
-
- AFS_GLOCK();
- afs_InactiveVCache(VTOAFS(vp), 0); /* decrs ref counts */
- AFS_GUNLOCK();
+#endif
+ if (tvc) {
+#ifdef AFS_DARWIN80_ENV
+ int unlinked = tvc->f.states & CUnlinked;
+#endif
+ AFS_GLOCK();
+ afs_InactiveVCache(tvc, 0); /* decrs ref counts */
+ AFS_GUNLOCK();
+#ifdef AFS_DARWIN80_ENV
+ if (unlinked) {
+ vnode_recycle(vp);
+ cache_purge(vp);
+ }
+#endif
+ }
+#ifndef AFS_DARWIN80_ENV
VOP_UNLOCK(vp, 0, ap->a_p);
+#endif
return 0;
}
int
afs_vop_reclaim(ap)
- struct vop_reclaim_args /* {
- struct vnode *a_vp;
- } */ *ap;
+ struct VOPPROT(reclaim_args) /* {
+ * struct vnode *a_vp;
+ * } */ *ap;
{
- int error;
- int sl;
- register struct vnode *vp = ap->a_vp;
+ int error = 0;
+ int sl, writelocked;
+ struct vnode *vp = ap->a_vp;
+ struct vcache *tvc = VTOAFS(vp);
+
+ osi_Assert(!ISAFS_GLOCK());
+ cache_purge(vp); /* just in case... */
+ if (tvc) {
+ AFS_GLOCK();
+ writelocked = (0 == NBObtainWriteLock(&afs_xvcache, 335));
+ if (!writelocked) {
+ ObtainWriteLock(&afs_xvreclaim, 176);
+#ifdef AFS_DARWIN80_ENV
+ vnode_clearfsnode(AFSTOV(tvc));
+ vnode_removefsref(AFSTOV(tvc));
+#else
+ tvc->v->v_data = NULL; /* remove from vnode */
+#endif
+ AFSTOV(tvc) = NULL; /* also drop the ptr to vnode */
+ tvc->f.states |= CVInit; /* also CDeadVnode? */
+ tvc->nextfree = ReclaimedVCList;
+ ReclaimedVCList = tvc;
+ ReleaseWriteLock(&afs_xvreclaim);
+ } else {
+ error = afs_FlushVCache(tvc, &sl); /* toss our stuff from vnode */
+ if (tvc->f.states & (CVInit
+#ifdef AFS_DARWIN80_ENV
+ | CDeadVnode
+#endif
+ )) {
+ tvc->f.states &= ~(CVInit
+#ifdef AFS_DARWIN80_ENV
+ | CDeadVnode
+#endif
+ );
+ afs_osi_Wakeup(&tvc->f.states);
+ }
+ if (!error && vnode_fsnode(vp))
+ panic("afs_reclaim: vnode not cleaned");
+ if (!error && (tvc->v != NULL))
+ panic("afs_reclaim: vcache not cleaned");
+ ReleaseWriteLock(&afs_xvcache);
+ }
+ AFS_GUNLOCK();
+ }
+ return error;
+}
- cache_purge(vp); /* just in case... */
+/*
+ * Return POSIX pathconf information applicable to ufs filesystems.
+ */
+afs_vop_pathconf(ap)
+ struct VOPPROT(pathconf_args) /* {
+ * struct vnode *a_vp;
+ * int a_name;
+ * int *a_retval;
+ * } */ *ap;
+{
+ AFS_STATCNT(afs_cntl);
+ switch (ap->a_name) {
+ case _PC_LINK_MAX:
+ *ap->a_retval = LINK_MAX;
+ break;
+ case _PC_NAME_MAX:
+ *ap->a_retval = NAME_MAX;
+ break;
+ case _PC_PATH_MAX:
+ *ap->a_retval = PATH_MAX;
+ break;
+ case _PC_CHOWN_RESTRICTED:
+ *ap->a_retval = 1;
+ break;
+ case _PC_NO_TRUNC:
+ *ap->a_retval = 1;
+ break;
+ case _PC_PIPE_BUF:
+ return EINVAL;
+ break;
+ case _PC_NAME_CHARS_MAX:
+ *ap->a_retval = NAME_MAX;
+ break;
+ case _PC_CASE_SENSITIVE:
+ *ap->a_retval = 1;
+ break;
+ case _PC_CASE_PRESERVING:
+ *ap->a_retval = 1;
+ break;
+ default:
+ return EINVAL;
+ }
+ return 0;
+}
-#if 0
+/*
+ * Advisory record locking support (fcntl() POSIX style)
+ */
+int
+afs_vop_advlock(ap)
+ struct VOPPROT(advlock_args) /* {
+ * struct vnode *a_vp;
+ * caddr_t a_id;
+ * int a_op;
+ * struct flock *a_fl;
+ * int a_flags;
+ * } */ *ap;
+{
+ int error;
+ struct ucred *tcr;
+ int clid;
+ int op;
+#ifdef AFS_DARWIN80_ENV
+ proc_t p;
+ tcr=vop_cred;
+#else
+ struct proc *p = current_proc();
+ struct ucred cr;
+ pcred_readlock(p);
+ cr = *p->p_cred->pc_ucred;
+ pcred_unlock(p);
+ tcr=&cr;
+#endif
+ if (ap->a_flags & F_POSIX) {
+#ifdef AFS_DARWIN80_ENV
+ p = (proc_t) ap->a_id;
+ clid = proc_pid(p);
+#else
+ p = (struct proc *) ap->a_id;
+ clid = p->p_pid;
+#endif
+ } else {
+ clid = (int)ap->a_id;
+ }
+ if (ap->a_op == F_UNLCK) {
+ op = F_SETLK;
+ } else if (ap->a_op == F_SETLK && ap->a_flags & F_WAIT) {
+ op = F_SETLKW;
+ } else {
+ op = ap->a_op;
+ }
AFS_GLOCK();
- error = afs_FlushVCache(VTOAFS(vp), &sl); /* tosses our stuff from vnode */
+ error = afs_lockctl(VTOAFS(ap->a_vp), ap->a_fl, op, tcr, clid);
AFS_GUNLOCK();
- ubc_unlink(vp);
- if (!error && vp->v_data)
- panic("afs_reclaim: vnode not cleaned");
return error;
-#else
- if (vp->v_usecount == 2) {
- vprint("reclaim count==2", vp);
- } else if (vp->v_usecount == 1) {
- vprint("reclaim count==1", vp);
- } else
- vprint("reclaim bad count", vp);
+}
- return 0;
-#endif
+int
+afs_vop_blktooff(ap)
+ struct VOPPROT(blktooff_args) /* {
+ * struct vnode *a_vp;
+ * daddr_t a_lblkno;
+ * off_t *a_offset;
+ * } */ *ap;
+{
+ *ap->a_offset = (off_t) (ap->a_lblkno * DEV_BSIZE);
+ return 0;
+}
+
+int
+afs_vop_offtoblk(ap)
+ struct VOPPROT(offtoblk_args) /* {
+ * struct vnode *a_vp;
+ * off_t a_offset;
+ * daddr_t *a_lblkno;
+ * } */ *ap;
+{
+ *ap->a_lblkno = (daddr_t) (ap->a_offset / DEV_BSIZE);
+
+ return (0);
}
+#ifndef AFS_DARWIN80_ENV
int
afs_vop_lock(ap)
- struct vop_lock_args /* {
- struct vnode *a_vp;
- } */ *ap;
+ struct VOPPROT(lock_args) /* {
+ * struct vnode *a_vp;
+ * } */ *ap;
{
- register struct vnode *vp = ap->a_vp;
- register struct vcache *avc = VTOAFS(vp);
+ struct vnode *vp = ap->a_vp;
+ struct vcache *avc = VTOAFS(vp);
- if (vp->v_tag == VT_NON)
- return (ENOENT);
- return (lockmgr(&avc->rwlock, ap->a_flags, &vp->v_interlock,
- ap->a_p));
+ if (vp->v_tag == VT_NON)
+ return (ENOENT);
+
+ return (lockmgr(&avc->rwlock, ap->a_flags, &vp->v_interlock, ap->a_p));
}
int
afs_vop_unlock(ap)
- struct vop_unlock_args /* {
- struct vnode *a_vp;
- } */ *ap;
+ struct VOPPROT(unlock_args) /* {
+ * struct vnode *a_vp;
+ * } */ *ap;
{
struct vnode *vp = ap->a_vp;
struct vcache *avc = VTOAFS(vp);
- return (lockmgr(&avc->rwlock, ap->a_flags | LK_RELEASE,
- &vp->v_interlock, ap->a_p));
+ return (lockmgr
+ (&avc->rwlock, ap->a_flags | LK_RELEASE, &vp->v_interlock,
+ ap->a_p));
+
+}
+
+int
+afs_vop_truncate(ap)
+ struct VOPPROT(truncate_args) /* {
+ * struct vnode *a_vp;
+ * off_t a_length;
+ * int a_flags;
+ * struct ucred *a_cred;
+ * struct proc *a_p;
+ * } */ *ap;
+{
+ /* printf("stray afs_vop_truncate\n"); */
+ return ENOTSUP;
+}
+
+int
+afs_vop_update(ap)
+ struct VOPPROT(update_args) /* {
+ * struct vnode *a_vp;
+ * struct timeval *a_access;
+ * struct timeval *a_modify;
+ * int a_waitfor;
+ * } */ *ap;
+{
+ /* printf("stray afs_vop_update\n"); */
+ return ENOTSUP;
}
int
afs_vop_bmap(ap)
- struct vop_bmap_args /* {
- struct vnode *a_vp;
- daddr_t a_bn;
- struct vnode **a_vpp;
- daddr_t *a_bnp;
- int *a_runp;
- int *a_runb;
- } */ *ap;
+ struct VOPPROT(bmap_args) /* {
+ * struct vnode *a_vp;
+ * daddr_t a_bn;
+ * struct vnode **a_vpp;
+ * daddr_t *a_bnp;
+ * int *a_runp;
+ * int *a_runb;
+ * } */ *ap;
{
- struct vcache *vcp;
int error;
if (ap->a_bnp) {
*ap->a_bnp = ap->a_bn * (PAGE_SIZE / DEV_BSIZE);
if (ap->a_vpp) {
*ap->a_vpp = ap->a_vp;
}
- if (ap->a_runp != NULL)
- *ap->a_runp = 0;
+ if (ap->a_runp != NULL)
+ *ap->a_runp = 0;
#ifdef notyet
- if (ap->a_runb != NULL)
- *ap->a_runb = 0;
+ if (ap->a_runb != NULL)
+ *ap->a_runb = 0;
#endif
-
+
return 0;
}
+
int
afs_vop_strategy(ap)
- struct vop_strategy_args /* {
- struct buf *a_bp;
- } */ *ap;
+ struct VOPPROT(strategy_args) /* {
+ * struct buf *a_bp;
+ * } */ *ap;
{
int error;
AFS_GLOCK();
- error= afs_ustrategy(ap->a_bp);
+ error = afs_ustrategy(ap->a_bp);
AFS_GUNLOCK();
return error;
}
+
int
afs_vop_print(ap)
- struct vop_print_args /* {
- struct vnode *a_vp;
- } */ *ap;
+ struct VOPPROT(print_args) /* {
+ * struct vnode *a_vp;
+ * } */ *ap;
{
- register struct vnode *vp = ap->a_vp;
- register struct vcache *vc = VTOAFS(ap->a_vp);
- int s = vc->states;
- printf("tag %d, fid: %ld.%x.%x.%x, opens %d, writers %d", vp->v_tag, vc->fid.Cell,
- vc->fid.Fid.Volume, vc->fid.Fid.Vnode, vc->fid.Fid.Unique, vc->opens,
- vc->execsOrWriters);
- printf("\n states%s%s%s%s%s", (s&CStatd) ? " statd" : "", (s&CRO) ? " readonly" : "",(s&CDirty) ? " dirty" : "",(s&CMAPPED) ? " mapped" : "", (s&CVFlushed) ? " flush in progress" : "");
+ struct vnode *vp = ap->a_vp;
+ struct vcache *vc = VTOAFS(ap->a_vp);
+ int s = vc->f.states;
+ printf("tag %d, fid: %ld.%x.%x.%x, opens %d, writers %d", vp->v_tag,
+ vc->f.fid.Cell, vc->f.fid.Fid.Volume, vc->f.fid.Fid.Vnode,
+ vc->f.fid.Fid.Unique, vc->opens, vc->execsOrWriters);
+ printf("\n states%s%s%s%s%s", (s & CStatd) ? " statd" : "",
+ (s & CRO) ? " readonly" : "", (s & CDirty) ? " dirty" : "",
+ (s & CMAPPED) ? " mapped" : "",
+ (s & CVFlushed) ? " flush in progress" : "");
if (UBCISVALID(vp)) {
- printf("\n UBC: ");
- if (UBCINFOEXISTS(vp)) {
- printf("exists, ") ;
-#ifdef AFS_DARWIN14_ENV
- printf("refs %d%s%s", vp->v_ubcinfo->ui_refcount,
- ubc_issetflags(vp, UI_HASOBJREF) ? " HASOBJREF" : "",
- ubc_issetflags(vp, UI_WASMAPPED) ? " WASMAPPED" : "");
-#else
- printf("holdcnt %d", vp->v_ubcinfo->ui_holdcnt);
-#endif
- } else printf("does not exist");
+ printf("\n UBC: ");
+ if (UBCINFOEXISTS(vp)) {
+ printf("exists, ");
+ printf("refs %d%s%s", vp->v_ubcinfo->ui_refcount,
+ ubc_issetflags(vp, UI_HASOBJREF) ? " HASOBJREF" : "",
+ ubc_issetflags(vp, UI_WASMAPPED) ? " WASMAPPED" : "");
+ } else
+ printf("does not exist");
}
printf("\n");
return 0;
int
afs_vop_islocked(ap)
- struct vop_islocked_args /* {
- struct vnode *a_vp;
- } */ *ap;
+ struct VOPPROT(islocked_args) /* {
+ * struct vnode *a_vp;
+ * } */ *ap;
{
struct vcache *vc = VTOAFS(ap->a_vp);
return lockstatus(&vc->rwlock);
}
-/*
- * Return POSIX pathconf information applicable to ufs filesystems.
- */
-afs_vop_pathconf(ap)
- struct vop_pathconf_args /* {
- struct vnode *a_vp;
- int a_name;
- int *a_retval;
- } */ *ap;
+int
+afs_vop_cmap(ap)
+ struct VOPPROT(cmap_args) /* {
+ * struct vnode *a_vp;
+ * off_t a_foffset;
+ * size_t a_size;
+ * daddr_t *a_bpn;
+ * size_t *a_run;
+ * void *a_poff;
+ * } */ *ap;
{
- AFS_STATCNT(afs_cntl);
- switch (ap->a_name) {
- case _PC_LINK_MAX:
- *ap->a_retval = LINK_MAX;
- break;
- case _PC_NAME_MAX:
- *ap->a_retval = NAME_MAX;
- break;
- case _PC_PATH_MAX:
- *ap->a_retval = PATH_MAX;
- break;
- case _PC_CHOWN_RESTRICTED:
- *ap->a_retval = 1;
- break;
- case _PC_NO_TRUNC:
- *ap->a_retval = 1;
- break;
- case _PC_PIPE_BUF:
- return EINVAL;
- break;
- default:
- return EINVAL;
- }
+ *ap->a_bpn = (daddr_t) (ap->a_foffset / DEV_BSIZE);
+ *ap->a_run = MAX(ap->a_size, AFS_CHUNKSIZE(ap->a_foffset));
return 0;
}
+#endif
-/*
- * Advisory record locking support (fcntl() POSIX style)
- */
int
-afs_vop_advlock(ap)
- struct vop_advlock_args /* {
- struct vnode *a_vp;
- caddr_t a_id;
- int a_op;
- struct flock *a_fl;
- int a_flags;
- } */ *ap;
+afs_darwin_getnewvnode(struct vcache *avc)
{
- int error;
- struct proc *p=current_proc();
- struct ucred cr;
- pcred_readlock(p);
- cr=*p->p_cred->pc_ucred;
- pcred_unlock(p);
- AFS_GLOCK();
- error= afs_lockctl(VTOAFS(ap->a_vp), ap->a_fl, ap->a_op, &cr,
- (int) ap->a_id);
- AFS_GUNLOCK();
+#ifdef AFS_DARWIN80_ENV
+ vnode_t vp;
+ int error, dead;
+ struct vnode_fsparam par;
+
+ memset(&par, 0, sizeof(struct vnode_fsparam));
+ par.vnfs_vtype = VNON;
+ par.vnfs_vops = afs_dead_vnodeop_p;
+ par.vnfs_flags = VNFS_NOCACHE|VNFS_CANTCACHE;
+ par.vnfs_mp = afs_globalVFS;
+ par.vnfs_fsnode = avc;
+
+ error = vnode_create(VNCREATE_FLAVOR, VCREATESIZE, &par, &vp);
+ if (!error) {
+ vnode_addfsref(vp);
+ vnode_ref(vp);
+ avc->v = vp;
+ vnode_recycle(vp); /* terminate as soon as iocount drops */
+ avc->f.states |= CDeadVnode;
+ }
return error;
+#else
+ while (getnewvnode(VT_AFS, afs_globalVFS, afs_vnodeop_p, &avc->v)) {
+ /* no vnodes available, force an alloc (limits be damned)! */
+ printf("failed to get vnode\n");
+ }
+ avc->v->v_data = (void *)avc;
+ return 0;
+#endif
}
-
-int
-afs_vop_truncate(ap)
- struct vop_truncate_args /* {
- struct vnode *a_vp;
- off_t a_length;
- int a_flags;
- struct ucred *a_cred;
- struct proc *a_p;
- } */ *ap;
-{
- printf("stray afs_vop_truncate\n");
- return EOPNOTSUPP;
-}
-
+#ifdef AFS_DARWIN80_ENV
+/* if this fails, then tvc has been unrefed and may have been freed.
+ Don't touch! */
int
-afs_vop_update(ap)
- struct vop_update_args /* {
- struct vnode *a_vp;
- struct timeval *a_access;
- struct timeval *a_modify;
- int a_waitfor;
- } */ *ap;
-{
- printf("stray afs_vop_update\n");
- return EOPNOTSUPP;
-}
-
-int afs_vop_blktooff(ap)
- struct vop_blktooff_args /* {
- struct vnode *a_vp;
- daddr_t a_lblkno;
- off_t *a_offset;
- } */ *ap;
+afs_darwin_finalizevnode(struct vcache *avc, struct vnode *dvp,
+ struct componentname *cnp, int isroot, int locked)
{
- *ap->a_offset = (off_t)(ap->a_lblkno * DEV_BSIZE);
- return 0;
-}
+ vnode_t ovp;
+ vnode_t nvp;
+ int error;
+ struct vnode_fsparam par;
-int afs_vop_offtoblk(ap)
- struct vop_offtoblk_args /* {
- struct vnode *a_vp;
- off_t a_offset;
- daddr_t *a_lblkno;
- } */ *ap;
-{
- *ap->a_lblkno = (daddr_t)(ap->a_offset / DEV_BSIZE);
+ if (!locked) {
+ AFS_GLOCK();
+ ObtainWriteLock(&avc->lock,325);
+ }
+ ovp = AFSTOV(avc);
+
+ if (!(avc->f.states & CDeadVnode) && vnode_vtype(ovp) != VNON) {
+ AFS_GUNLOCK();
+#if 0 /* unsupported */
+ if (dvp && cnp)
+ vnode_update_identity(ovp, dvp, cnp->cn_nameptr, cnp->cn_namelen,
+ cnp->cn_hash,
+ VNODE_UPDATE_PARENT|VNODE_UPDATE_NAME);
+#endif
+ /* Can end up in reclaim... drop GLOCK */
+ vnode_rele(ovp);
+ AFS_GLOCK();
+ if (!locked) {
+ ReleaseWriteLock(&avc->lock);
+ AFS_GUNLOCK();
+ }
+ return 0;
+ }
- return (0);
-}
+ if ((avc->f.states & CDeadVnode) && vnode_vtype(ovp) != VNON)
+ panic("vcache %p should not be CDeadVnode", avc);
+ AFS_GUNLOCK();
+ memset(&par, 0, sizeof(struct vnode_fsparam));
+ par.vnfs_mp = afs_globalVFS;
+ par.vnfs_vtype = avc->f.m.Type;
+ par.vnfs_vops = afs_vnodeop_p;
+ par.vnfs_filesize = avc->f.m.Length;
+ par.vnfs_fsnode = avc;
+ par.vnfs_dvp = dvp;
+ if (cnp && (cnp->cn_flags & ISDOTDOT) == 0)
+ par.vnfs_cnp = cnp;
+ if (!dvp || !cnp || (cnp->cn_flags & MAKEENTRY) == 0)
+ par.vnfs_flags = VNFS_NOCACHE;
+ if (isroot)
+ par.vnfs_markroot = 1;
+ error = vnode_create(VNCREATE_FLAVOR, VCREATESIZE, &par, &nvp);
+ if (!error) {
+ vnode_addfsref(nvp);
+ if ((avc->f.states & CDeadVnode) && vnode_vtype(ovp) != VNON)
+ printf("vcache %p should not be CDeadVnode", avc);
+ if (avc->v == ovp) {
+ if (!(avc->f.states & CVInit)) {
+ vnode_clearfsnode(ovp);
+ vnode_removefsref(ovp);
+ }
+ /* we're discarding on a fixup. mark for recycle */
+ if (!(avc->f.states & CDeadVnode))
+ vnode_recycle(ovp);
+ }
+ avc->v = nvp;
+ avc->f.states &=~ CDeadVnode;
+ /* If we were carrying an extra ref for dirty, hold/push it. */
+ if (avc->f.ddirty_flags) {
+ vnode_get(nvp);
+ vnode_ref(nvp);
+ }
+ /* If we were carrying an extra ref for shadow, hold/push it. */
+ if (avc->f.shadow.vnode) {
+ vnode_get(nvp);
+ vnode_ref(nvp);
+ }
+ }
+ /* Drop any extra dirty ref on the old vnode */
+ if (avc->f.ddirty_flags) {
+ vnode_put(ovp);
+ vnode_rele(ovp);
+ }
+ /* Drop any extra shadow ref on the old vnode */
+ if (avc->f.shadow.vnode) {
+ vnode_put(ovp);
+ vnode_rele(ovp);
+ }
+ /* If it's ref'd still, unmark stat'd to force new lookup */
+ if ((vnode_vtype(ovp) != avc->f.m.Type) && VREFCOUNT_GT(avc, 1))
+ avc->f.states &= ~CStatd;
-int afs_vop_cmap(ap)
- struct vop_cmap_args /* {
- struct vnode *a_vp;
- off_t a_foffset;
- size_t a_size;
- daddr_t *a_bpn;
- size_t *a_run;
- void *a_poff;
- } */ *ap;
-{
- *ap->a_bpn = (daddr_t)(ap->a_foffset / DEV_BSIZE);
- *ap->a_run= MAX(ap->a_size, AFS_CHUNKSIZE(ap->a_foffset));
- return 0;
+ vnode_put(ovp);
+ vnode_rele(ovp);
+ AFS_GLOCK();
+ if (!locked)
+ ReleaseWriteLock(&avc->lock);
+ if (!error)
+ afs_osi_Wakeup(&avc->f.states);
+ if (!locked)
+ AFS_GUNLOCK();
+ return error;
}
-
+#endif