linux-2630-maybe-20090331
[openafs.git] / src / afs / afs_syscall.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
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
8  */
9
10 #include <afsconfig.h>
11 #include "afs/param.h"
12
13 RCSID
14     ("$Header$");
15
16 #include "afs/sysincludes.h"    /* Standard vendor system headers */
17 #include "afsincludes.h"        /* Afs-based standard headers */
18 #include "afs/afs_stats.h"
19 #include "rx/rx_globals.h"
20 #if !defined(UKERNEL) && !defined(AFS_LINUX20_ENV)
21 #include "net/if.h"
22 #ifdef AFS_SGI62_ENV
23 #include "h/hashing.h"
24 #endif
25 #if !defined(AFS_HPUX110_ENV) && !defined(AFS_DARWIN60_ENV)
26 #include "netinet/in_var.h"
27 #endif
28 #endif /* !defined(UKERNEL) */
29 #ifdef AFS_LINUX22_ENV
30 #include "h/smp_lock.h"
31 #endif
32
33 #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)
34 static void
35 afs_ioctl32_to_afs_ioctl(const struct afs_ioctl32 *src, struct afs_ioctl *dst)
36 {
37     dst->in = (char *)(unsigned long)src->in;
38     dst->out = (char *)(unsigned long)src->out;
39     dst->in_size = src->in_size;
40     dst->out_size = src->out_size;
41 }
42 #endif
43
44 /*
45  * If you need to change copyin_afs_ioctl(), you may also need to change
46  * copyin_iparam().
47  */
48
49 int
50 copyin_afs_ioctl(caddr_t cmarg, struct afs_ioctl *dst)
51 {
52     int code;
53 #if defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL)
54     struct afs_ioctl32 dst32;
55
56     if (!(IS64U)) {
57         AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
58         if (!code)
59             afs_ioctl32_to_afs_ioctl(&dst32, dst);
60         return code;
61     }
62 #endif /* defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL) */
63
64
65 #if defined(AFS_HPUX_64BIT_ENV)
66     struct afs_ioctl32 dst32;
67
68     if (is_32bit(u.u_procp)) {  /* is_32bit() in proc_iface.h */
69         AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
70         if (!code)
71             afs_ioctl32_to_afs_ioctl(&dst32, dst);
72         return code;
73     }
74 #endif /* defined(AFS_HPUX_64BIT_ENV) */
75
76 #if defined(AFS_SUN57_64BIT_ENV)
77     struct afs_ioctl32 dst32;
78
79     if (get_udatamodel() == DATAMODEL_ILP32) {
80         AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
81         if (!code)
82             afs_ioctl32_to_afs_ioctl(&dst32, dst);
83         return code;
84     }
85 #endif /* defined(AFS_SUN57_64BIT_ENV) */
86
87 #if defined(AFS_SGI_ENV) && (_MIPS_SZLONG==64)
88     struct afs_ioctl32 dst32;
89
90     if (!ABI_IS_64BIT(get_current_abi())) {
91         AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
92         if (!code)
93             afs_ioctl32_to_afs_ioctl(&dst32, dst);
94         return code;
95     }
96 #endif /* defined(AFS_SGI_ENV) && (_MIPS_SZLONG==64) */
97
98 #if defined(AFS_LINUX_64BIT_KERNEL) && !defined(AFS_ALPHA_LINUX20_ENV) && !defined(AFS_IA64_LINUX20_ENV)
99     struct afs_ioctl32 dst32;
100
101 #ifdef AFS_SPARC64_LINUX26_ENV
102     if (test_thread_flag(TIF_32BIT))
103 #elif defined(AFS_SPARC64_LINUX24_ENV)
104     if (current->thread.flags & SPARC_FLAG_32BIT)
105 #elif defined(AFS_SPARC64_LINUX20_ENV)
106     if (current->tss.flags & SPARC_FLAG_32BIT)
107
108 #elif defined(AFS_AMD64_LINUX26_ENV)
109     if (test_thread_flag(TIF_IA32))
110 #elif defined(AFS_AMD64_LINUX20_ENV)
111     if (current->thread.flags & THREAD_IA32)
112
113 #elif defined(AFS_PPC64_LINUX26_ENV)
114 #if defined(STRUCT_TASK_STRUCT_HAS_THREAD_INFO)
115     if (current->thread_info->flags & _TIF_32BIT) 
116 #else
117     if (task_thread_info(current)->flags & _TIF_32BIT) 
118 #endif      
119 #elif defined(AFS_PPC64_LINUX20_ENV)
120     if (current->thread.flags & PPC_FLAG_32BIT)
121
122 #elif defined(AFS_S390X_LINUX26_ENV)
123     if (test_thread_flag(TIF_31BIT))
124 #elif defined(AFS_S390X_LINUX20_ENV)
125     if (current->thread.flags & S390_FLAG_31BIT)
126
127 #else
128 #error pioctl32 not done for this linux
129 #endif
130     {
131         AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
132         if (!code)
133             afs_ioctl32_to_afs_ioctl(&dst32, dst);
134         return code;
135     }
136 #endif /* defined(AFS_LINUX_64BIT_KERNEL) */
137
138     AFS_COPYIN(cmarg, (caddr_t) dst, sizeof *dst, code);
139     return code;
140 }
141
142
143 #ifdef AFS_AIX32_ENV
144
145 #include "sys/lockl.h"
146
147 /*
148  * syscall -    this is the VRMIX system call entry point.
149  *
150  * NOTE:
151  *      THIS SHOULD BE CHANGED TO afs_syscall(), but requires
152  *      all the user-level calls to `syscall' to change.
153  */
154 syscall(syscall, p1, p2, p3, p4, p5, p6)
155 {
156     register rval1 = 0, code;
157     register monster;
158     int retval = 0;
159 #ifndef AFS_AIX41_ENV
160     extern lock_t kernel_lock;
161     monster = lockl(&kernel_lock, LOCK_SHORT);
162 #endif /* !AFS_AIX41_ENV */
163
164     AFS_STATCNT(syscall);
165     setuerror(0);
166     switch (syscall) {
167     case AFSCALL_CALL:
168         rval1 = afs_syscall_call(p1, p2, p3, p4, p5, p6);
169         break;
170
171     case AFSCALL_SETPAG:
172         AFS_GLOCK();
173         rval1 = afs_setpag();
174         AFS_GUNLOCK();
175         break;
176
177     case AFSCALL_PIOCTL:
178         AFS_GLOCK();
179         rval1 = afs_syscall_pioctl(p1, p2, p3, p4);
180         AFS_GUNLOCK();
181         break;
182
183     case AFSCALL_ICREATE:
184         rval1 = afs_syscall_icreate(p1, p2, p3, p4, p5, p6);
185         break;
186
187     case AFSCALL_IOPEN:
188         rval1 = afs_syscall_iopen(p1, p2, p3);
189         break;
190
191     case AFSCALL_IDEC:
192         rval1 = afs_syscall_iincdec(p1, p2, p3, -1);
193         break;
194
195     case AFSCALL_IINC:
196         rval1 = afs_syscall_iincdec(p1, p2, p3, 1);
197         break;
198
199     case AFSCALL_ICL:
200         AFS_GLOCK();
201         code = Afscall_icl(p1, p2, p3, p4, p5, &retval);
202         AFS_GUNLOCK();
203         if (!code)
204             rval1 = retval;
205         if (!rval1)
206             rval1 = code;
207         break;
208
209     default:
210         rval1 = EINVAL;
211         setuerror(EINVAL);
212         break;
213     }
214
215   out:
216 #ifndef AFS_AIX41_ENV
217     if (monster != LOCK_NEST)
218         unlockl(&kernel_lock);
219 #endif /* !AFS_AIX41_ENV */
220     return getuerror()? -1 : rval1;
221 }
222
223 /*
224  * lsetpag -    interface to afs_setpag().
225  */
226 lsetpag()
227 {
228
229     AFS_STATCNT(lsetpag);
230     return syscall(AFSCALL_SETPAG, 0, 0, 0, 0, 0);
231 }
232
233 /*
234  * lpioctl -    interface to pioctl()
235  */
236 lpioctl(path, cmd, cmarg, follow)
237      char *path, *cmarg;
238 {
239
240     AFS_STATCNT(lpioctl);
241     return syscall(AFSCALL_PIOCTL, path, cmd, cmarg, follow);
242 }
243
244 #else /* !AFS_AIX32_ENV       */
245
246 #if defined(AFS_SGI_ENV)
247 struct afsargs {
248     sysarg_t syscall;
249     sysarg_t parm1;
250     sysarg_t parm2;
251     sysarg_t parm3;
252     sysarg_t parm4;
253     sysarg_t parm5;
254 };
255
256
257 int
258 Afs_syscall(struct afsargs *uap, rval_t * rvp)
259 {
260     int error;
261     long retval;
262
263     AFS_STATCNT(afs_syscall);
264     switch (uap->syscall) {
265     case AFSCALL_ICL:
266         retval = 0;
267         AFS_GLOCK();
268         error =
269             Afscall_icl(uap->parm1, uap->parm2, uap->parm3, uap->parm4,
270                         uap->parm5, &retval);
271         AFS_GUNLOCK();
272         rvp->r_val1 = retval;
273         break;
274 #ifdef AFS_SGI_XFS_IOPS_ENV
275     case AFSCALL_IDEC64:
276         error =
277             afs_syscall_idec64(uap->parm1, uap->parm2, uap->parm3, uap->parm4,
278                                uap->parm5);
279         break;
280     case AFSCALL_IINC64:
281         error =
282             afs_syscall_iinc64(uap->parm1, uap->parm2, uap->parm3, uap->parm4,
283                                uap->parm5);
284         break;
285     case AFSCALL_ILISTINODE64:
286         error =
287             afs_syscall_ilistinode64(uap->parm1, uap->parm2, uap->parm3,
288                                      uap->parm4, uap->parm5);
289         break;
290     case AFSCALL_ICREATENAME64:
291         error =
292             afs_syscall_icreatename64(uap->parm1, uap->parm2, uap->parm3,
293                                       uap->parm4, uap->parm5);
294         break;
295 #endif
296 #ifdef AFS_SGI_VNODE_GLUE
297     case AFSCALL_INIT_KERNEL_CONFIG:
298         error = afs_init_kernel_config(uap->parm1);
299         break;
300 #endif
301     default:
302         error =
303             afs_syscall_call(uap->syscall, uap->parm1, uap->parm2, uap->parm3,
304                              uap->parm4, uap->parm5);
305     }
306     return error;
307 }
308
309 #else /* AFS_SGI_ENV */
310
311 struct iparam {
312     long param1;
313     long param2;
314     long param3;
315     long param4;
316 };
317
318 struct iparam32 {
319     int param1;
320     int param2;
321     int param3;
322     int param4;
323 };
324
325
326 #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))
327 static void
328 iparam32_to_iparam(const struct iparam32 *src, struct iparam *dst)
329 {
330     dst->param1 = src->param1;
331     dst->param2 = src->param2;
332     dst->param3 = src->param3;
333     dst->param4 = src->param4;
334 }
335 #endif
336
337 /*
338  * If you need to change copyin_iparam(), you may also need to change
339  * copyin_afs_ioctl().
340  */
341
342 static int
343 copyin_iparam(caddr_t cmarg, struct iparam *dst)
344 {
345     int code;
346
347 #if defined(AFS_HPUX_64BIT_ENV)
348     struct iparam32 dst32;
349
350     if (is_32bit(u.u_procp)) {  /* is_32bit() in proc_iface.h */
351         AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
352         if (!code)
353             iparam32_to_iparam(&dst32, dst);
354         return code;
355     }
356 #endif /* AFS_HPUX_64BIT_ENV */
357
358 #if defined(AFS_SUN57_64BIT_ENV)
359     struct iparam32 dst32;
360
361     if (get_udatamodel() == DATAMODEL_ILP32) {
362         AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
363         if (!code)
364             iparam32_to_iparam(&dst32, dst);
365         return code;
366     }
367 #endif /* AFS_SUN57_64BIT_ENV */
368
369 #if defined(AFS_LINUX_64BIT_KERNEL) && !defined(AFS_ALPHA_LINUX20_ENV) && !defined(AFS_IA64_LINUX20_ENV)
370     struct iparam32 dst32;
371
372 #ifdef AFS_SPARC64_LINUX26_ENV
373     if (test_thread_flag(TIF_32BIT))
374 #elif defined(AFS_SPARC64_LINUX24_ENV)
375     if (current->thread.flags & SPARC_FLAG_32BIT)
376 #elif defined(AFS_SPARC64_LINUX20_ENV)
377     if (current->tss.flags & SPARC_FLAG_32BIT)
378
379 #elif defined(AFS_AMD64_LINUX26_ENV)
380     if (test_thread_flag(TIF_IA32))
381 #elif defined(AFS_AMD64_LINUX20_ENV)
382     if (current->thread.flags & THREAD_IA32)
383
384 #elif defined(AFS_PPC64_LINUX26_ENV)
385 #if defined(STRUCT_TASK_STRUCT_HAS_THREAD_INFO)
386     if (current->thread_info->flags & _TIF_32BIT) 
387 #else
388     if (task_thread_info(current)->flags & _TIF_32BIT) 
389 #endif      
390 #elif defined(AFS_PPC64_LINUX20_ENV)
391     if (current->thread.flags & PPC_FLAG_32BIT) 
392
393 #elif defined(AFS_S390X_LINUX26_ENV)
394     if (test_thread_flag(TIF_31BIT))
395 #elif defined(AFS_S390X_LINUX20_ENV)
396     if (current->thread.flags & S390_FLAG_31BIT) 
397
398 #else
399 #error iparam32 not done for this linux platform
400 #endif
401     {
402         AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
403         if (!code)
404             iparam32_to_iparam(&dst32, dst);
405         return code;
406     }
407 #endif /* AFS_LINUX_64BIT_KERNEL */
408
409     AFS_COPYIN(cmarg, (caddr_t) dst, sizeof *dst, code);
410     return code;
411 }
412
413 /* Main entry of all afs system calls */
414 #ifdef  AFS_SUN5_ENV
415 extern int afs_sinited;
416
417 /** The 32 bit OS expects the members of this structure to be 32 bit
418  * quantities and the 64 bit OS expects them as 64 bit quanties. Hence
419  * to accomodate both, *long* is used instead of afs_int32
420  */
421
422 #ifdef AFS_SUN57_ENV
423 struct afssysa {
424     long syscall;
425     long parm1;
426     long parm2;
427     long parm3;
428     long parm4;
429     long parm5;
430     long parm6;
431 };
432 #else
433 struct afssysa {
434     afs_int32 syscall;
435     afs_int32 parm1;
436     afs_int32 parm2;
437     afs_int32 parm3;
438     afs_int32 parm4;
439     afs_int32 parm5;
440     afs_int32 parm6;
441 };
442 #endif
443
444 Afs_syscall(register struct afssysa *uap, rval_t * rvp)
445 {
446     int *retval = &rvp->r_val1;
447 #else /* AFS_SUN5_ENV */
448 #if     defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
449 int
450 afs3_syscall(p, args, retval)
451 #ifdef AFS_FBSD50_ENV
452      struct thread *p;
453 #else
454      struct proc *p;
455 #endif
456      void *args;
457      long *retval;
458 {
459     register struct a {
460         long syscall;
461         long parm1;
462         long parm2;
463         long parm3;
464         long parm4;
465         long parm5;
466         long parm6;
467     } *uap = (struct a *)args;
468 #else /* AFS_OSF_ENV */
469 #ifdef AFS_LINUX20_ENV
470 struct afssysargs {
471     long syscall;
472     long parm1;
473     long parm2;
474     long parm3;
475     long parm4;
476     long parm5;
477     long parm6;                 /* not actually used - should be removed */
478 };
479 /* Linux system calls only set up for 5 arguments. */
480 asmlinkage long
481 afs_syscall(long syscall, long parm1, long parm2, long parm3, long parm4)
482 {
483     struct afssysargs args, *uap = &args;
484     long linux_ret = 0;
485     long *retval = &linux_ret;
486     long eparm[4];              /* matches AFSCALL_ICL in fstrace.c */
487 #ifdef AFS_SPARC64_LINUX24_ENV
488     afs_int32 eparm32[4];
489 #endif
490     /* eparm is also used by AFSCALL_CALL in afsd.c */
491 #else
492 #if defined(UKERNEL)
493 Afs_syscall()
494 {
495     register struct a {
496         long syscall;
497         long parm1;
498         long parm2;
499         long parm3;
500         long parm4;
501         long parm5;
502         long parm6;
503     } *uap = (struct a *)u.u_ap;
504 #else /* UKERNEL */
505 int
506 Afs_syscall()
507 {
508     register struct a {
509         long syscall;
510         long parm1;
511         long parm2;
512         long parm3;
513         long parm4;
514         long parm5;
515         long parm6;
516     } *uap = (struct a *)u.u_ap;
517 #endif /* UKERNEL */
518 #if defined(AFS_HPUX_ENV)
519     long *retval = &u.u_rval1;
520 #else
521     int *retval = &u.u_rval1;
522 #endif
523 #endif /* AFS_LINUX20_ENV */
524 #endif /* AFS_OSF_ENV */
525 #endif /* AFS_SUN5_ENV */
526     register int code = 0;
527
528     AFS_STATCNT(afs_syscall);
529 #ifdef        AFS_SUN5_ENV
530     rvp->r_vals = 0;
531     if (!afs_sinited) {
532         return (ENODEV);
533     }
534 #endif
535 #ifdef AFS_LINUX20_ENV
536     lock_kernel();
537     /* setup uap for use below - pull out the magic decoder ring to know
538      * which syscalls have folded argument lists.
539      */
540     uap->syscall = syscall;
541     uap->parm1 = parm1;
542     uap->parm2 = parm2;
543     uap->parm3 = parm3;
544     if (syscall == AFSCALL_ICL || syscall == AFSCALL_CALL) {
545 #ifdef AFS_SPARC64_LINUX24_ENV
546 /* from arch/sparc64/kernel/sys_sparc32.c */
547 #define AA(__x)                                \
548 ({     unsigned long __ret;            \
549        __asm__ ("srl   %0, 0, %0"      \
550                 : "=r" (__ret)         \
551                 : "0" (__x));          \
552        __ret;                          \
553 })
554
555
556 #ifdef AFS_SPARC64_LINUX26_ENV
557         if (test_thread_flag(TIF_32BIT))
558 #else
559         if (current->thread.flags & SPARC_FLAG_32BIT)
560 #endif
561         {
562             AFS_COPYIN((char *)parm4, (char *)eparm32, sizeof(eparm32), code);
563             eparm[0] = AA(eparm32[0]);
564             eparm[1] = AA(eparm32[1]);
565             eparm[2] = AA(eparm32[2]);
566 #undef AA
567         } else
568 #endif
569             AFS_COPYIN((char *)parm4, (char *)eparm, sizeof(eparm), code);
570         uap->parm4 = eparm[0];
571         uap->parm5 = eparm[1];
572         uap->parm6 = eparm[2];
573     } else {
574         uap->parm4 = parm4;
575         uap->parm5 = 0;
576         uap->parm6 = 0;
577     }
578 #endif
579 #if defined(AFS_DARWIN80_ENV)
580     get_vfs_context();
581     osi_Assert(*retval == 0);
582 #endif
583 #if defined(AFS_HPUX_ENV)
584     /*
585      * There used to be code here (duplicated from osi_Init()) for
586      * initializing the semaphore used by AFS_GLOCK().  Was the
587      * duplication to handle the case of a dynamically loaded kernel
588      * module?
589      */
590     osi_InitGlock();
591 #endif
592     if (uap->syscall == AFSCALL_CALL) {
593         code =
594             afs_syscall_call(uap->parm1, uap->parm2, uap->parm3, uap->parm4,
595                              uap->parm5, uap->parm6);
596     } else if (uap->syscall == AFSCALL_SETPAG) {
597 #ifdef  AFS_SUN5_ENV
598         register proc_t *procp;
599
600         procp = ttoproc(curthread);
601         AFS_GLOCK();
602         code = afs_setpag(&procp->p_cred);
603         AFS_GUNLOCK();
604 #else
605         AFS_GLOCK();
606 #if     defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
607         code = afs_setpag(p, args, retval);
608 #else /* AFS_OSF_ENV */
609         code = afs_setpag();
610 #endif
611         AFS_GUNLOCK();
612 #endif
613     } else if (uap->syscall == AFSCALL_PIOCTL) {
614         AFS_GLOCK();
615 #if defined(AFS_SUN5_ENV)
616         code =
617             afs_syscall_pioctl(uap->parm1, uap->parm2, uap->parm3, uap->parm4,
618                                rvp, CRED());
619 #elif defined(AFS_FBSD50_ENV)
620         code =
621             afs_syscall_pioctl(uap->parm1, uap->parm2, uap->parm3, uap->parm4,
622                                p->td_ucred);
623 #elif defined(AFS_DARWIN80_ENV)
624         code =
625             afs_syscall_pioctl(uap->parm1, uap->parm2, uap->parm3, uap->parm4,
626                                kauth_cred_get());
627 #elif defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
628         code =
629             afs_syscall_pioctl(uap->parm1, uap->parm2, uap->parm3, uap->parm4,
630                                p->p_cred->pc_ucred);
631 #else
632         code =
633             afs_syscall_pioctl((char *)uap->parm1, (unsigned int)uap->parm2, (caddr_t)uap->parm3,
634                                (int) uap->parm4);
635 #endif
636         AFS_GUNLOCK();
637     } else if (uap->syscall == AFSCALL_ICREATE) {
638         struct iparam iparams;
639
640         code = copyin_iparam((char *)uap->parm3, &iparams);
641         if (code) {
642 #if defined(KERNEL_HAVE_UERROR)
643             setuerror(code);
644 #endif
645         } else
646 #ifdef  AFS_SUN5_ENV
647             code =
648                 afs_syscall_icreate(uap->parm1, uap->parm2, iparams.param1,
649                                     iparams.param2, iparams.param3,
650                                     iparams.param4, rvp, CRED());
651 #else
652             code =
653                 afs_syscall_icreate(uap->parm1, uap->parm2, iparams.param1,
654                                     iparams.param2,
655 #if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
656                                     iparams.param3, iparams.param4, retval);
657 #else
658                                     iparams.param3, iparams.param4);
659 #endif
660 #endif /* AFS_SUN5_ENV */
661     } else if (uap->syscall == AFSCALL_IOPEN) {
662 #ifdef  AFS_SUN5_ENV
663         code =
664             afs_syscall_iopen(uap->parm1, uap->parm2, uap->parm3, rvp,
665                               CRED());
666 #else
667 #if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
668         code = afs_syscall_iopen(uap->parm1, uap->parm2, uap->parm3, retval);
669 #else
670         code = afs_syscall_iopen(uap->parm1, uap->parm2, uap->parm3);
671 #endif
672 #endif /* AFS_SUN5_ENV */
673     } else if (uap->syscall == AFSCALL_IDEC) {
674 #ifdef  AFS_SUN5_ENV
675         code =
676             afs_syscall_iincdec(uap->parm1, uap->parm2, uap->parm3, -1, rvp,
677                                 CRED());
678 #else
679         code = afs_syscall_iincdec(uap->parm1, uap->parm2, uap->parm3, -1);
680 #endif /* AFS_SUN5_ENV */
681     } else if (uap->syscall == AFSCALL_IINC) {
682 #ifdef  AFS_SUN5_ENV
683         code =
684             afs_syscall_iincdec(uap->parm1, uap->parm2, uap->parm3, 1, rvp,
685                                 CRED());
686 #else
687         code = afs_syscall_iincdec(uap->parm1, uap->parm2, uap->parm3, 1);
688 #endif /* AFS_SUN5_ENV */
689     } else if (uap->syscall == AFSCALL_ICL) {
690         AFS_GLOCK();
691         code =
692             Afscall_icl(uap->parm1, uap->parm2, uap->parm3, uap->parm4,
693                         uap->parm5, retval);
694         AFS_GUNLOCK();
695 #ifdef AFS_LINUX20_ENV
696         if (!code) {
697             /* ICL commands can return values. */
698             code = -linux_ret;  /* Gets negated again at exit below */
699         }
700 #else
701         if (code) {
702 #if defined(KERNEL_HAVE_UERROR)
703             setuerror(code);
704 #endif
705         }
706 #endif /* !AFS_LINUX20_ENV */
707     } else {
708 #if defined(KERNEL_HAVE_UERROR)
709         setuerror(EINVAL);
710 #else
711         code = EINVAL;
712 #endif
713     }
714
715 #if defined(AFS_DARWIN80_ENV)
716     if (uap->syscall != AFSCALL_CALL)
717         put_vfs_context();
718 #endif
719 #ifdef AFS_LINUX20_ENV
720     code = -code;
721     unlock_kernel();
722 #endif
723     return code;
724 }
725 #endif /* AFS_SGI_ENV */
726 #endif /* !AFS_AIX32_ENV       */