macos-rollup-20051013
[openafs.git] / src / sys / afssyscalls.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 <signal.h>
17 #include <sys/errno.h>
18 #include <afs/afs_args.h>
19 #include <sys/file.h>
20 #include <sys/ioctl.h>
21 #if defined(AFS_SUN_ENV) && !defined(AFS_SUN5_ENV)
22 #include <unistd.h>
23 #else
24 #include <stdio.h>
25 #endif
26 #ifdef AFS_SUN5_ENV
27 #include <fcntl.h>
28 #endif
29 #ifdef AFS_SGI_XFS_IOPS_ENV
30 #include "xfsattrs.h"
31 #endif
32 #include <errno.h>
33 #include "afssyscalls.h"
34
35 #ifdef AFS_DEBUG_IOPS
36 FILE *inode_debug_log;          /* If set, write to this file. */
37 /* Indices used for database arrays. */
38 #define CREATE_I 0
39 #define OPEN_I   1
40 #define INC_I    2
41 #define DEC_I    3
42 #define MAX_I    3
43 static void check_iops(int index, char *fun, char *file, int line);
44 #endif /* AFS_DEBUG_IOPS */
45
46 #ifdef AFS_AIX32_ENV
47 /*
48  * in VRMIX, system calls look just like function calls, so we don't
49  * need to do anything!
50  */
51
52 #else
53 #if defined(AFS_SGI_ENV)
54 #ifdef AFS_SGI61_ENV
55 #include <sys/types.h>
56 #endif /* AFS_SGI61_ENV */
57
58 #pragma weak xicreate = icreate
59 #pragma weak xiinc = iinc
60 #pragma weak xidec = idec
61 #pragma weak xiopen = iopen
62 #pragma weak xlsetpag = lsetpag
63 #pragma weak xlpioctl = lpioctl
64 #ifdef notdef
65 #pragma weak xiread = iread
66 #pragma weak xiwrite = iwrite
67 #endif
68
69 int
70 icreate(int dev, int near_inode, int param1, int param2, int param3,
71         int param4)
72 {
73     return (syscall
74             (AFS_ICREATE, dev, near_inode, param1, param2, param3, param4));
75 }
76
77 int
78 iopen(int dev, int inode, int usrmod)
79 {
80     return (syscall(AFS_IOPEN, dev, inode, usrmod));
81 }
82
83 int
84 iinc(int dev, int inode, int inode_p1)
85 {
86     return (syscall(AFS_IINC, dev, inode, inode_p1));
87 }
88
89 int
90 idec(int dev, int inode, int inode_p1)
91 {
92     return (syscall(AFS_IDEC, dev, inode, inode_p1));
93 }
94
95
96 #ifdef AFS_SGI_XFS_IOPS_ENV
97 uint64_t
98 icreatename64(int dev, char *partname, int p0, int p1, int p2, int p3)
99 {
100     uint64_t ino;
101     int code;
102     afs_inode_params_t param;
103
104     /* Use an array so we don't widen the syscall interface. */
105     param[0] = p0;
106     param[1] = p1;
107     param[2] = p2;
108     param[3] = p3;
109     code =
110         afs_syscall(AFSCALL_ICREATENAME64, dev, partname,
111                     1 + strlen(partname), param, &ino);
112     if (code)
113         return (uint64_t) - 1;
114     return ino;
115 }
116
117 int
118 iopen64(int dev, uint64_t inode, int usrmod)
119 {
120     return (syscall
121             (AFS_IOPEN64, dev, (u_int) ((inode >> 32) & 0xffffffff),
122              (u_int) (inode & 0xffffffff), usrmod));
123 }
124
125 int
126 iinc64(int dev, uint64_t inode, int inode_p1)
127 {
128     return (afs_syscall
129             (AFSCALL_IINC64, dev, (u_int) ((inode >> 32) & 0xffffffff),
130              (u_int) (inode & 0xffffffff), inode_p1));
131 }
132
133 int
134 idec64(int dev, uint64_t inode, int inode_p1)
135 {
136     return (afs_syscall
137             (AFSCALL_IDEC64, dev, (u_int) ((inode >> 32) & 0xffffffff),
138              (u_int) (inode & 0xffffffff), inode_p1));
139 }
140
141 int
142 ilistinode64(int dev, uint64_t inode, void *data, int *datalen)
143 {
144     return (afs_syscall
145             (AFSCALL_ILISTINODE64, dev, (u_int) ((inode >> 32) & 0xffffffff),
146              (u_int) (inode & 0xffffffff), data, datalen));
147 }
148
149 #ifdef AFS_DEBUG_IOPS
150 uint64_t
151 debug_icreatename64(int dev, char *partname, int p0, int p1, int p2, int p3,
152                     char *file, int line)
153 {
154     check_iops(CREATE_I, "icreatename64", file, line);
155     return icreatename64(dev, partname, p0, p1, p2, p3);
156 }
157
158 int
159 debug_iopen64(int dev, uint64_t inode, int usrmod, char *file, int line)
160 {
161     check_iops(OPEN_I, "iopen64", file, line);
162     return iopen64(dev, inode, usrmod);
163 }
164
165 int
166 debug_iinc64(int dev, uint64_t inode, int inode_p1, char *file, int line)
167 {
168     check_iops(INC_I, "iinc64", file, line);
169     return iinc64(dev, inode, inode_p1);
170 }
171
172 int
173 debug_idec64(int dev, uint64_t inode, int inode_p1, char *file, int line)
174 {
175     check_iops(DEC_I, "idec64", file, line);
176     return idec64(dev, inode, inode_p1);
177 }
178
179 #endif /* AFS_DEBUG_IOPS */
180 #endif /* AFS_SGI_XFS_IOPS_ENV */
181
182 #ifdef AFS_SGI_VNODE_GLUE
183 /* flag: 1 = has NUMA, 0 = no NUMA, -1 = kernel decides. */
184 int
185 afs_init_kernel_config(int flag)
186 {
187     return afs_syscall(AFSCALL_INIT_KERNEL_CONFIG, flag);
188 }
189 #endif
190
191 #ifdef notdef
192 /* iread and iwrite are deprecated interfaces. Use inode_read and inode_write instead. */
193 int
194 iread(int dev, int inode, int inode_p1, unsigned int offset, char *cbuf,
195       unsigned int count)
196 {
197     return (syscall(AFS_IREAD, dev, inode, inode_p1, offset, cbuf, count));
198 }
199
200 int
201 iwrite(int dev, int inode, int inode_p1, unsigned int offset, char *cbuf,
202        unsigned int count)
203 {
204     return (syscall(AFS_IWRITE, dev, inode, inode_p1, offset, cbuf, count));
205 }
206 #endif /* notdef */
207
208 int
209 lsetpag(void)
210 {
211     return (syscall(AFS_SETPAG));
212 }
213
214 int
215 lpioctl(char *path, int cmd, char *cmarg, int follow)
216 {
217     return (syscall(AFS_PIOCTL, path, cmd, cmarg, follow));
218 }
219 #else /* AFS_SGI_ENV */
220
221 #ifndef AFS_NAMEI_ENV
222 struct iparam {
223     long param1;
224     long param2;
225     long param3;
226     long param4;
227 };
228
229 /* This module contains the stubs for all AFS-related kernel calls that use a single common entry (i.e. AFS_SYSCALL  system call). Note we ignore SIGSYS signals that are sent when a "nosys" is reached so that kernels that don't support this new entry, will revert back to the original old afs entry; note that in some cases (where EINVAL is normally returned) we'll call the appropriate system call twice (sigh) */
230
231 /* Also since we're limited to 6 parameters/call, in some calls (icreate,
232    iread, iwrite) we combine some in a structure */
233
234 int
235 icreate(int dev, int near_inode, int param1, int param2, int param3,
236         int param4)
237 {
238     int errcode;
239     struct iparam iparams;
240
241     iparams.param1 = param1;
242     iparams.param2 = param2;
243     iparams.param3 = param3;
244     iparams.param4 = param4;
245
246     errcode =
247         syscall(AFS_SYSCALL, AFSCALL_ICREATE, dev, near_inode, &iparams);
248     return (errcode);
249 }
250
251
252 int
253 iopen(int dev, int inode, int usrmod)
254 {
255     int errcode;
256
257     errcode = syscall(AFS_SYSCALL, AFSCALL_IOPEN, dev, inode, usrmod);
258     return (errcode);
259 }
260
261
262 int
263 iinc(int dev, int inode, int inode_p1)
264 {
265     int errcode;
266
267     errcode = syscall(AFS_SYSCALL, AFSCALL_IINC, dev, inode, inode_p1);
268     return (errcode);
269 }
270
271
272 int
273 idec(int dev, int inode, int inode_p1)
274 {
275     int errcode;
276
277     errcode = syscall(AFS_SYSCALL, AFSCALL_IDEC, dev, inode, inode_p1);
278     return (errcode);
279 }
280
281
282 #ifdef notdef
283 int
284 iread(int dev, int inode, int inode_p1, unsigned int offset, char *cbuf,
285       unsigned int count)
286 {
287     int errcode;
288     struct iparam iparams;
289
290     iparams.param1 = inode_p1;
291     iparams.param2 = offset;
292     iparams.param3 = (long)cbuf;
293     iparams.param4 = count;
294     errcode = syscall(AFS_SYSCALL, AFSCALL_IREAD, dev, inode, &iparams);
295     return (errcode);
296 }
297
298
299 iwrite(int dev, int inode, int inode_p1, unsigned int offset, char *cbuf,
300        unsigned int count)
301 {
302     int errcode;
303     struct iparam iparams;
304
305     iparams.param1 = inode_p1;
306     iparams.param2 = offset;
307     iparams.param3 = (long)cbuf;
308     iparams.param4 = count;
309
310     errcode = syscall(AFS_SYSCALL, AFSCALL_IWRITE, dev, inode, &iparams);
311     return (errcode);
312 }
313 #endif
314
315 #endif /* AFS_NAMEI_ENV */
316
317 #if defined(AFS_DARWIN80_ENV)
318 int ioctl_afs_syscall(long syscall, long param1, long param2, long param3, 
319                      long param4, long param5, long param6, int *rval) {
320   struct afssysargs syscall_data;
321   int code;
322   int fd = open(SYSCALL_DEV_FNAME, O_RDWR);
323   if(fd < 0)
324     return -1;
325
326   syscall_data.syscall = syscall;
327   syscall_data.param1 = param1;
328   syscall_data.param2 = param2;
329   syscall_data.param3 = param3;
330   syscall_data.param4 = param4;
331   syscall_data.param5 = param5;
332   syscall_data.param6 = param6;
333
334   code = ioctl(fd, VIOC_SYSCALL, &syscall_data);
335
336   close(fd);
337   if (code)
338      return code;
339   *rval=syscall_data.retval;
340   return 0;
341 }
342 #endif
343 #if defined(AFS_LINUX20_ENV)
344 int proc_afs_syscall(long syscall, long param1, long param2, long param3, 
345                      long param4, int *rval) {
346   struct afsprocdata syscall_data;
347   int fd = open(PROC_SYSCALL_FNAME, O_RDWR);
348   if(fd < 0)
349       fd = open(PROC_SYSCALL_ARLA_FNAME, O_RDWR);
350   if(fd < 0)
351     return -1;
352
353   syscall_data.syscall = syscall;
354   syscall_data.param1 = param1;
355   syscall_data.param2 = param2;
356   syscall_data.param3 = param3;
357   syscall_data.param4 = param4;
358
359   *rval = ioctl(fd, VIOC_SYSCALL, &syscall_data);
360
361   close(fd);
362
363   return 0;
364 }
365 #endif
366
367 int
368 lsetpag(void)
369 {
370     int errcode, rval;
371
372 #if defined(AFS_LINUX20_ENV)
373     rval = proc_afs_syscall(AFSCALL_SETPAG,0,0,0,0,&errcode);
374     
375     if(rval)
376       errcode = syscall(AFS_SYSCALL, AFSCALL_SETPAG);
377 #elif defined(AFS_DARWIN80_ENV)
378     if (ioctl_afs_syscall(AFSCALL_SETPAG,0,0,0,0,0,0,&errcode))
379         errcode=ENOSYS;
380 #else
381     errcode = syscall(AFS_SYSCALL, AFSCALL_SETPAG);
382 #endif
383     
384     return (errcode);
385 }
386
387 int
388 lpioctl(char *path, int cmd, char *cmarg, int follow)
389 {
390     int errcode, rval;
391
392 #if defined(AFS_LINUX20_ENV)
393     rval = proc_afs_syscall(AFSCALL_PIOCTL, (long)path, cmd, (long)cmarg, follow, &errcode);
394
395     if(rval)
396     errcode = syscall(AFS_SYSCALL, AFSCALL_PIOCTL, path, cmd, cmarg, follow);
397 #elif defined(AFS_DARWIN80_ENV)
398     if (ioctl_afs_syscall(AFSCALL_PIOCTL,(long)path,cmd,(long)cmarg,follow,0,0,&errcode))
399         errcode=ENOSYS;
400 #else
401     errcode = syscall(AFS_SYSCALL, AFSCALL_PIOCTL, path, cmd, cmarg, follow);
402 #endif
403
404     return (errcode);
405 }
406
407 #endif /* !AFS_SGI_ENV */
408 #endif /* !AFS_AIX32_ENV */
409
410 #ifndef AFS_NAMEI_ENV
411
412 int
413 inode_read(afs_int32 dev, Inode inode, afs_int32 inode_p1,
414            unsigned int offset, char *cbuf, unsigned int count)
415 {
416     int fd;
417     int code = 0;
418
419
420     fd = IOPEN(dev, inode, O_RDONLY);
421     if (fd < 0)
422         return -1;
423
424     code = lseek(fd, offset, SEEK_SET);
425     if (code != offset) {
426         code = -1;
427     } else {
428         code = read(fd, cbuf, count);
429     }
430     close(fd);
431     return code;
432 }
433
434
435 int
436 inode_write(afs_int32 dev, Inode inode, afs_int32 inode_p1,
437             unsigned int offset, char *cbuf, unsigned int count)
438 {
439     int fd;
440     int code = 0;
441
442     fd = IOPEN(dev, inode, O_WRONLY);
443     if (fd < 0)
444         return -1;
445
446     code = lseek(fd, offset, SEEK_SET);
447     if (code != offset) {
448         code = -1;
449     } else {
450         code = write(fd, cbuf, count);
451     }
452     close(fd);
453     return code;
454 }
455
456
457 /* PrintInode
458  *
459  * returns a static string used to print either 32 or 64 bit inode numbers.
460  */
461 #ifdef AFS_64BIT_IOPS_ENV
462 char *
463 PrintInode(char *s, Inode ino)
464 #else
465 char *
466 PrintInode(afs_ino_str_t s, Inode ino)
467 #endif
468 {
469     static afs_ino_str_t result;
470
471     if (!s)
472         s = result;
473
474 #ifdef AFS_64BIT_IOPS_ENV
475     (void)sprintf((char *)s, "%llu", ino);
476 #else
477     (void)sprintf((char *)s, "%u", ino);
478 #endif
479     return (char *)s;
480 }
481 #endif /* AFS_NAMEI_ENV */
482
483
484 #ifdef AFS_DEBUG_IOPS
485 #define MAX_FILE_NAME_LENGTH 32
486 typedef struct {
487     int line;
488     char file[MAX_FILE_NAME_LENGTH];
489 } iops_debug_t;
490 int iops_debug_n_avail[MAX_I + 1];
491 int iops_debug_n_used[MAX_I + 1];
492 iops_debug_t *iops_debug[MAX_I + 1];
493 #define IOPS_DEBUG_MALLOC_STEP 64
494
495 /* check_iops
496  * Returns 1 if first time we've seen this file/line. 
497  * Puts file/line in array so we only print the first time we encounter
498  * this entry.
499  */
500 static void
501 check_iops(int index, char *fun, char *file, int line)
502 {
503     int i;
504     int *availp = &iops_debug_n_avail[index];
505     int *usedp = &iops_debug_n_used[index];
506     iops_debug_t *iops = iops_debug[index];
507     int used;
508
509     if (!inode_debug_log)
510         return;
511
512     used = *usedp;
513     if (used) {
514         for (i = 0; i < used; i++) {
515             if (line == iops[i].line) {
516                 if (!strncmp(file, iops[i].file, MAX_FILE_NAME_LENGTH)) {
517                     /* We've already entered this one. */
518                     return;
519                 }
520             }
521         }
522     }
523
524     /* Not found, enter into db. */
525     if (used >= *availp) {
526         int avail = *availp;
527         avail += IOPS_DEBUG_MALLOC_STEP;
528         if (avail == IOPS_DEBUG_MALLOC_STEP)
529             iops_debug[index] =
530                 (iops_debug_t *) malloc(avail * sizeof(iops_debug_t));
531         else
532             iops_debug[index] =
533                 (iops_debug_t *) realloc(*iops, avail * sizeof(iops_debug_t));
534         if (!iops_debug[index]) {
535             printf("check_iops: Can't %salloc %lu bytes for index %d\n",
536                    (avail == IOPS_DEBUG_MALLOC_STEP) ? "m" : "re",
537                    avail * sizeof(iops_debug_t), index);
538             exit(1);
539         }
540         *availp = avail;
541         iops = iops_debug[index];
542     }
543     iops[used].line = line;
544     (void)strncpy(iops[used].file, file, MAX_FILE_NAME_LENGTH);
545     *usedp = used + 1;
546
547     fprintf(inode_debug_log, "%s: file %s, line %d\n", fun, file, line);
548     fflush(inode_debug_log);
549 }
550 #endif /* AFS_DEBUG_IOPS */