/*
* osi_misc.c
*
- * Implements:
- * afs_suser
*/
#include <afsconfig.h>
#include "afs/param.h"
-RCSID("$Header$");
#include "afs/sysincludes.h" /* Standard vendor system headers */
#include "afsincludes.h" /* Afs-based standard headers */
#include <sys/namei.h>
-#ifndef AFS_FBSD50_ENV
-/*
- * afs_suser() returns true if the caller is superuser, false otherwise.
- *
- * Note that it must NOT set errno.
- */
+int
+osi_lookupname(char *aname, enum uio_seg seg, int followlink,
+ struct vnode **vpp)
+{
+ struct nameidata n;
+ int flags, error, glocked;
-afs_suser() {
- int error;
+ glocked = ISAFS_GLOCK();
+ if (glocked)
+ AFS_GUNLOCK();
- if (suser(curproc) == 0) {
- return(1);
+#if __FreeBSD_version >= 1000021 /* MPSAFE is gone for good! */
+ flags = LOCKLEAF;
+#else
+ flags = LOCKLEAF | MPSAFE; /* namei must take Giant if needed */
+#endif
+ if (followlink)
+ flags |= FOLLOW;
+ else
+ flags |= NOFOLLOW;
+ NDINIT(&n, LOOKUP, flags, seg, aname, curthread);
+ if ((error = namei(&n)) != 0) {
+ if (glocked)
+ AFS_GLOCK();
+ return error;
}
- return(0);
-}
+ *vpp = n.ni_vp;
+ /* XXX should we do this? Usually NOT (matt) */
+#if defined(AFS_FBSD80_ENV)
+ /*VOP_UNLOCK(n.ni_vp, 0);*/
+#else
+ VOP_UNLOCK(n.ni_vp, 0, curthread);
#endif
+ NDFREE(&n, NDF_ONLY_PNBUF);
+ if (glocked)
+ AFS_GLOCK();
+ return 0;
+}
-int osi_lookupname(char *aname, enum uio_seg seg, int followlink,
- struct vnode **dirvpp, struct vnode **vpp)
+/*
+ * does not implement security features of kern_time.c:settime()
+ */
+void
+afs_osi_SetTime(osi_timeval_t * atv)
{
- struct nameidata n;
- int flags,error;
- flags=0;
- flags=LOCKLEAF;
- if (followlink)
- flags|=FOLLOW;
- else
- flags|=NOFOLLOW;
-/* if (dirvpp) flags|=WANTPARENT;*/ /* XXX LOCKPARENT? */
- NDINIT(&n, LOOKUP, flags, seg, aname, curproc);
- if (error=namei(&n))
- return error;
- *vpp=n.ni_vp;
+ printf("afs attempted to set clock; use \"afsd -nosettime\"\n");
+}
+
/*
- if (dirvpp)
- *dirvpp = n.ni_dvp;
-*/
- /* should we do this? */
- VOP_UNLOCK(n.ni_vp, 0, curproc);
- NDFREE(&n, NDF_ONLY_PNBUF);
- return 0;
+ * Replace all of the bogus special-purpose memory allocators...
+ */
+void *
+osi_fbsd_alloc(size_t size, int dropglobal)
+{
+ void *rv;
+ int glocked;
+
+ if (dropglobal) {
+ glocked = ISAFS_GLOCK();
+ if (glocked)
+ AFS_GUNLOCK();
+ rv = malloc(size, M_AFS, M_WAITOK);
+ if (glocked)
+ AFS_GLOCK();
+ } else
+ rv = malloc(size, M_AFS, M_NOWAIT);
+
+ return (rv);
+}
+
+void
+osi_fbsd_free(void *p)
+{
+ free(p, M_AFS);
+}
+
+/**
+ * check if a vcache is in use
+ *
+ * @return status
+ * @retcode 0 success
+ * @retcode EBUSY vcache is in use by someone else
+ * @retcode otherwise other error
+ *
+ * @pre The caller must hold the vnode interlock for the associated vnode
+ * @post The vnode interlock for the associated vnode will still be held
+ * and must be VI_UNLOCK'd by the caller
+ */
+int
+osi_fbsd_checkinuse(struct vcache *avc)
+{
+ struct vnode *vp = AFSTOV(avc);
+
+ ASSERT_VI_LOCKED(vp, "osi_fbsd_checkinuse");
+
+ /* The interlock is needed to check the usecount. */
+ if (vp->v_usecount > 0) {
+ return EBUSY;
+ }
+
+ /* XXX
+ * The value of avc->opens here came to be, at some point,
+ * typically -1. This was caused by incorrectly performing afs_close
+ * processing on vnodes being recycled */
+ if (avc->opens) {
+ return EBUSY;
+ }
+
+ /* if a lock is held, give up */
+ if (CheckLock(&avc->lock)) {
+ return EBUSY;
+ }
+
+ return 0;
}