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"
14 #include "afs/sysincludes.h" /* Standard vendor system headers */
15 #include "afsincludes.h" /* Afs-based standard headers */
16 #include "afs/afs_stats.h"
17 #include "rx/rx_globals.h"
18 #if !defined(UKERNEL) && !defined(AFS_LINUX20_ENV)
21 #include "h/hashing.h"
23 #if !defined(AFS_HPUX110_ENV) && !defined(AFS_DARWIN60_ENV)
24 #include "netinet/in_var.h"
26 #endif /* !defined(UKERNEL) */
27 #ifdef AFS_LINUX22_ENV
28 #include "h/smp_lock.h"
31 #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)
33 afs_ioctl32_to_afs_ioctl(const struct afs_ioctl32 *src, struct afs_ioctl *dst)
35 dst->in = (char *)(unsigned long)src->in;
36 dst->out = (char *)(unsigned long)src->out;
37 dst->in_size = src->in_size;
38 dst->out_size = src->out_size;
43 * If you need to change copyin_afs_ioctl(), you may also need to change
48 #ifdef AFS_DARWIN100_ENV
49 copyin_afs_ioctl(user_addr_t cmarg, struct afs_ioctl *dst)
51 copyin_afs_ioctl(caddr_t cmarg, struct afs_ioctl *dst)
55 #if defined(AFS_DARWIN100_ENV)
56 struct afs_ioctl32 dst32;
58 if (!proc_is64bit(current_proc())) {
59 AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
61 afs_ioctl32_to_afs_ioctl(&dst32, dst);
65 #if defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL)
66 struct afs_ioctl32 dst32;
69 AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
71 afs_ioctl32_to_afs_ioctl(&dst32, dst);
74 #endif /* defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL) */
77 #if defined(AFS_HPUX_64BIT_ENV)
78 struct afs_ioctl32 dst32;
80 if (is_32bit(u.u_procp)) { /* is_32bit() in proc_iface.h */
81 AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
83 afs_ioctl32_to_afs_ioctl(&dst32, dst);
86 #endif /* defined(AFS_HPUX_64BIT_ENV) */
88 #if defined(AFS_SUN57_64BIT_ENV)
89 struct afs_ioctl32 dst32;
91 if (get_udatamodel() == DATAMODEL_ILP32) {
92 AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
94 afs_ioctl32_to_afs_ioctl(&dst32, dst);
97 #endif /* defined(AFS_SUN57_64BIT_ENV) */
99 #if defined(AFS_SGI_ENV) && (_MIPS_SZLONG==64)
100 struct afs_ioctl32 dst32;
102 if (!ABI_IS_64BIT(get_current_abi())) {
103 AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
105 afs_ioctl32_to_afs_ioctl(&dst32, dst);
108 #endif /* defined(AFS_SGI_ENV) && (_MIPS_SZLONG==64) */
110 #if defined(AFS_LINUX_64BIT_KERNEL) && !defined(AFS_ALPHA_LINUX20_ENV) && !defined(AFS_IA64_LINUX20_ENV)
111 struct afs_ioctl32 dst32;
113 #ifdef AFS_SPARC64_LINUX26_ENV
114 if (test_thread_flag(TIF_32BIT))
115 #elif defined(AFS_SPARC64_LINUX24_ENV)
116 if (current->thread.flags & SPARC_FLAG_32BIT)
117 #elif defined(AFS_SPARC64_LINUX20_ENV)
118 if (current->tss.flags & SPARC_FLAG_32BIT)
120 #elif defined(AFS_AMD64_LINUX26_ENV)
121 if (test_thread_flag(TIF_IA32))
122 #elif defined(AFS_AMD64_LINUX20_ENV)
123 if (current->thread.flags & THREAD_IA32)
125 #elif defined(AFS_PPC64_LINUX26_ENV)
126 #if defined(STRUCT_TASK_STRUCT_HAS_THREAD_INFO)
127 if (current->thread_info->flags & _TIF_32BIT)
129 if (task_thread_info(current)->flags & _TIF_32BIT)
131 #elif defined(AFS_PPC64_LINUX20_ENV)
132 if (current->thread.flags & PPC_FLAG_32BIT)
134 #elif defined(AFS_S390X_LINUX26_ENV)
135 if (test_thread_flag(TIF_31BIT))
136 #elif defined(AFS_S390X_LINUX20_ENV)
137 if (current->thread.flags & S390_FLAG_31BIT)
140 #error pioctl32 not done for this linux
143 AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
145 afs_ioctl32_to_afs_ioctl(&dst32, dst);
148 #endif /* defined(AFS_LINUX_64BIT_KERNEL) */
150 AFS_COPYIN(cmarg, (caddr_t) dst, sizeof *dst, code);
157 #include "sys/lockl.h"
160 * syscall - this is the VRMIX system call entry point.
163 * THIS SHOULD BE CHANGED TO afs_syscall(), but requires
164 * all the user-level calls to `syscall' to change.
166 syscall(syscall, p1, p2, p3, p4, p5, p6)
168 register rval1 = 0, code;
171 #ifndef AFS_AIX41_ENV
172 extern lock_t kernel_lock;
173 monster = lockl(&kernel_lock, LOCK_SHORT);
174 #endif /* !AFS_AIX41_ENV */
176 AFS_STATCNT(syscall);
180 rval1 = afs_syscall_call(p1, p2, p3, p4, p5, p6);
185 rval1 = afs_setpag();
191 rval1 = afs_syscall_pioctl(p1, p2, p3, p4);
195 case AFSCALL_ICREATE:
196 rval1 = afs_syscall_icreate(p1, p2, p3, p4, p5, p6);
200 rval1 = afs_syscall_iopen(p1, p2, p3);
204 rval1 = afs_syscall_iincdec(p1, p2, p3, -1);
208 rval1 = afs_syscall_iincdec(p1, p2, p3, 1);
213 code = Afscall_icl(p1, p2, p3, p4, p5, &retval);
228 #ifndef AFS_AIX41_ENV
229 if (monster != LOCK_NEST)
230 unlockl(&kernel_lock);
231 #endif /* !AFS_AIX41_ENV */
232 return getuerror()? -1 : rval1;
236 * lsetpag - interface to afs_setpag().
242 AFS_STATCNT(lsetpag);
243 return syscall(AFSCALL_SETPAG, 0, 0, 0, 0, 0);
247 * lpioctl - interface to pioctl()
250 lpioctl(char *path, int cmd, void *cmarg, int follow)
253 AFS_STATCNT(lpioctl);
254 return syscall(AFSCALL_PIOCTL, path, cmd, cmarg, follow);
257 #else /* !AFS_AIX32_ENV */
259 #if defined(AFS_SGI_ENV)
271 Afs_syscall(struct afsargs *uap, rval_t * rvp)
276 AFS_STATCNT(afs_syscall);
277 switch (uap->syscall) {
282 Afscall_icl(uap->parm1, uap->parm2, uap->parm3, uap->parm4,
283 uap->parm5, &retval);
285 rvp->r_val1 = retval;
287 #ifdef AFS_SGI_XFS_IOPS_ENV
290 afs_syscall_idec64(uap->parm1, uap->parm2, uap->parm3, uap->parm4,
295 afs_syscall_iinc64(uap->parm1, uap->parm2, uap->parm3, uap->parm4,
298 case AFSCALL_ILISTINODE64:
300 afs_syscall_ilistinode64(uap->parm1, uap->parm2, uap->parm3,
301 uap->parm4, uap->parm5);
303 case AFSCALL_ICREATENAME64:
305 afs_syscall_icreatename64(uap->parm1, uap->parm2, uap->parm3,
306 uap->parm4, uap->parm5);
309 #ifdef AFS_SGI_VNODE_GLUE
310 case AFSCALL_INIT_KERNEL_CONFIG:
311 error = afs_init_kernel_config(uap->parm1);
316 afs_syscall_call(uap->syscall, uap->parm1, uap->parm2, uap->parm3,
317 uap->parm4, uap->parm5);
322 #else /* AFS_SGI_ENV */
339 #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)
341 iparam32_to_iparam(const struct iparam32 *src, struct iparam *dst)
343 dst->param1 = src->param1;
344 dst->param2 = src->param2;
345 dst->param3 = src->param3;
346 dst->param4 = src->param4;
351 * If you need to change copyin_iparam(), you may also need to change
352 * copyin_afs_ioctl().
354 * This function is needed only for icreate, meaning, only on platforms
355 * providing the inode fileserver.
359 copyin_iparam(caddr_t cmarg, struct iparam *dst)
363 #if defined(AFS_HPUX_64BIT_ENV)
364 struct iparam32 dst32;
366 if (is_32bit(u.u_procp)) { /* is_32bit() in proc_iface.h */
367 AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
369 iparam32_to_iparam(&dst32, dst);
372 #endif /* AFS_HPUX_64BIT_ENV */
374 #if defined(AFS_SUN57_64BIT_ENV)
375 struct iparam32 dst32;
377 if (get_udatamodel() == DATAMODEL_ILP32) {
378 AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
380 iparam32_to_iparam(&dst32, dst);
383 #endif /* AFS_SUN57_64BIT_ENV */
385 #if defined(AFS_LINUX_64BIT_KERNEL) && !defined(AFS_ALPHA_LINUX20_ENV) && !defined(AFS_IA64_LINUX20_ENV)
386 struct iparam32 dst32;
388 #ifdef AFS_SPARC64_LINUX26_ENV
389 if (test_thread_flag(TIF_32BIT))
390 #elif defined(AFS_SPARC64_LINUX24_ENV)
391 if (current->thread.flags & SPARC_FLAG_32BIT)
392 #elif defined(AFS_SPARC64_LINUX20_ENV)
393 if (current->tss.flags & SPARC_FLAG_32BIT)
395 #elif defined(AFS_AMD64_LINUX26_ENV)
396 if (test_thread_flag(TIF_IA32))
397 #elif defined(AFS_AMD64_LINUX20_ENV)
398 if (current->thread.flags & THREAD_IA32)
400 #elif defined(AFS_PPC64_LINUX26_ENV)
401 #if defined(STRUCT_TASK_STRUCT_HAS_THREAD_INFO)
402 if (current->thread_info->flags & _TIF_32BIT)
404 if (task_thread_info(current)->flags & _TIF_32BIT)
406 #elif defined(AFS_PPC64_LINUX20_ENV)
407 if (current->thread.flags & PPC_FLAG_32BIT)
409 #elif defined(AFS_S390X_LINUX26_ENV)
410 if (test_thread_flag(TIF_31BIT))
411 #elif defined(AFS_S390X_LINUX20_ENV)
412 if (current->thread.flags & S390_FLAG_31BIT)
415 #error iparam32 not done for this linux platform
418 AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
420 iparam32_to_iparam(&dst32, dst);
423 #endif /* AFS_LINUX_64BIT_KERNEL */
425 AFS_COPYIN(cmarg, (caddr_t) dst, sizeof *dst, code);
429 /* Main entry of all afs system calls */
431 extern int afs_sinited;
433 /** The 32 bit OS expects the members of this structure to be 32 bit
434 * quantities and the 64 bit OS expects them as 64 bit quanties. Hence
435 * to accomodate both, *long* is used instead of afs_int32
460 Afs_syscall(register struct afssysa *uap, rval_t * rvp)
462 int *retval = &rvp->r_val1;
463 #else /* AFS_SUN5_ENV */
464 #ifdef AFS_DARWIN100_ENV
484 afs3_syscall(struct proc *p, void *args, unsigned int *retval)
486 struct afssysa64 *uap64 = NULL;
487 struct afssysa *uap = NULL;
488 #elif defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
490 afs3_syscall(p, args, retval)
491 #ifdef AFS_FBSD50_ENV
507 } *uap = (struct a *)args;
508 #else /* AFS_OSF_ENV */
509 #ifdef AFS_LINUX20_ENV
517 long parm6; /* not actually used - should be removed */
519 /* Linux system calls only set up for 5 arguments. */
521 afs_syscall(long syscall, long parm1, long parm2, long parm3, long parm4)
523 struct afssysargs args, *uap = &args;
525 long *retval = &linux_ret;
526 long eparm[4]; /* matches AFSCALL_ICL in fstrace.c */
527 #ifdef AFS_SPARC64_LINUX24_ENV
528 afs_int32 eparm32[4];
530 /* eparm is also used by AFSCALL_CALL in afsd.c */
544 } *uap = (struct a *)u.u_ap;
557 } *uap = (struct a *)u.u_ap;
559 #if defined(AFS_HPUX_ENV)
560 long *retval = &u.u_rval1;
562 int *retval = &u.u_rval1;
564 #endif /* AFS_LINUX20_ENV */
565 #endif /* AFS_OSF_ENV */
566 #endif /* AFS_SUN5_ENV */
567 register int code = 0;
569 AFS_STATCNT(afs_syscall);
576 #ifdef AFS_LINUX20_ENV
578 /* setup uap for use below - pull out the magic decoder ring to know
579 * which syscalls have folded argument lists.
581 uap->syscall = syscall;
585 if (syscall == AFSCALL_ICL || syscall == AFSCALL_CALL) {
586 #ifdef AFS_SPARC64_LINUX24_ENV
587 /* from arch/sparc64/kernel/sys_sparc32.c */
589 ({ unsigned long __ret; \
590 __asm__ ("srl %0, 0, %0" \
597 #ifdef AFS_SPARC64_LINUX26_ENV
598 if (test_thread_flag(TIF_32BIT))
600 if (current->thread.flags & SPARC_FLAG_32BIT)
603 AFS_COPYIN((char *)parm4, (char *)eparm32, sizeof(eparm32), code);
604 eparm[0] = AA(eparm32[0]);
605 eparm[1] = AA(eparm32[1]);
606 eparm[2] = AA(eparm32[2]);
610 AFS_COPYIN((char *)parm4, (char *)eparm, sizeof(eparm), code);
611 uap->parm4 = eparm[0];
612 uap->parm5 = eparm[1];
613 uap->parm6 = eparm[2];
620 #if defined(AFS_DARWIN80_ENV)
622 osi_Assert(*retval == 0);
623 #ifdef AFS_DARWIN100_ENV
624 if (proc_is64bit(p)) {
625 uap64 = (struct afssysa64 *)args;
626 if (uap64->syscall == AFSCALL_CALL) {
628 afs_syscall64_call(uap64->parm1, uap64->parm2, uap64->parm3,
629 uap64->parm4, uap64->parm5, uap64->parm6);
630 } else if (uap64->syscall == AFSCALL_SETPAG) {
632 code = afs_setpag(p, args, retval);
634 } else if (uap64->syscall == AFSCALL_PIOCTL) {
637 afs_syscall64_pioctl(uap64->parm1, (unsigned int)uap64->parm2,
638 uap64->parm3, (int)uap64->parm4,
641 } else if (uap64->syscall == AFSCALL_ICL) {
644 Afscall64_icl(uap64->parm1, uap64->parm2, uap64->parm3,
645 uap64->parm4, uap64->parm5, retval);
649 if (uap64->syscall != AFSCALL_CALL)
651 } else { /* and the default case for 32 bit procs */
653 uap = (struct afssysa *)args;
655 #if defined(AFS_HPUX_ENV)
657 * There used to be code here (duplicated from osi_Init()) for
658 * initializing the semaphore used by AFS_GLOCK(). Was the
659 * duplication to handle the case of a dynamically loaded kernel
664 if (uap->syscall == AFSCALL_CALL) {
666 afs_syscall_call(uap->parm1, uap->parm2, uap->parm3,
667 uap->parm4, uap->parm5, uap->parm6);
668 } else if (uap->syscall == AFSCALL_SETPAG) {
670 register proc_t *procp;
672 procp = ttoproc(curthread);
674 code = afs_setpag(&procp->p_cred);
678 #if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
679 code = afs_setpag(p, args, retval);
680 #else /* AFS_OSF_ENV */
685 } else if (uap->syscall == AFSCALL_PIOCTL) {
687 #if defined(AFS_SUN5_ENV)
689 afs_syscall_pioctl(uap->parm1, uap->parm2, uap->parm3,
690 uap->parm4, rvp, CRED());
691 #elif defined(AFS_FBSD50_ENV)
693 afs_syscall_pioctl(uap->parm1, uap->parm2, uap->parm3,
694 uap->parm4, p->td_ucred);
695 #elif defined(AFS_DARWIN80_ENV)
697 afs_syscall_pioctl(uap->parm1, uap->parm2, uap->parm3,
698 uap->parm4, kauth_cred_get());
699 #elif defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
701 afs_syscall_pioctl(uap->parm1, uap->parm2, uap->parm3,
702 uap->parm4, p->p_cred->pc_ucred);
705 afs_syscall_pioctl((char *)uap->parm1,
706 (unsigned int)uap->parm2,
711 } else if (uap->syscall == AFSCALL_ICREATE) {
712 struct iparam iparams;
714 code = copyin_iparam((char *)uap->parm3, &iparams);
716 #if defined(KERNEL_HAVE_UERROR)
722 afs_syscall_icreate(uap->parm1, uap->parm2, iparams.param1,
723 iparams.param2, iparams.param3,
724 iparams.param4, rvp, CRED());
727 afs_syscall_icreate(uap->parm1, uap->parm2, iparams.param1,
728 iparams.param2, iparams.param3,
730 #if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
734 #endif /* AFS_SUN5_ENV */
736 } else if (uap->syscall == AFSCALL_IOPEN) {
739 afs_syscall_iopen(uap->parm1, uap->parm2, uap->parm3, rvp,
742 code = afs_syscall_iopen(uap->parm1, uap->parm2, uap->parm3
743 #if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
747 #endif /* AFS_SUN5_ENV */
748 } else if (uap->syscall == AFSCALL_IDEC) {
750 afs_syscall_iincdec(uap->parm1, uap->parm2, uap->parm3, -1
755 } else if (uap->syscall == AFSCALL_IINC) {
757 afs_syscall_iincdec(uap->parm1, uap->parm2, uap->parm3, 1
762 } else if (uap->syscall == AFSCALL_ICL) {
765 Afscall_icl(uap->parm1, uap->parm2, uap->parm3, uap->parm4,
768 #ifdef AFS_LINUX20_ENV
770 /* ICL commands can return values. */
771 code = -linux_ret; /* Gets negated again at exit below */
775 #if defined(KERNEL_HAVE_UERROR)
779 #endif /* !AFS_LINUX20_ENV */
781 #if defined(KERNEL_HAVE_UERROR)
787 #if defined(AFS_DARWIN80_ENV)
788 if (uap->syscall != AFSCALL_CALL)
790 #ifdef AFS_DARWIN100_ENV
794 #ifdef AFS_LINUX20_ENV
800 #endif /* AFS_SGI_ENV */
801 #endif /* !AFS_AIX32_ENV */