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