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