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 copyin_afs_ioctl(caddr_t cmarg, struct afs_ioctl *dst)
51 #if defined(AFS_DARWIN100_ENV)
52 struct afs_ioctl32 dst32;
54 if (!proc_is64bit(current_proc())) {
55 AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
57 afs_ioctl32_to_afs_ioctl(&dst32, dst);
61 #if defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL)
62 struct afs_ioctl32 dst32;
65 AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
67 afs_ioctl32_to_afs_ioctl(&dst32, dst);
70 #endif /* defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL) */
73 #if defined(AFS_HPUX_64BIT_ENV)
74 struct afs_ioctl32 dst32;
76 if (is_32bit(u.u_procp)) { /* is_32bit() in proc_iface.h */
77 AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
79 afs_ioctl32_to_afs_ioctl(&dst32, dst);
82 #endif /* defined(AFS_HPUX_64BIT_ENV) */
84 #if defined(AFS_SUN57_64BIT_ENV)
85 struct afs_ioctl32 dst32;
87 if (get_udatamodel() == DATAMODEL_ILP32) {
88 AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
90 afs_ioctl32_to_afs_ioctl(&dst32, dst);
93 #endif /* defined(AFS_SUN57_64BIT_ENV) */
95 #if defined(AFS_SGI_ENV) && (_MIPS_SZLONG==64)
96 struct afs_ioctl32 dst32;
98 if (!ABI_IS_64BIT(get_current_abi())) {
99 AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
101 afs_ioctl32_to_afs_ioctl(&dst32, dst);
104 #endif /* defined(AFS_SGI_ENV) && (_MIPS_SZLONG==64) */
106 #if defined(AFS_LINUX_64BIT_KERNEL) && !defined(AFS_ALPHA_LINUX20_ENV) && !defined(AFS_IA64_LINUX20_ENV)
107 struct afs_ioctl32 dst32;
109 #ifdef AFS_SPARC64_LINUX26_ENV
110 if (test_thread_flag(TIF_32BIT))
111 #elif defined(AFS_SPARC64_LINUX24_ENV)
112 if (current->thread.flags & SPARC_FLAG_32BIT)
113 #elif defined(AFS_SPARC64_LINUX20_ENV)
114 if (current->tss.flags & SPARC_FLAG_32BIT)
116 #elif defined(AFS_AMD64_LINUX26_ENV)
117 if (test_thread_flag(TIF_IA32))
118 #elif defined(AFS_AMD64_LINUX20_ENV)
119 if (current->thread.flags & THREAD_IA32)
121 #elif defined(AFS_PPC64_LINUX26_ENV)
122 #if defined(STRUCT_TASK_STRUCT_HAS_THREAD_INFO)
123 if (current->thread_info->flags & _TIF_32BIT)
125 if (task_thread_info(current)->flags & _TIF_32BIT)
127 #elif defined(AFS_PPC64_LINUX20_ENV)
128 if (current->thread.flags & PPC_FLAG_32BIT)
130 #elif defined(AFS_S390X_LINUX26_ENV)
131 if (test_thread_flag(TIF_31BIT))
132 #elif defined(AFS_S390X_LINUX20_ENV)
133 if (current->thread.flags & S390_FLAG_31BIT)
136 #error pioctl32 not done for this linux
139 AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
141 afs_ioctl32_to_afs_ioctl(&dst32, dst);
144 #endif /* defined(AFS_LINUX_64BIT_KERNEL) */
146 AFS_COPYIN(cmarg, (caddr_t) dst, sizeof *dst, code);
153 #include "sys/lockl.h"
156 * syscall - this is the VRMIX system call entry point.
159 * THIS SHOULD BE CHANGED TO afs_syscall(), but requires
160 * all the user-level calls to `syscall' to change.
162 syscall(syscall, p1, p2, p3, p4, p5, p6)
164 register rval1 = 0, code;
167 #ifndef AFS_AIX41_ENV
168 extern lock_t kernel_lock;
169 monster = lockl(&kernel_lock, LOCK_SHORT);
170 #endif /* !AFS_AIX41_ENV */
172 AFS_STATCNT(syscall);
176 rval1 = afs_syscall_call(p1, p2, p3, p4, p5, p6);
181 rval1 = afs_setpag();
187 rval1 = afs_syscall_pioctl(p1, p2, p3, p4);
191 case AFSCALL_ICREATE:
192 rval1 = afs_syscall_icreate(p1, p2, p3, p4, p5, p6);
196 rval1 = afs_syscall_iopen(p1, p2, p3);
200 rval1 = afs_syscall_iincdec(p1, p2, p3, -1);
204 rval1 = afs_syscall_iincdec(p1, p2, p3, 1);
209 code = Afscall_icl(p1, p2, p3, p4, p5, &retval);
224 #ifndef AFS_AIX41_ENV
225 if (monster != LOCK_NEST)
226 unlockl(&kernel_lock);
227 #endif /* !AFS_AIX41_ENV */
228 return getuerror()? -1 : rval1;
232 * lsetpag - interface to afs_setpag().
238 AFS_STATCNT(lsetpag);
239 return syscall(AFSCALL_SETPAG, 0, 0, 0, 0, 0);
243 * lpioctl - interface to pioctl()
246 lpioctl(char *path, int cmd, void *cmarg, int follow)
249 AFS_STATCNT(lpioctl);
250 return syscall(AFSCALL_PIOCTL, path, cmd, cmarg, follow);
253 #else /* !AFS_AIX32_ENV */
255 #if defined(AFS_SGI_ENV)
267 Afs_syscall(struct afsargs *uap, rval_t * rvp)
272 AFS_STATCNT(afs_syscall);
273 switch (uap->syscall) {
278 Afscall_icl(uap->parm1, uap->parm2, uap->parm3, uap->parm4,
279 uap->parm5, &retval);
281 rvp->r_val1 = retval;
283 #ifdef AFS_SGI_XFS_IOPS_ENV
286 afs_syscall_idec64(uap->parm1, uap->parm2, uap->parm3, uap->parm4,
291 afs_syscall_iinc64(uap->parm1, uap->parm2, uap->parm3, uap->parm4,
294 case AFSCALL_ILISTINODE64:
296 afs_syscall_ilistinode64(uap->parm1, uap->parm2, uap->parm3,
297 uap->parm4, uap->parm5);
299 case AFSCALL_ICREATENAME64:
301 afs_syscall_icreatename64(uap->parm1, uap->parm2, uap->parm3,
302 uap->parm4, uap->parm5);
305 #ifdef AFS_SGI_VNODE_GLUE
306 case AFSCALL_INIT_KERNEL_CONFIG:
307 error = afs_init_kernel_config(uap->parm1);
312 afs_syscall_call(uap->syscall, uap->parm1, uap->parm2, uap->parm3,
313 uap->parm4, uap->parm5);
318 #else /* AFS_SGI_ENV */
335 #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)
337 iparam32_to_iparam(const struct iparam32 *src, struct iparam *dst)
339 dst->param1 = src->param1;
340 dst->param2 = src->param2;
341 dst->param3 = src->param3;
342 dst->param4 = src->param4;
347 * If you need to change copyin_iparam(), you may also need to change
348 * copyin_afs_ioctl().
352 copyin_iparam(caddr_t cmarg, struct iparam *dst)
356 #if defined(AFS_DARWIN100_ENV)
357 struct iparam32 dst32;
359 if (!proc_is64bit(current_proc())) {
360 AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
362 iparam32_to_iparam(&dst32, dst);
366 #if defined(AFS_HPUX_64BIT_ENV)
367 struct iparam32 dst32;
369 if (is_32bit(u.u_procp)) { /* is_32bit() in proc_iface.h */
370 AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
372 iparam32_to_iparam(&dst32, dst);
375 #endif /* AFS_HPUX_64BIT_ENV */
377 #if defined(AFS_SUN57_64BIT_ENV)
378 struct iparam32 dst32;
380 if (get_udatamodel() == DATAMODEL_ILP32) {
381 AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
383 iparam32_to_iparam(&dst32, dst);
386 #endif /* AFS_SUN57_64BIT_ENV */
388 #if defined(AFS_LINUX_64BIT_KERNEL) && !defined(AFS_ALPHA_LINUX20_ENV) && !defined(AFS_IA64_LINUX20_ENV)
389 struct iparam32 dst32;
391 #ifdef AFS_SPARC64_LINUX26_ENV
392 if (test_thread_flag(TIF_32BIT))
393 #elif defined(AFS_SPARC64_LINUX24_ENV)
394 if (current->thread.flags & SPARC_FLAG_32BIT)
395 #elif defined(AFS_SPARC64_LINUX20_ENV)
396 if (current->tss.flags & SPARC_FLAG_32BIT)
398 #elif defined(AFS_AMD64_LINUX26_ENV)
399 if (test_thread_flag(TIF_IA32))
400 #elif defined(AFS_AMD64_LINUX20_ENV)
401 if (current->thread.flags & THREAD_IA32)
403 #elif defined(AFS_PPC64_LINUX26_ENV)
404 #if defined(STRUCT_TASK_STRUCT_HAS_THREAD_INFO)
405 if (current->thread_info->flags & _TIF_32BIT)
407 if (task_thread_info(current)->flags & _TIF_32BIT)
409 #elif defined(AFS_PPC64_LINUX20_ENV)
410 if (current->thread.flags & PPC_FLAG_32BIT)
412 #elif defined(AFS_S390X_LINUX26_ENV)
413 if (test_thread_flag(TIF_31BIT))
414 #elif defined(AFS_S390X_LINUX20_ENV)
415 if (current->thread.flags & S390_FLAG_31BIT)
418 #error iparam32 not done for this linux platform
421 AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
423 iparam32_to_iparam(&dst32, dst);
426 #endif /* AFS_LINUX_64BIT_KERNEL */
428 AFS_COPYIN(cmarg, (caddr_t) dst, sizeof *dst, code);
432 /* Main entry of all afs system calls */
434 extern int afs_sinited;
436 /** The 32 bit OS expects the members of this structure to be 32 bit
437 * quantities and the 64 bit OS expects them as 64 bit quanties. Hence
438 * to accomodate both, *long* is used instead of afs_int32
463 Afs_syscall(register struct afssysa *uap, rval_t * rvp)
465 int *retval = &rvp->r_val1;
466 #else /* AFS_SUN5_ENV */
467 #if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
469 afs3_syscall(p, args, retval)
470 #ifdef AFS_FBSD50_ENV
486 } *uap = (struct a *)args;
487 #else /* AFS_OSF_ENV */
488 #ifdef AFS_LINUX20_ENV
496 long parm6; /* not actually used - should be removed */
498 /* Linux system calls only set up for 5 arguments. */
500 afs_syscall(long syscall, long parm1, long parm2, long parm3, long parm4)
502 struct afssysargs args, *uap = &args;
504 long *retval = &linux_ret;
505 long eparm[4]; /* matches AFSCALL_ICL in fstrace.c */
506 #ifdef AFS_SPARC64_LINUX24_ENV
507 afs_int32 eparm32[4];
509 /* eparm is also used by AFSCALL_CALL in afsd.c */
523 } *uap = (struct a *)u.u_ap;
536 } *uap = (struct a *)u.u_ap;
538 #if defined(AFS_HPUX_ENV)
539 long *retval = &u.u_rval1;
541 int *retval = &u.u_rval1;
543 #endif /* AFS_LINUX20_ENV */
544 #endif /* AFS_OSF_ENV */
545 #endif /* AFS_SUN5_ENV */
546 register int code = 0;
548 AFS_STATCNT(afs_syscall);
555 #ifdef AFS_LINUX20_ENV
557 /* setup uap for use below - pull out the magic decoder ring to know
558 * which syscalls have folded argument lists.
560 uap->syscall = syscall;
564 if (syscall == AFSCALL_ICL || syscall == AFSCALL_CALL) {
565 #ifdef AFS_SPARC64_LINUX24_ENV
566 /* from arch/sparc64/kernel/sys_sparc32.c */
568 ({ unsigned long __ret; \
569 __asm__ ("srl %0, 0, %0" \
576 #ifdef AFS_SPARC64_LINUX26_ENV
577 if (test_thread_flag(TIF_32BIT))
579 if (current->thread.flags & SPARC_FLAG_32BIT)
582 AFS_COPYIN((char *)parm4, (char *)eparm32, sizeof(eparm32), code);
583 eparm[0] = AA(eparm32[0]);
584 eparm[1] = AA(eparm32[1]);
585 eparm[2] = AA(eparm32[2]);
589 AFS_COPYIN((char *)parm4, (char *)eparm, sizeof(eparm), code);
590 uap->parm4 = eparm[0];
591 uap->parm5 = eparm[1];
592 uap->parm6 = eparm[2];
599 #if defined(AFS_DARWIN80_ENV)
601 osi_Assert(*retval == 0);
603 #if defined(AFS_HPUX_ENV)
605 * There used to be code here (duplicated from osi_Init()) for
606 * initializing the semaphore used by AFS_GLOCK(). Was the
607 * duplication to handle the case of a dynamically loaded kernel
612 if (uap->syscall == AFSCALL_CALL) {
614 afs_syscall_call(uap->parm1, uap->parm2, uap->parm3, uap->parm4,
615 uap->parm5, uap->parm6);
616 } else if (uap->syscall == AFSCALL_SETPAG) {
618 register proc_t *procp;
620 procp = ttoproc(curthread);
622 code = afs_setpag(&procp->p_cred);
626 #if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
627 code = afs_setpag(p, args, retval);
628 #else /* AFS_OSF_ENV */
633 } else if (uap->syscall == AFSCALL_PIOCTL) {
635 #if defined(AFS_SUN5_ENV)
637 afs_syscall_pioctl(uap->parm1, uap->parm2, uap->parm3, uap->parm4,
639 #elif defined(AFS_FBSD50_ENV)
641 afs_syscall_pioctl(uap->parm1, uap->parm2, uap->parm3, uap->parm4,
643 #elif defined(AFS_DARWIN80_ENV)
645 afs_syscall_pioctl(uap->parm1, uap->parm2, uap->parm3, uap->parm4,
647 #elif defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
649 afs_syscall_pioctl(uap->parm1, uap->parm2, uap->parm3, uap->parm4,
650 p->p_cred->pc_ucred);
653 afs_syscall_pioctl((char *)uap->parm1, (unsigned int)uap->parm2, (caddr_t)uap->parm3,
657 } else if (uap->syscall == AFSCALL_ICREATE) {
658 struct iparam iparams;
660 code = copyin_iparam((char *)uap->parm3, &iparams);
662 #if defined(KERNEL_HAVE_UERROR)
668 afs_syscall_icreate(uap->parm1, uap->parm2, iparams.param1,
669 iparams.param2, iparams.param3,
670 iparams.param4, rvp, CRED());
673 afs_syscall_icreate(uap->parm1, uap->parm2, iparams.param1,
675 #if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
676 iparams.param3, iparams.param4, retval);
678 iparams.param3, iparams.param4);
680 #endif /* AFS_SUN5_ENV */
681 } else if (uap->syscall == AFSCALL_IOPEN) {
684 afs_syscall_iopen(uap->parm1, uap->parm2, uap->parm3, rvp,
687 #if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
688 code = afs_syscall_iopen(uap->parm1, uap->parm2, uap->parm3, retval);
690 code = afs_syscall_iopen(uap->parm1, uap->parm2, uap->parm3);
692 #endif /* AFS_SUN5_ENV */
693 } else if (uap->syscall == AFSCALL_IDEC) {
696 afs_syscall_iincdec(uap->parm1, uap->parm2, uap->parm3, -1, rvp,
699 code = afs_syscall_iincdec(uap->parm1, uap->parm2, uap->parm3, -1);
700 #endif /* AFS_SUN5_ENV */
701 } else if (uap->syscall == AFSCALL_IINC) {
704 afs_syscall_iincdec(uap->parm1, uap->parm2, uap->parm3, 1, rvp,
707 code = afs_syscall_iincdec(uap->parm1, uap->parm2, uap->parm3, 1);
708 #endif /* AFS_SUN5_ENV */
709 } else if (uap->syscall == AFSCALL_ICL) {
712 Afscall_icl(uap->parm1, uap->parm2, uap->parm3, uap->parm4,
715 #ifdef AFS_LINUX20_ENV
717 /* ICL commands can return values. */
718 code = -linux_ret; /* Gets negated again at exit below */
722 #if defined(KERNEL_HAVE_UERROR)
726 #endif /* !AFS_LINUX20_ENV */
728 #if defined(KERNEL_HAVE_UERROR)
735 #if defined(AFS_DARWIN80_ENV)
736 if (uap->syscall != AFSCALL_CALL)
739 #ifdef AFS_LINUX20_ENV
745 #endif /* AFS_SGI_ENV */
746 #endif /* !AFS_AIX32_ENV */