afsconfig-and-rcsid-all-around-20010705
[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 <afs/param.h>
11 #include <afsconfig.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(dev, near_inode, param1, param2, param3, param4)
68 int dev, near_inode, param1, param2, param3, param4;
69 {
70         return(syscall(AFS_ICREATE, dev, near_inode, param1, param2, param3,
71                        param4));
72 }
73
74 int
75 iopen(dev, inode, usrmod)
76 int dev, inode, usrmod;
77 {
78         return(syscall(AFS_IOPEN, dev, inode, usrmod));
79 }
80
81 int
82 iinc(dev, inode, inode_p1)
83 int dev, inode, inode_p1;
84 {
85         return(syscall(AFS_IINC, dev, inode, inode_p1));
86 }
87
88 int
89 idec(dev, inode, inode_p1)
90 int dev, inode, 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 = afs_syscall(AFSCALL_ICREATENAME64, dev, partname,
110                        1 + strlen(partname), param, &ino);
111     if (code)
112         return (uint64_t)-1;
113     return ino;
114 }
115
116 int
117 iopen64(int dev, uint64_t inode, int usrmod)
118 {
119     return(syscall(AFS_IOPEN64, dev, (u_int)((inode>>32)&0xffffffff),
120                    (u_int)(inode&0xffffffff), usrmod));
121 }
122
123 int
124 iinc64(int dev, uint64_t inode, int inode_p1)
125 {
126     return(afs_syscall(AFSCALL_IINC64, dev,
127                    (u_int)((inode>>32)&0xffffffff),
128                    (u_int)(inode&0xffffffff),
129                    inode_p1));
130 }
131
132 int
133 idec64(int dev, uint64_t inode, int inode_p1)
134 {
135     return(afs_syscall(AFSCALL_IDEC64, dev,
136                    (u_int)((inode>>32)&0xffffffff),
137                    (u_int)(inode&0xffffffff),
138                    inode_p1));
139 }
140
141 int
142 ilistinode64(int dev, uint64_t inode, void *data, int *datalen)
143 {
144     return(afs_syscall(AFSCALL_ILISTINODE64, dev,
145                    (u_int)((inode>>32)&0xffffffff),
146                    (u_int)(inode&0xffffffff),
147                    data, datalen));
148 }
149
150 #ifdef AFS_DEBUG_IOPS
151 uint64_t debug_icreatename64(int dev, char *partname, int p0, int p1,
152                                     int p2, int p3, 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 debug_iopen64(int dev, uint64_t inode, int usrmod, char *file, int line)
159 {
160     check_iops(OPEN_I, "iopen64", file, line);
161     return iopen64(dev, inode, usrmod);
162 }
163
164 int debug_iinc64(int dev, uint64_t inode, int inode_p1, char *file, int line)
165 {
166     check_iops(INC_I, "iinc64", file, line);
167     return iinc64(dev, inode, inode_p1);
168 }
169
170 int debug_idec64(int dev, uint64_t inode, int inode_p1, char *file, int line)
171 {
172     check_iops(DEC_I, "idec64", file, line);
173     return idec64(dev, inode, inode_p1);
174 }
175
176 #endif /* AFS_DEBUG_IOPS */
177 #endif /* AFS_SGI_XFS_IOPS_ENV */
178
179 #ifdef AFS_SGI_VNODE_GLUE
180 /* flag: 1 = has NUMA, 0 = no NUMA, -1 = kernel decides. */
181 int afs_init_kernel_config(int flag)
182 {
183     return afs_syscall(AFSCALL_INIT_KERNEL_CONFIG, flag);
184 }
185 #endif
186
187 #ifdef notdef
188 /* iread and iwrite are deprecated interfaces. Use inode_read and inode_write instead. */
189 int
190 iread(dev, inode, inode_p1, offset, cbuf, count)
191 int dev, inode, inode_p1;
192 unsigned int offset;
193 char *cbuf;
194 unsigned int count;
195 {
196         return(syscall(AFS_IREAD, dev, inode, inode_p1, offset, cbuf, count));
197 }
198
199 int
200 iwrite(dev, inode, inode_p1, offset, cbuf, count)
201 int dev, inode, inode_p1;
202 unsigned int offset;
203 char *cbuf;
204 unsigned int count;
205 {
206         return(syscall(AFS_IWRITE, dev, inode, inode_p1, offset, cbuf, count));
207 }
208 #endif /* notdef */
209
210 int
211 lsetpag()
212 {
213         return(syscall(AFS_SETPAG));
214 }
215
216 int
217 lpioctl(path, cmd, cmarg, follow)
218 char *path, *cmarg;
219 int cmd, follow;
220 {
221         return(syscall(AFS_PIOCTL, path, cmd, cmarg, follow));
222 }
223 #else /* AFS_SGI_ENV */
224
225 #ifndef AFS_NAMEI_ENV
226 struct iparam {
227     long param1;
228     long param2;
229     long param3;
230     long param4;
231 };
232
233 /* 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) */
234
235 /* Also since we're limited to 6 parameters/call, in some calls (icreate,
236    iread, iwrite) we combine some in a structure */
237
238 icreate(dev, near_inode, param1, param2, param3, param4)
239 int dev, near_inode, param1, param2, param3, param4;
240 {
241     extern int errno;
242     int errcode;
243     struct iparam iparams;
244
245     iparams.param1 = param1;
246     iparams.param2 = param2;
247     iparams.param3 = param3;
248     iparams.param4 = param4;
249
250     errcode = syscall(AFS_SYSCALL, AFSCALL_ICREATE, dev, near_inode, &iparams);
251     return (errcode);
252 }
253
254
255 iopen(dev, inode, usrmod)
256 int dev, inode, usrmod;
257 {
258     extern int errno;
259     int errcode;
260
261     errcode = syscall(AFS_SYSCALL, AFSCALL_IOPEN, dev, inode, usrmod);
262     return (errcode);
263 }
264
265
266 iinc(dev, inode, inode_p1)
267 int dev, inode, inode_p1;
268 {
269     extern int errno;
270     int errcode;
271
272     errcode = syscall(AFS_SYSCALL, AFSCALL_IINC, dev, inode, inode_p1);
273     return (errcode);
274 }
275
276
277 idec(dev, inode, inode_p1)
278 int dev, inode, inode_p1;
279 {
280     extern int errno;
281     int errcode;
282
283     errcode = syscall(AFS_SYSCALL, AFSCALL_IDEC, dev, inode, inode_p1);
284     return (errcode);
285 }
286
287
288 #ifdef notdef
289 iread(dev, inode, inode_p1, offset, cbuf, count)
290 int dev, inode, inode_p1;
291 unsigned int offset;
292 char *cbuf;
293 unsigned int count;
294 {
295     extern int errno;
296     int errcode;
297     struct iparam iparams;
298
299     iparams.param1 = inode_p1;
300     iparams.param2 = offset;
301     iparams.param3 = (long)cbuf;
302     iparams.param4 = count;
303     errcode = syscall(AFS_SYSCALL, AFSCALL_IREAD, dev, inode, &iparams);
304     return (errcode);
305 }
306
307
308 iwrite(dev, inode, inode_p1, offset, cbuf, count)
309 int dev, inode, inode_p1;
310 unsigned int offset;
311 char *cbuf;
312 unsigned int count;
313 {
314     extern int errno;
315     int errcode;
316     struct iparam iparams;
317
318     iparams.param1 = inode_p1;
319     iparams.param2 = offset;
320     iparams.param3 = (long)cbuf;
321     iparams.param4 = count;
322
323     errcode = syscall(AFS_SYSCALL, AFSCALL_IWRITE, dev, inode, &iparams);
324     return (errcode);
325 }
326 #endif
327
328 #endif /* AFS_NAMEI_ENV */
329
330 lsetpag()
331 {
332     extern int errno;
333     int errcode;
334
335     errcode = syscall(AFS_SYSCALL, AFSCALL_SETPAG);
336     return (errcode);
337 }
338
339 lpioctl(path, cmd, cmarg, follow)
340 char *path, *cmarg;
341 int cmd, follow;
342 {
343     extern int errno;
344     int errcode;
345
346     errcode = syscall(AFS_SYSCALL, AFSCALL_PIOCTL, path, cmd, cmarg, follow);
347     return (errcode);
348 }
349
350 #endif  /* !AFS_SGI_ENV */
351 #endif  /* !AFS_AIX32_ENV */
352
353 #ifndef AFS_NAMEI_ENV
354
355 int
356 inode_read(dev, inode, inode_p1, offset, cbuf, count)
357 afs_int32 dev;
358 Inode inode;
359 afs_int32 inode_p1;
360 unsigned int offset;
361 char *cbuf;
362 unsigned int count;
363 {
364     int fd;
365     int code = 0;
366
367
368     fd = IOPEN(dev, inode, O_RDONLY);
369     if (fd<0)
370         return -1;
371
372     code = lseek(fd, offset, SEEK_SET);
373     if (code != offset) {
374         code =  -1;
375     }
376     else {
377         code = read(fd, cbuf, count);
378     }
379     close(fd);
380     return code;
381 }
382
383
384 int
385 inode_write(dev, inode, inode_p1, offset, cbuf, count)
386 afs_int32 dev;
387 Inode inode;
388 afs_int32 inode_p1;
389 unsigned int offset;
390 char *cbuf;
391 unsigned int count;
392 {
393     int fd;
394     int code = 0;
395
396     fd = IOPEN(dev, inode, O_WRONLY);
397     if (fd<0)
398         return -1;
399
400     code = lseek(fd, offset, SEEK_SET);
401     if (code != offset) {
402         code =  -1;
403     }
404     else {
405         code = write(fd, cbuf, count);
406     }
407     close(fd);
408     return code;
409 }
410
411
412 /* PrintInode
413  *
414  * returns a static string used to print either 32 or 64 bit inode numbers.
415  */
416 #ifdef AFS_64BIT_IOPS_ENV
417 char * PrintInode(char *s, Inode ino)
418 #else
419 char * PrintInode(s, ino)
420 afs_ino_str_t s;
421 Inode ino;
422 #endif
423 {
424     static afs_ino_str_t result; 
425
426     if (!s)
427         s = result;
428
429 #ifdef AFS_64BIT_IOPS_ENV
430     (void) sprintf((char*)s, "%llu", ino);
431 #else
432     (void) sprintf((char*)s, "%u", ino);
433 #endif
434     return (char*)s;
435 }
436 #endif /* AFS_NAMEI_ENV */
437
438
439 #ifdef AFS_DEBUG_IOPS
440 #define MAX_FILE_NAME_LENGTH 32
441 typedef struct {
442     int line;
443     char file[MAX_FILE_NAME_LENGTH];
444 } iops_debug_t;
445 int iops_debug_n_avail[MAX_I+1];
446 int iops_debug_n_used[MAX_I+1];
447 iops_debug_t *iops_debug[MAX_I+1];
448 #define IOPS_DEBUG_MALLOC_STEP 64
449
450 /* check_iops
451  * Returns 1 if first time we've seen this file/line. 
452  * Puts file/line in array so we only print the first time we encounter
453  * this entry.
454  */
455 static void check_iops(int index, char *fun, char *file, int line)
456 {
457     int i;
458     int *availp = &iops_debug_n_avail[index];
459     int *usedp = &iops_debug_n_used[index];
460     iops_debug_t *iops = iops_debug[index];
461     int used;
462
463     if (!inode_debug_log)
464         return;
465
466     used = *usedp;
467     if (used) {
468         for (i=0; i< used; i++) {
469             if (line == iops[i].line) {
470                 if (!strncmp(file, iops[i].file, MAX_FILE_NAME_LENGTH)) {
471                     /* We've already entered this one. */
472                     return;
473                 }
474             }
475         }
476     }
477
478     /* Not found, enter into db. */
479     if (used >= *availp) {
480         int avail = *availp;
481         avail += IOPS_DEBUG_MALLOC_STEP;
482         if (avail == IOPS_DEBUG_MALLOC_STEP)
483             iops_debug[index] =
484                 (iops_debug_t*) malloc(avail * sizeof(iops_debug_t));
485         else
486             iops_debug[index] = (iops_debug_t*) realloc(*iops,
487                                            avail * sizeof(iops_debug_t));
488         if (!iops_debug[index]) {
489             printf("check_iops: Can't %salloc %lu bytes for index %d\n",
490                    (avail == IOPS_DEBUG_MALLOC_STEP) ? "m" : "re",
491                    avail * sizeof(iops_debug_t), index);
492             exit(1);
493         }
494         *availp = avail;
495         iops = iops_debug[index];
496     }
497     iops[used].line = line;
498     (void) strncpy(iops[used].file, file, MAX_FILE_NAME_LENGTH);
499     *usedp = used + 1;
500
501     fprintf(inode_debug_log, "%s: file %s, line %d\n", fun, file, line);
502     fflush(inode_debug_log);
503 }
504 #endif /* AFS_DEBUG_IOPS */
505