+/*
+ * Portions Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
+ */
#include <afsconfig.h>
#include <afs/param.h>
#include <sys/malloc.h>
#include <sys/namei.h>
#include <sys/ubc.h>
+#if defined(AFS_DARWIN70_ENV)
+#include <vfs/vfs_support.h>
+#endif /* defined(AFS_DARWIN70_ENV) */
int afs_vop_lookup(struct vop_lookup_args *);
int afs_vop_create(struct vop_create_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 *);
+#if !defined(AFS_DARWIN70_ENV)
extern int ufs_abortop(struct vop_abortop_args *);
+#endif /* !defined(AFS_DARWIN70_ENV) */
int afs_vop_inactive(struct vop_inactive_args *);
int afs_vop_reclaim(struct vop_reclaim_args *);
int afs_vop_lock(struct vop_lock_args *);
{&vop_symlink_desc, afs_vop_symlink}, /* symlink */
{&vop_readdir_desc, afs_vop_readdir}, /* readdir */
{&vop_readlink_desc, afs_vop_readlink}, /* readlink */
+#if defined(AFS_DARWIN70_ENV)
+ { &vop_abortop_desc, nop_abortop }, /* abortop */
+#else /* ! defined(AFS_DARWIN70_ENV) */
/* Yes, we use the ufs_abortop call. It just releases the namei
* buffer stuff */
{&vop_abortop_desc, ufs_abortop}, /* abortop */
+#endif /* defined(AFS_DARWIN70_ENV) */
{&vop_inactive_desc, afs_vop_inactive}, /* inactive */
{&vop_reclaim_desc, afs_vop_reclaim}, /* reclaim */
{&vop_lock_desc, afs_vop_lock}, /* lock */
* } */ *ap;
{
int error;
- struct vcache *vc = VTOAFS(ap->a_vp);
+ struct vnode *vp = ap->a_vp;
+ struct vcache *vc = VTOAFS(vp);
+#ifdef AFS_DARWIN14_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_DARWIN14_ENV */
AFS_GLOCK();
error = afs_open(&vc, ap->a_mode, ap->a_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, ap->a_cred);
afs_BozonUnlock(&vc->pvnLock, vc);
AFS_GUNLOCK();
+#ifdef AFS_DARWIN14_ENV
+ if (error && didhold)
+ ubc_rele(vp);
+#endif /* AFS_DARWIN14_ENV */
return error;
}
register struct vnode *fdvp = ap->a_fdvp;
struct proc *p = fcnp->cn_proc;
+ /* Check for cross-device rename.
+ * For AFS, this means anything not in AFS-space
+ */
+ if ((0 != strcmp(tdvp->v_mount->mnt_stat.f_fstypename, "afs")) ||
+ (tvp && (0 != strcmp(tvp->v_mount->mnt_stat.f_fstypename, "afs")))) {
+ error = EXDEV;
+ 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.
case _PC_PIPE_BUF:
return EINVAL;
break;
+#if defined(AFS_DARWIN70_ENV)
+ 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;
+#endif /* defined(AFS_DARWIN70_ENV) */
default:
return EINVAL;
}