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