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