2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afsconfig.h>
11 #include "afs/param.h"
13 #ifdef IGNORE_SOME_GCC_WARNINGS
14 # pragma GCC diagnostic warning "-Wold-style-definition"
15 # pragma GCC diagnostic warning "-Wstrict-prototypes"
18 #include "afs/sysincludes.h" /* Standard vendor system headers */
19 #include "afsincludes.h" /* Afs-based standard headers */
20 #include "afs/afs_stats.h"
21 #include "rx/rx_globals.h"
22 #if !defined(UKERNEL) && !defined(AFS_LINUX20_ENV)
25 #include "h/hashing.h"
27 #if !defined(AFS_HPUX110_ENV) && !defined(AFS_DARWIN_ENV)
28 #include "netinet/in_var.h"
30 #endif /* !defined(UKERNEL) */
31 #ifdef AFS_LINUX22_ENV
32 #include "h/smp_lock.h"
35 #if (defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL)) || defined(AFS_HPUX_64BIT_ENV) || defined(AFS_SUN57_64BIT_ENV) || (defined(AFS_SGI_ENV) && (_MIPS_SZLONG==64)) || defined(NEED_IOCTL32)
37 afs_ioctl32_to_afs_ioctl(const struct afs_ioctl32 *src, struct afs_ioctl *dst)
39 dst->in = (char *)(unsigned long)src->in;
40 dst->out = (char *)(unsigned long)src->out;
41 dst->in_size = src->in_size;
42 dst->out_size = src->out_size;
47 * If you need to change copyin_afs_ioctl(), you may also need to change
52 #ifdef AFS_DARWIN100_ENV
53 copyin_afs_ioctl(user_addr_t cmarg, struct afs_ioctl *dst)
55 copyin_afs_ioctl(caddr_t cmarg, struct afs_ioctl *dst)
59 #if defined(AFS_DARWIN100_ENV)
60 struct afs_ioctl32 dst32;
62 if (!proc_is64bit(current_proc())) {
63 AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
65 afs_ioctl32_to_afs_ioctl(&dst32, dst);
69 #if defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL)
70 struct afs_ioctl32 dst32;
73 AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
75 afs_ioctl32_to_afs_ioctl(&dst32, dst);
78 #endif /* defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL) */
81 #if defined(AFS_HPUX_64BIT_ENV)
82 struct afs_ioctl32 dst32;
84 if (is_32bit(u.u_procp)) { /* is_32bit() in proc_iface.h */
85 AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
87 afs_ioctl32_to_afs_ioctl(&dst32, dst);
90 #endif /* defined(AFS_HPUX_64BIT_ENV) */
92 #if defined(AFS_SUN57_64BIT_ENV)
93 struct afs_ioctl32 dst32;
95 if (get_udatamodel() == DATAMODEL_ILP32) {
96 AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
98 afs_ioctl32_to_afs_ioctl(&dst32, dst);
101 #endif /* defined(AFS_SUN57_64BIT_ENV) */
103 #if defined(AFS_SGI_ENV) && (_MIPS_SZLONG==64)
104 struct afs_ioctl32 dst32;
106 if (!ABI_IS_64BIT(get_current_abi())) {
107 AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
109 afs_ioctl32_to_afs_ioctl(&dst32, dst);
112 #endif /* defined(AFS_SGI_ENV) && (_MIPS_SZLONG==64) */
114 #if defined(AFS_LINUX_64BIT_KERNEL) && !defined(AFS_ALPHA_LINUX20_ENV) && !defined(AFS_IA64_LINUX20_ENV)
115 struct afs_ioctl32 dst32;
117 #ifdef AFS_SPARC64_LINUX26_ENV
118 if (test_thread_flag(TIF_32BIT))
119 #elif defined(AFS_SPARC64_LINUX24_ENV)
120 if (current->thread.flags & SPARC_FLAG_32BIT)
121 #elif defined(AFS_SPARC64_LINUX20_ENV)
122 if (current->tss.flags & SPARC_FLAG_32BIT)
124 #elif defined(AFS_AMD64_LINUX26_ENV)
125 if (test_thread_flag(TIF_IA32))
126 #elif defined(AFS_AMD64_LINUX20_ENV)
127 if (current->thread.flags & THREAD_IA32)
129 #elif defined(AFS_PPC64_LINUX26_ENV)
130 #if defined(STRUCT_TASK_STRUCT_HAS_THREAD_INFO)
131 if (current->thread_info->flags & _TIF_32BIT)
133 if (task_thread_info(current)->flags & _TIF_32BIT)
135 #elif defined(AFS_PPC64_LINUX20_ENV)
136 if (current->thread.flags & PPC_FLAG_32BIT)
138 #elif defined(AFS_S390X_LINUX26_ENV)
139 if (test_thread_flag(TIF_31BIT))
140 #elif defined(AFS_S390X_LINUX20_ENV)
141 if (current->thread.flags & S390_FLAG_31BIT)
144 #error pioctl32 not done for this linux
147 AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
149 afs_ioctl32_to_afs_ioctl(&dst32, dst);
152 #endif /* defined(AFS_LINUX_64BIT_KERNEL) */
154 AFS_COPYIN(cmarg, (caddr_t) dst, sizeof *dst, code);
161 #include "sys/lockl.h"
164 * syscall - this is the VRMIX system call entry point.
167 * THIS SHOULD BE CHANGED TO afs_syscall(), but requires
168 * all the user-level calls to `syscall' to change.
170 syscall(syscall, p1, p2, p3, p4, p5, p6)
172 register rval1 = 0, code;
175 #ifndef AFS_AIX41_ENV
176 extern lock_t kernel_lock;
177 monster = lockl(&kernel_lock, LOCK_SHORT);
178 #endif /* !AFS_AIX41_ENV */
180 AFS_STATCNT(syscall);
184 rval1 = afs_syscall_call(p1, p2, p3, p4, p5, p6);
189 rval1 = afs_setpag();
195 rval1 = afs_syscall_pioctl(p1, p2, p3, p4);
199 case AFSCALL_ICREATE:
200 rval1 = afs_syscall_icreate(p1, p2, p3, p4, p5, p6);
204 rval1 = afs_syscall_iopen(p1, p2, p3);
208 rval1 = afs_syscall_iincdec(p1, p2, p3, -1);
212 rval1 = afs_syscall_iincdec(p1, p2, p3, 1);
217 code = Afscall_icl(p1, p2, p3, p4, p5, &retval);
232 #ifndef AFS_AIX41_ENV
233 if (monster != LOCK_NEST)
234 unlockl(&kernel_lock);
235 #endif /* !AFS_AIX41_ENV */
236 return getuerror()? -1 : rval1;
240 * lsetpag - interface to afs_setpag().
246 AFS_STATCNT(lsetpag);
247 return syscall(AFSCALL_SETPAG, 0, 0, 0, 0, 0);
251 * lpioctl - interface to pioctl()
254 lpioctl(char *path, int cmd, void *cmarg, int follow)
257 AFS_STATCNT(lpioctl);
258 return syscall(AFSCALL_PIOCTL, path, cmd, cmarg, follow);
261 #else /* !AFS_AIX32_ENV */
263 #if defined(AFS_SGI_ENV)
275 Afs_syscall(struct afsargs *uap, rval_t * rvp)
280 AFS_STATCNT(afs_syscall);
281 switch (uap->syscall) {
286 Afscall_icl(uap->parm1, uap->parm2, uap->parm3, uap->parm4,
287 uap->parm5, &retval);
289 rvp->r_val1 = retval;
291 #ifdef AFS_SGI_XFS_IOPS_ENV
294 afs_syscall_idec64(uap->parm1, uap->parm2, uap->parm3, uap->parm4,
299 afs_syscall_iinc64(uap->parm1, uap->parm2, uap->parm3, uap->parm4,
302 case AFSCALL_ILISTINODE64:
304 afs_syscall_ilistinode64(uap->parm1, uap->parm2, uap->parm3,
305 uap->parm4, uap->parm5);
307 case AFSCALL_ICREATENAME64:
309 afs_syscall_icreatename64(uap->parm1, uap->parm2, uap->parm3,
310 uap->parm4, uap->parm5);
313 #ifdef AFS_SGI_VNODE_GLUE
314 case AFSCALL_INIT_KERNEL_CONFIG:
315 error = afs_init_kernel_config(uap->parm1);
320 afs_syscall_call(uap->syscall, uap->parm1, uap->parm2, uap->parm3,
321 uap->parm4, uap->parm5);
326 #else /* AFS_SGI_ENV */
343 #if defined(AFS_HPUX_64BIT_ENV) || defined(AFS_SUN57_64BIT_ENV) || (defined(AFS_LINUX_64BIT_KERNEL) && !defined(AFS_ALPHA_LINUX20_ENV) && !defined(AFS_IA64_LINUX20_ENV)) || defined(NEED_IOCTL32)
344 #if SIZEOF_VOID_P == SIZEOF_UNSIGNED_INT
345 # define uintptrsz unsigned int
346 #elif SIZEOF_VOID_P == SIZEOF_UNSIGNED_LONG
347 # define uintptrsz unsigned long
348 #elif SIZEOF_VOID_P == SIZEOF_UNSIGNED_LONG_LONG
349 # define uintptrsz unsigned long long
351 # error "Unable to determine casting for pointers"
354 iparam32_to_iparam(const struct iparam32 *src, struct iparam *dst)
356 dst->param1 = (iparmtype)(uintptrsz)src->param1;
357 dst->param2 = (iparmtype)(uintptrsz)src->param2;
358 dst->param3 = (iparmtype)(uintptrsz)src->param3;
359 dst->param4 = (iparmtype)(uintptrsz)src->param4;
364 * If you need to change copyin_iparam(), you may also need to change
365 * copyin_afs_ioctl().
367 * This function is needed only for icreate, meaning, only on platforms
368 * providing the inode fileserver.
372 copyin_iparam(caddr_t cmarg, struct iparam *dst)
376 #if defined(AFS_HPUX_64BIT_ENV)
377 struct iparam32 dst32;
379 if (is_32bit(u.u_procp)) { /* is_32bit() in proc_iface.h */
380 AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
382 iparam32_to_iparam(&dst32, dst);
385 #endif /* AFS_HPUX_64BIT_ENV */
387 #if defined(AFS_SUN57_64BIT_ENV)
388 struct iparam32 dst32;
390 if (get_udatamodel() == DATAMODEL_ILP32) {
391 AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
393 iparam32_to_iparam(&dst32, dst);
396 #endif /* AFS_SUN57_64BIT_ENV */
398 #if defined(AFS_LINUX_64BIT_KERNEL) && !defined(AFS_ALPHA_LINUX20_ENV) && !defined(AFS_IA64_LINUX20_ENV)
399 struct iparam32 dst32;
401 #ifdef AFS_SPARC64_LINUX26_ENV
402 if (test_thread_flag(TIF_32BIT))
403 #elif defined(AFS_SPARC64_LINUX24_ENV)
404 if (current->thread.flags & SPARC_FLAG_32BIT)
405 #elif defined(AFS_SPARC64_LINUX20_ENV)
406 if (current->tss.flags & SPARC_FLAG_32BIT)
408 #elif defined(AFS_AMD64_LINUX26_ENV)
409 if (test_thread_flag(TIF_IA32))
410 #elif defined(AFS_AMD64_LINUX20_ENV)
411 if (current->thread.flags & THREAD_IA32)
413 #elif defined(AFS_PPC64_LINUX26_ENV)
414 #if defined(STRUCT_TASK_STRUCT_HAS_THREAD_INFO)
415 if (current->thread_info->flags & _TIF_32BIT)
417 if (task_thread_info(current)->flags & _TIF_32BIT)
419 #elif defined(AFS_PPC64_LINUX20_ENV)
420 if (current->thread.flags & PPC_FLAG_32BIT)
422 #elif defined(AFS_S390X_LINUX26_ENV)
423 if (test_thread_flag(TIF_31BIT))
424 #elif defined(AFS_S390X_LINUX20_ENV)
425 if (current->thread.flags & S390_FLAG_31BIT)
428 #error iparam32 not done for this linux platform
431 AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
433 iparam32_to_iparam(&dst32, dst);
436 #endif /* AFS_LINUX_64BIT_KERNEL */
438 AFS_COPYIN(cmarg, (caddr_t) dst, sizeof *dst, code);
442 /* Main entry of all afs system calls */
444 extern int afs_sinited;
446 /** The 32 bit OS expects the members of this structure to be 32 bit
447 * quantities and the 64 bit OS expects them as 64 bit quanties. Hence
448 * to accomodate both, *long* is used instead of afs_int32
451 # ifdef AFS_SUN57_ENV
473 Afs_syscall(register struct afssysa *uap, rval_t * rvp)
475 int *retval = &rvp->r_val1;
476 #elif defined(AFS_DARWIN100_ENV)
496 afs3_syscall(afs_proc_t *p, void *args, unsigned int *retval)
498 struct afssysa64 *uap64 = NULL;
499 struct afssysa *uap = NULL;
500 #elif defined(AFS_FBSD_ENV)
502 afs3_syscall(struct thread *p, void *args)
512 } *uap = (struct a *)args;
514 #elif defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
516 afs3_syscall(afs_proc_t *p, void *args, long *retval)
526 } *uap = (struct a *)args;
527 #elif defined(AFS_LINUX20_ENV)
535 long parm6; /* not actually used - should be removed */
537 /* Linux system calls only set up for 5 arguments. */
539 afs_syscall(long syscall, long parm1, long parm2, long parm3, long parm4)
541 struct afssysargs args, *uap = &args;
543 long *retval = &linux_ret;
544 long eparm[4]; /* matches AFSCALL_ICL in fstrace.c */
545 # ifdef AFS_SPARC64_LINUX24_ENV
546 afs_int32 eparm32[4];
548 /* eparm is also used by AFSCALL_CALL in afsd.c */
550 # if defined(UKERNEL)
562 } *uap = (struct a *)get_user_struct()->u_ap;
575 } *uap = (struct a *)u.u_ap;
576 # endif /* UKERNEL */
577 # if defined(AFS_HPUX_ENV)
578 long *retval = &u.u_rval1;
579 # elif defined(UKERNEL)
580 int *retval = &(get_user_struct()->u_rval1);
582 int *retval = &u.u_rval1;
585 register int code = 0;
587 AFS_STATCNT(afs_syscall);
594 #ifdef AFS_LINUX20_ENV
596 /* setup uap for use below - pull out the magic decoder ring to know
597 * which syscalls have folded argument lists.
599 uap->syscall = syscall;
603 if (syscall == AFSCALL_ICL || syscall == AFSCALL_CALL) {
604 #ifdef AFS_SPARC64_LINUX24_ENV
605 /* from arch/sparc64/kernel/sys_sparc32.c */
607 ({ unsigned long __ret; \
608 __asm__ ("srl %0, 0, %0" \
615 #ifdef AFS_SPARC64_LINUX26_ENV
616 if (test_thread_flag(TIF_32BIT))
618 if (current->thread.flags & SPARC_FLAG_32BIT)
621 AFS_COPYIN((char *)parm4, (char *)eparm32, sizeof(eparm32), code);
622 eparm[0] = AA(eparm32[0]);
623 eparm[1] = AA(eparm32[1]);
624 eparm[2] = AA(eparm32[2]);
628 AFS_COPYIN((char *)parm4, (char *)eparm, sizeof(eparm), code);
629 uap->parm4 = eparm[0];
630 uap->parm5 = eparm[1];
631 uap->parm6 = eparm[2];
638 #if defined(AFS_DARWIN80_ENV)
640 osi_Assert(*retval == 0);
641 #ifdef AFS_DARWIN100_ENV
642 if (proc_is64bit(p)) {
643 uap64 = (struct afssysa64 *)args;
644 if (uap64->syscall == AFSCALL_CALL) {
646 afs_syscall64_call(uap64->parm1, uap64->parm2, uap64->parm3,
647 uap64->parm4, uap64->parm5, uap64->parm6);
648 /* pass back the code as syscall retval */
653 } else if (uap64->syscall == AFSCALL_SETPAG) {
655 code = afs_setpag(p, args, retval);
657 } else if (uap64->syscall == AFSCALL_PIOCTL) {
660 afs_syscall64_pioctl(uap64->parm1, (unsigned int)uap64->parm2,
661 uap64->parm3, (int)uap64->parm4,
664 } else if (uap64->syscall == AFSCALL_ICL) {
667 Afscall64_icl(uap64->parm1, uap64->parm2, uap64->parm3,
668 uap64->parm4, uap64->parm5, retval);
672 if (uap64->syscall != AFSCALL_CALL)
674 } else { /* and the default case for 32 bit procs */
676 uap = (struct afssysa *)args;
678 #if defined(AFS_HPUX_ENV)
680 * There used to be code here (duplicated from osi_Init()) for
681 * initializing the semaphore used by AFS_GLOCK(). Was the
682 * duplication to handle the case of a dynamically loaded kernel
687 if (uap->syscall == AFSCALL_CALL) {
689 afs_syscall_call(uap->parm1, uap->parm2, uap->parm3,
690 uap->parm4, uap->parm5, uap->parm6);
691 #ifdef AFS_DARWIN_ENV
692 /* pass back the code as syscall retval */
698 } else if (uap->syscall == AFSCALL_SETPAG) {
700 register proc_t *procp;
702 procp = ttoproc(curthread);
704 code = afs_setpag(&procp->p_cred);
708 #if defined(AFS_FBSD_ENV)
709 code = afs_setpag(p, args);
710 #elif defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
711 code = afs_setpag(p, args, retval);
712 #else /* AFS_DARWIN_ENV || AFS_XBSD_ENV */
717 } else if (uap->syscall == AFSCALL_PIOCTL) {
719 #if defined(AFS_SUN5_ENV)
721 afs_syscall_pioctl(uap->parm1, uap->parm2, uap->parm3,
722 uap->parm4, rvp, CRED());
723 #elif defined(AFS_FBSD50_ENV)
725 afs_syscall_pioctl(uap->parm1, uap->parm2, uap->parm3,
726 uap->parm4, p->td_ucred);
727 #elif defined(AFS_DARWIN80_ENV)
729 afs_syscall_pioctl(uap->parm1, uap->parm2, uap->parm3,
730 uap->parm4, kauth_cred_get());
731 #elif defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
733 afs_syscall_pioctl(uap->parm1, uap->parm2, uap->parm3,
734 uap->parm4, p->p_cred->pc_ucred);
737 afs_syscall_pioctl((char *)uap->parm1,
738 (unsigned int)uap->parm2,
743 } else if (uap->syscall == AFSCALL_ICREATE) {
744 struct iparam iparams;
746 code = copyin_iparam((char *)uap->parm3, &iparams);
748 #if defined(KERNEL_HAVE_UERROR)
754 afs_syscall_icreate(uap->parm1, uap->parm2, iparams.param1,
755 iparams.param2, iparams.param3,
756 iparams.param4, rvp, CRED());
759 afs_syscall_icreate(uap->parm1, uap->parm2, iparams.param1,
760 iparams.param2, iparams.param3,
762 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
766 #endif /* AFS_SUN5_ENV */
768 } else if (uap->syscall == AFSCALL_IOPEN) {
771 afs_syscall_iopen(uap->parm1, uap->parm2, uap->parm3, rvp,
774 code = afs_syscall_iopen(uap->parm1, uap->parm2, uap->parm3
775 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
779 #endif /* AFS_SUN5_ENV */
780 } else if (uap->syscall == AFSCALL_IDEC) {
782 afs_syscall_iincdec(uap->parm1, uap->parm2, uap->parm3, -1
787 } else if (uap->syscall == AFSCALL_IINC) {
789 afs_syscall_iincdec(uap->parm1, uap->parm2, uap->parm3, 1
794 } else if (uap->syscall == AFSCALL_ICL) {
797 Afscall_icl(uap->parm1, uap->parm2, uap->parm3, uap->parm4,
798 uap->parm5, (long *)retval);
800 #ifdef AFS_LINUX20_ENV
802 /* ICL commands can return values. */
803 code = -linux_ret; /* Gets negated again at exit below */
807 #if defined(KERNEL_HAVE_UERROR)
811 #endif /* !AFS_LINUX20_ENV */
813 #if defined(KERNEL_HAVE_UERROR)
819 #if defined(AFS_DARWIN80_ENV)
820 if (uap->syscall != AFSCALL_CALL)
822 #ifdef AFS_DARWIN100_ENV
826 #ifdef AFS_LINUX20_ENV
832 #endif /* AFS_SGI_ENV */
833 #endif /* !AFS_AIX32_ENV */