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