]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/compat/linux/linux_time.c
Fix FreeBSD Linux ABI kernel panic.
[FreeBSD/FreeBSD.git] / sys / compat / linux / linux_time.c
1 /*      $NetBSD: linux_time.c,v 1.14 2006/05/14 03:40:54 christos Exp $ */
2
3 /*-
4  * SPDX-License-Identifier: BSD-2-Clause-NetBSD
5  *
6  * Copyright (c) 2001 The NetBSD Foundation, Inc.
7  * All rights reserved.
8  *
9  * This code is derived from software contributed to The NetBSD Foundation
10  * by Emmanuel Dreyfus.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
25  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD$");
36 #if 0
37 __KERNEL_RCSID(0, "$NetBSD: linux_time.c,v 1.14 2006/05/14 03:40:54 christos Exp $");
38 #endif
39
40 #include "opt_compat.h"
41
42 #include <sys/param.h>
43 #include <sys/kernel.h>
44 #include <sys/lock.h>
45 #include <sys/ucred.h>
46 #include <sys/limits.h>
47 #include <sys/mount.h>
48 #include <sys/mutex.h>
49 #include <sys/resourcevar.h>
50 #include <sys/sdt.h>
51 #include <sys/signal.h>
52 #include <sys/stdint.h>
53 #include <sys/syscallsubr.h>
54 #include <sys/sysproto.h>
55 #include <sys/time.h>
56 #include <sys/systm.h>
57 #include <sys/proc.h>
58
59 #ifdef COMPAT_LINUX32
60 #include <machine/../linux32/linux.h>
61 #include <machine/../linux32/linux32_proto.h>
62 #else
63 #include <machine/../linux/linux.h>
64 #include <machine/../linux/linux_proto.h>
65 #endif
66
67 #include <compat/linux/linux_dtrace.h>
68 #include <compat/linux/linux_timer.h>
69
70 /* DTrace init */
71 LIN_SDT_PROVIDER_DECLARE(LINUX_DTRACE);
72
73 /**
74  * DTrace probes in this module.
75  */
76 LIN_SDT_PROBE_DEFINE2(time, native_to_linux_timespec, entry,
77     "struct l_timespec *", "struct timespec *");
78 LIN_SDT_PROBE_DEFINE0(time, native_to_linux_timespec, return);
79 LIN_SDT_PROBE_DEFINE2(time, linux_to_native_timespec, entry,
80     "struct timespec *", "struct l_timespec *");
81 LIN_SDT_PROBE_DEFINE1(time, linux_to_native_timespec, return, "int");
82 LIN_SDT_PROBE_DEFINE2(time, linux_to_native_clockid, entry, "clockid_t *",
83     "clockid_t");
84 LIN_SDT_PROBE_DEFINE1(time, linux_to_native_clockid, unsupported_clockid,
85     "clockid_t");
86 LIN_SDT_PROBE_DEFINE1(time, linux_to_native_clockid, unknown_clockid,
87     "clockid_t");
88 LIN_SDT_PROBE_DEFINE1(time, linux_to_native_clockid, return, "int");
89 LIN_SDT_PROBE_DEFINE2(time, linux_clock_gettime, entry, "clockid_t",
90     "struct l_timespec *");
91 LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime, conversion_error, "int");
92 LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime, gettime_error, "int");
93 LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime, copyout_error, "int");
94 LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime, return, "int");
95 LIN_SDT_PROBE_DEFINE2(time, linux_clock_settime, entry, "clockid_t",
96     "struct l_timespec *");
97 LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime, conversion_error, "int");
98 LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime, settime_error, "int");
99 LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime, copyin_error, "int");
100 LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime, return, "int");
101 LIN_SDT_PROBE_DEFINE2(time, linux_clock_getres, entry, "clockid_t",
102     "struct l_timespec *");
103 LIN_SDT_PROBE_DEFINE0(time, linux_clock_getres, nullcall);
104 LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres, conversion_error, "int");
105 LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres, getres_error, "int");
106 LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres, copyout_error, "int");
107 LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres, return, "int");
108 LIN_SDT_PROBE_DEFINE2(time, linux_nanosleep, entry, "const struct l_timespec *",
109     "struct l_timespec *");
110 LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, conversion_error, "int");
111 LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, copyout_error, "int");
112 LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, copyin_error, "int");
113 LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, return, "int");
114 LIN_SDT_PROBE_DEFINE4(time, linux_clock_nanosleep, entry, "clockid_t", "int",
115     "struct l_timespec *", "struct l_timespec *");
116 LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, conversion_error, "int");
117 LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, copyout_error, "int");
118 LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, copyin_error, "int");
119 LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, unsupported_flags, "int");
120 LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, unsupported_clockid, "int");
121 LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, return, "int");
122
123
124 int
125 native_to_linux_timespec(struct l_timespec *ltp, struct timespec *ntp)
126 {
127
128         LIN_SDT_PROBE2(time, native_to_linux_timespec, entry, ltp, ntp);
129 #ifdef COMPAT_LINUX32
130         if (ntp->tv_sec > INT_MAX || ntp->tv_sec < INT_MIN)
131                 return (EOVERFLOW);
132 #endif
133         ltp->tv_sec = ntp->tv_sec;
134         ltp->tv_nsec = ntp->tv_nsec;
135
136         LIN_SDT_PROBE0(time, native_to_linux_timespec, return);
137         return (0);
138 }
139
140 int
141 linux_to_native_timespec(struct timespec *ntp, struct l_timespec *ltp)
142 {
143
144         LIN_SDT_PROBE2(time, linux_to_native_timespec, entry, ntp, ltp);
145
146         if (ltp->tv_sec < 0 || ltp->tv_nsec < 0 || ltp->tv_nsec > 999999999) {
147                 LIN_SDT_PROBE1(time, linux_to_native_timespec, return, EINVAL);
148                 return (EINVAL);
149         }
150         ntp->tv_sec = ltp->tv_sec;
151         ntp->tv_nsec = ltp->tv_nsec;
152
153         LIN_SDT_PROBE1(time, linux_to_native_timespec, return, 0);
154         return (0);
155 }
156
157 int
158 native_to_linux_itimerspec(struct l_itimerspec *ltp, struct itimerspec *ntp)
159 {
160         int error;
161
162         error = native_to_linux_timespec(&ltp->it_interval, &ntp->it_interval);
163         if (error == 0)
164                 error = native_to_linux_timespec(&ltp->it_value, &ntp->it_interval);
165         return (error);
166 }
167
168 int
169 linux_to_native_itimerspec(struct itimerspec *ntp, struct l_itimerspec *ltp)
170 {
171         int error;
172
173         error = linux_to_native_timespec(&ntp->it_interval, &ltp->it_interval);
174         if (error == 0)
175                 error = linux_to_native_timespec(&ntp->it_value, &ltp->it_value);
176         return (error);
177 }
178
179 int
180 linux_to_native_clockid(clockid_t *n, clockid_t l)
181 {
182
183         LIN_SDT_PROBE2(time, linux_to_native_clockid, entry, n, l);
184
185         if (l < 0) {
186                 /* cpu-clock */
187                 if ((l & LINUX_CLOCKFD_MASK) == LINUX_CLOCKFD)
188                         return (EINVAL);
189                 if (LINUX_CPUCLOCK_WHICH(l) >= LINUX_CPUCLOCK_MAX)
190                         return (EINVAL);
191
192                 if (LINUX_CPUCLOCK_PERTHREAD(l))
193                         *n = CLOCK_THREAD_CPUTIME_ID;
194                 else
195                         *n = CLOCK_PROCESS_CPUTIME_ID;
196                 return (0);
197         }
198
199         switch (l) {
200         case LINUX_CLOCK_REALTIME:
201                 *n = CLOCK_REALTIME;
202                 break;
203         case LINUX_CLOCK_MONOTONIC:
204                 *n = CLOCK_MONOTONIC;
205                 break;
206         case LINUX_CLOCK_REALTIME_COARSE:
207                 *n = CLOCK_REALTIME_FAST;
208                 break;
209         case LINUX_CLOCK_MONOTONIC_COARSE:
210                 *n = CLOCK_MONOTONIC_FAST;
211                 break;
212         case LINUX_CLOCK_BOOTTIME:
213                 *n = CLOCK_UPTIME;
214                 break;
215         case LINUX_CLOCK_MONOTONIC_RAW:
216         case LINUX_CLOCK_REALTIME_ALARM:
217         case LINUX_CLOCK_BOOTTIME_ALARM:
218         case LINUX_CLOCK_SGI_CYCLE:
219         case LINUX_CLOCK_TAI:
220                 LIN_SDT_PROBE1(time, linux_to_native_clockid,
221                     unsupported_clockid, l);
222                 LIN_SDT_PROBE1(time, linux_to_native_clockid, return, EINVAL);
223                 return (EINVAL);
224         default:
225                 LIN_SDT_PROBE1(time, linux_to_native_clockid,
226                     unknown_clockid, l);
227                 LIN_SDT_PROBE1(time, linux_to_native_clockid, return, EINVAL);
228                 return (EINVAL);
229         }
230
231         LIN_SDT_PROBE1(time, linux_to_native_clockid, return, 0);
232         return (0);
233 }
234
235 int
236 linux_to_native_timerflags(int *nflags, int flags)
237 {
238
239         if (flags & ~LINUX_TIMER_ABSTIME)
240                 return (EINVAL);
241         *nflags = 0;
242         if (flags & LINUX_TIMER_ABSTIME)
243                 *nflags |= TIMER_ABSTIME;
244         return (0);
245 }
246
247 int
248 linux_clock_gettime(struct thread *td, struct linux_clock_gettime_args *args)
249 {
250         struct l_timespec lts;
251         struct timespec tp;
252         struct rusage ru;
253         struct thread *targettd;
254         struct proc *p;
255         int error, clockwhich;
256         clockid_t nwhich = 0;   /* XXX: GCC */
257         pid_t pid;
258         lwpid_t tid;
259
260         LIN_SDT_PROBE2(time, linux_clock_gettime, entry, args->which, args->tp);
261
262         error = linux_to_native_clockid(&nwhich, args->which);
263         if (error != 0) {
264                 LIN_SDT_PROBE1(time, linux_clock_gettime, conversion_error,
265                     error);
266                 LIN_SDT_PROBE1(time, linux_clock_gettime, return, error);
267                 return (error);
268         }
269
270         switch (nwhich) {
271         case CLOCK_PROCESS_CPUTIME_ID:
272                 clockwhich = LINUX_CPUCLOCK_WHICH(args->which);
273                 pid = LINUX_CPUCLOCK_ID(args->which);
274                 if (pid == 0) {
275                         p = td->td_proc;
276                         PROC_LOCK(p);
277                 } else {
278                         error = pget(pid, PGET_CANSEE, &p);
279                         if (error != 0)
280                                 return (EINVAL);
281                 }
282                 switch (clockwhich) {
283                 case LINUX_CPUCLOCK_PROF:
284                         PROC_STATLOCK(p);
285                         calcru(p, &ru.ru_utime, &ru.ru_stime);
286                         PROC_STATUNLOCK(p);
287                         PROC_UNLOCK(p);
288                         timevaladd(&ru.ru_utime, &ru.ru_stime);
289                         TIMEVAL_TO_TIMESPEC(&ru.ru_utime, &tp);
290                         break;
291                 case LINUX_CPUCLOCK_VIRT:
292                         PROC_STATLOCK(p);
293                         calcru(p, &ru.ru_utime, &ru.ru_stime);
294                         PROC_STATUNLOCK(p);
295                         PROC_UNLOCK(p);
296                         TIMEVAL_TO_TIMESPEC(&ru.ru_utime, &tp);
297                         break;
298                 case LINUX_CPUCLOCK_SCHED:
299                         PROC_UNLOCK(p);
300                         error = kern_clock_getcpuclockid2(td, pid,
301                             CPUCLOCK_WHICH_PID, &nwhich);
302                         if (error != 0)
303                                 return (EINVAL);
304                         error = kern_clock_gettime(td, nwhich, &tp);
305                         break;
306                 default:
307                         PROC_UNLOCK(p);
308                         return (EINVAL);
309                 }
310
311                 break;
312
313         case CLOCK_THREAD_CPUTIME_ID:
314                 clockwhich = LINUX_CPUCLOCK_WHICH(args->which);
315                 p = td->td_proc;
316                 tid = LINUX_CPUCLOCK_ID(args->which);
317                 if (tid == 0) {
318                         targettd = td;
319                         PROC_LOCK(p);
320                 } else {
321                         targettd = tdfind(tid, p->p_pid);
322                         if (targettd == NULL)
323                                 return (EINVAL);
324                 }
325                 switch (clockwhich) {
326                 case LINUX_CPUCLOCK_PROF:
327                         PROC_STATLOCK(p);
328                         thread_lock(targettd);
329                         rufetchtd(targettd, &ru);
330                         thread_unlock(targettd);
331                         PROC_STATUNLOCK(p);
332                         PROC_UNLOCK(p);
333                         timevaladd(&ru.ru_utime, &ru.ru_stime);
334                         TIMEVAL_TO_TIMESPEC(&ru.ru_utime, &tp);
335                         break;
336                 case LINUX_CPUCLOCK_VIRT:
337                         PROC_STATLOCK(p);
338                         thread_lock(targettd);
339                         rufetchtd(targettd, &ru);
340                         thread_unlock(targettd);
341                         PROC_STATUNLOCK(p);
342                         PROC_UNLOCK(p);
343                         TIMEVAL_TO_TIMESPEC(&ru.ru_utime, &tp);
344                         break;
345                 case LINUX_CPUCLOCK_SCHED:
346                         error = kern_clock_getcpuclockid2(td, tid,
347                             CPUCLOCK_WHICH_TID, &nwhich);
348                         PROC_UNLOCK(p);
349                         if (error != 0)
350                                 return (EINVAL);
351                         error = kern_clock_gettime(td, nwhich, &tp);
352                         break;
353                 default:
354                         PROC_UNLOCK(p);
355                         return (EINVAL);
356                 }
357                 break;
358
359         default:
360                 error = kern_clock_gettime(td, nwhich, &tp);
361                 break;
362         }
363         if (error != 0) {
364                 LIN_SDT_PROBE1(time, linux_clock_gettime, gettime_error, error);
365                 LIN_SDT_PROBE1(time, linux_clock_gettime, return, error);
366                 return (error);
367         }
368         error = native_to_linux_timespec(&lts, &tp);
369         if (error != 0)
370                 return (error);
371         error = copyout(&lts, args->tp, sizeof lts);
372         if (error != 0)
373                 LIN_SDT_PROBE1(time, linux_clock_gettime, copyout_error, error);
374
375         LIN_SDT_PROBE1(time, linux_clock_gettime, return, error);
376         return (error);
377 }
378
379 int
380 linux_clock_settime(struct thread *td, struct linux_clock_settime_args *args)
381 {
382         struct timespec ts;
383         struct l_timespec lts;
384         int error;
385         clockid_t nwhich = 0;   /* XXX: GCC */
386
387         LIN_SDT_PROBE2(time, linux_clock_settime, entry, args->which, args->tp);
388
389         error = linux_to_native_clockid(&nwhich, args->which);
390         if (error != 0) {
391                 LIN_SDT_PROBE1(time, linux_clock_settime, conversion_error,
392                     error);
393                 LIN_SDT_PROBE1(time, linux_clock_settime, return, error);
394                 return (error);
395         }
396         error = copyin(args->tp, &lts, sizeof lts);
397         if (error != 0) {
398                 LIN_SDT_PROBE1(time, linux_clock_settime, copyin_error, error);
399                 LIN_SDT_PROBE1(time, linux_clock_settime, return, error);
400                 return (error);
401         }
402         error = linux_to_native_timespec(&ts, &lts);
403         if (error != 0) {
404                 LIN_SDT_PROBE1(time, linux_clock_settime, conversion_error,
405                     error);
406                 LIN_SDT_PROBE1(time, linux_clock_settime, return, error);
407                 return (error);
408         }
409
410         error = kern_clock_settime(td, nwhich, &ts);
411         if (error != 0)
412                 LIN_SDT_PROBE1(time, linux_clock_settime, settime_error, error);
413
414         LIN_SDT_PROBE1(time, linux_clock_settime, return, error);
415         return (error);
416 }
417
418 int
419 linux_clock_getres(struct thread *td, struct linux_clock_getres_args *args)
420 {
421         struct proc *p;
422         struct timespec ts;
423         struct l_timespec lts;
424         int error, clockwhich;
425         clockid_t nwhich = 0;   /* XXX: GCC */
426         pid_t pid;
427         lwpid_t tid;
428
429         LIN_SDT_PROBE2(time, linux_clock_getres, entry, args->which, args->tp);
430
431         error = linux_to_native_clockid(&nwhich, args->which);
432         if (error != 0) {
433                 LIN_SDT_PROBE1(time, linux_clock_getres, conversion_error,
434                     error);
435                 LIN_SDT_PROBE1(time, linux_clock_getres, return, error);
436                 return (error);
437         }
438
439         /*
440          * Check user supplied clock id in case of per-process
441          * or thread-specific cpu-time clock.
442          */
443         switch (nwhich) {
444         case CLOCK_THREAD_CPUTIME_ID:
445                 tid = LINUX_CPUCLOCK_ID(args->which);
446                 if (tid != 0) {
447                         p = td->td_proc;
448                         if (tdfind(tid, p->p_pid) == NULL)
449                                 return (ESRCH);
450                         PROC_UNLOCK(p);
451                 }
452                 break;
453         case CLOCK_PROCESS_CPUTIME_ID:
454                 pid = LINUX_CPUCLOCK_ID(args->which);
455                 if (pid != 0) {
456                         error = pget(pid, PGET_CANSEE, &p);
457                         if (error != 0)
458                                 return (EINVAL);
459                         PROC_UNLOCK(p);
460                 }
461                 break;
462         }
463
464         if (args->tp == NULL) {
465                 LIN_SDT_PROBE0(time, linux_clock_getres, nullcall);
466                 LIN_SDT_PROBE1(time, linux_clock_getres, return, 0);
467                 return (0);
468         }
469
470         switch (nwhich) {
471         case CLOCK_THREAD_CPUTIME_ID:
472         case CLOCK_PROCESS_CPUTIME_ID:
473                 clockwhich = LINUX_CPUCLOCK_WHICH(args->which);
474                 switch (clockwhich) {
475                 case LINUX_CPUCLOCK_PROF:
476                         nwhich = CLOCK_PROF;
477                         break;
478                 case LINUX_CPUCLOCK_VIRT:
479                         nwhich = CLOCK_VIRTUAL;
480                         break;
481                 case LINUX_CPUCLOCK_SCHED:
482                         break;
483                 default:
484                         return (EINVAL);
485                 }
486                 break;
487
488         default:
489                 break;
490         }
491         error = kern_clock_getres(td, nwhich, &ts);
492         if (error != 0) {
493                 LIN_SDT_PROBE1(time, linux_clock_getres, getres_error, error);
494                 LIN_SDT_PROBE1(time, linux_clock_getres, return, error);
495                 return (error);
496         }
497         error = native_to_linux_timespec(&lts, &ts);
498         if (error != 0)
499                 return (error);
500         error = copyout(&lts, args->tp, sizeof lts);
501         if (error != 0)
502                 LIN_SDT_PROBE1(time, linux_clock_getres, copyout_error, error);
503
504         LIN_SDT_PROBE1(time, linux_clock_getres, return, error);
505         return (error);
506 }
507
508 int
509 linux_nanosleep(struct thread *td, struct linux_nanosleep_args *args)
510 {
511         struct timespec *rmtp;
512         struct l_timespec lrqts, lrmts;
513         struct timespec rqts, rmts;
514         int error, error2;
515
516         LIN_SDT_PROBE2(time, linux_nanosleep, entry, args->rqtp, args->rmtp);
517
518         error = copyin(args->rqtp, &lrqts, sizeof lrqts);
519         if (error != 0) {
520                 LIN_SDT_PROBE1(time, linux_nanosleep, copyin_error, error);
521                 LIN_SDT_PROBE1(time, linux_nanosleep, return, error);
522                 return (error);
523         }
524
525         if (args->rmtp != NULL)
526                 rmtp = &rmts;
527         else
528                 rmtp = NULL;
529
530         error = linux_to_native_timespec(&rqts, &lrqts);
531         if (error != 0) {
532                 LIN_SDT_PROBE1(time, linux_nanosleep, conversion_error, error);
533                 LIN_SDT_PROBE1(time, linux_nanosleep, return, error);
534                 return (error);
535         }
536         error = kern_nanosleep(td, &rqts, rmtp);
537         if (error == EINTR && args->rmtp != NULL) {
538                 error2 = native_to_linux_timespec(&lrmts, rmtp);
539                 if (error2 != 0)
540                         return (error2);
541                 error2 = copyout(&lrmts, args->rmtp, sizeof(lrmts));
542                 if (error2 != 0) {
543                         LIN_SDT_PROBE1(time, linux_nanosleep, copyout_error,
544                             error2);
545                         LIN_SDT_PROBE1(time, linux_nanosleep, return, error2);
546                         return (error2);
547                 }
548         }
549
550         LIN_SDT_PROBE1(time, linux_nanosleep, return, error);
551         return (error);
552 }
553
554 int
555 linux_clock_nanosleep(struct thread *td, struct linux_clock_nanosleep_args *args)
556 {
557         struct timespec *rmtp;
558         struct l_timespec lrqts, lrmts;
559         struct timespec rqts, rmts;
560         int error, error2, flags;
561         clockid_t clockid;
562
563         LIN_SDT_PROBE4(time, linux_clock_nanosleep, entry, args->which,
564             args->flags, args->rqtp, args->rmtp);
565
566         error = linux_to_native_timerflags(&flags, args->flags);
567         if (error != 0) {
568                 LIN_SDT_PROBE1(time, linux_clock_nanosleep, unsupported_flags,
569                     args->flags);
570                 LIN_SDT_PROBE1(time, linux_clock_nanosleep, return, error);
571                 return (error);
572         }
573
574         error = linux_to_native_clockid(&clockid, args->which);
575         if (error != 0) {
576                 LIN_SDT_PROBE1(time, linux_clock_nanosleep, unsupported_clockid,
577                     args->which);
578                 LIN_SDT_PROBE1(time, linux_clock_settime, return, error);
579                 return (error);
580         }
581
582         error = copyin(args->rqtp, &lrqts, sizeof(lrqts));
583         if (error != 0) {
584                 LIN_SDT_PROBE1(time, linux_clock_nanosleep, copyin_error,
585                     error);
586                 LIN_SDT_PROBE1(time, linux_clock_nanosleep, return, error);
587                 return (error);
588         }
589
590         if (args->rmtp != NULL)
591                 rmtp = &rmts;
592         else
593                 rmtp = NULL;
594
595         error = linux_to_native_timespec(&rqts, &lrqts);
596         if (error != 0) {
597                 LIN_SDT_PROBE1(time, linux_clock_nanosleep, conversion_error,
598                     error);
599                 LIN_SDT_PROBE1(time, linux_clock_nanosleep, return, error);
600                 return (error);
601         }
602         error = kern_clock_nanosleep(td, clockid, flags, &rqts, rmtp);
603         if (error == EINTR && (flags & TIMER_ABSTIME) == 0 &&
604             args->rmtp != NULL) {
605                 error2 = native_to_linux_timespec(&lrmts, rmtp);
606                 if (error2 != 0)
607                         return (error2);
608                 error2 = copyout(&lrmts, args->rmtp, sizeof(lrmts));
609                 if (error2 != 0) {
610                         LIN_SDT_PROBE1(time, linux_clock_nanosleep,
611                             copyout_error, error2);
612                         LIN_SDT_PROBE1(time, linux_clock_nanosleep,
613                             return, error2);
614                         return (error2);
615                 }
616         }
617
618         LIN_SDT_PROBE1(time, linux_clock_nanosleep, return, error);
619         return (error);
620 }