librt/aio_cancel(): Set errno to EBADF if the fd is not valid.
[dragonfly.git] / lib / librt / aio.c
CommitLineData
ea3ab097
VS
1/*-
2 * Copyright (c) 2011 Venkatesh Srinivas <vsrinivas@dragonflybsd.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 */
15
16/*
17 * This file contains support for the POSIX 1003.1B AIO/LIO facility.
18 *
19 * This version of AIO is aimed at standards compliance; it is not aimed
20 * at either reasonability or performance. It merely wraps synchronous I/O
21 * routines.
22 *
23 * This version cannot perform asynchronous notification of I/O completion
84c33861 24 * on DragonFly via SIGEV_SIGNAL.
ea3ab097
VS
25 *
26 * 2) SIGEV_SIGNAL code is present, but if-ed out under 'notyet'; Dfly
27 * does not support sigqueue(), so we cannot control the payload to
28 * a SIGINFO-signal from userspace. Programs using AIO signals use
29 * the payload field to carry pointers to the completed AIO structure,
30 * which is not yet possible here.
31 *
32 * It would be possible for this version to support SIGEV_KEVENT.
33 */
34
35#include <stdlib.h>
36#include <sys/types.h>
37#include <sys/time.h>
38#include <sys/signal.h>
39#include <sys/queue.h>
789d6d70 40#include <sys/stat.h>
ea3ab097
VS
41#include <unistd.h>
42#include <errno.h>
43#include <sys/aio.h>
84c33861
VS
44#include <pthread.h>
45
46static void *_aio_thr_start(void *);
ea3ab097
VS
47
48static void
84c33861 49_aio_notify(struct sigevent *sigevp)
ea3ab097 50{
dacb3008 51#if 0 /* not yet */
ea3ab097
VS
52 int sig;
53 union sigval sv;
54 pid_t pid;
dacb3008 55#endif
84c33861 56 pthread_t thr;
ea3ab097 57
84c33861
VS
58 switch (sigevp->sigev_notify) {
59 case SIGEV_NONE:
ea3ab097
VS
60 return;
61
84c33861
VS
62 case SIGEV_THREAD:
63 pthread_create(&thr,
64 sigevp->sigev_notify_attributes,
65 _aio_thr_start,
66 sigevp);
67 break;
ea3ab097 68
84c33861 69 case SIGEV_SIGNAL:
dacb3008 70#if 0 /* not yet */
84c33861
VS
71 pid = getpid();
72 sig = sigevp->sigev_signo;
73 sv = sigevp->sigev_value;
74 sigqueue(pid, sig, sv);
75#endif
76 break;
ea3ab097 77
84c33861 78 case SIGEV_KEVENT:
dacb3008 79 /* not yet */
84c33861
VS
80 break;
81 }
82}
83
84static void *
85_aio_thr_start(void *vsigevp)
86{
87 struct sigevent *sigevp = vsigevp;
88 sigevp->sigev_notify_function(sigevp->sigev_value);
89 return (NULL);
ea3ab097
VS
90}
91
92/*
93 * aio_read()
94 *
95 * Asynchronously read from a file
96 */
97int
98aio_read(struct aiocb *ap)
99{
100#ifndef notyet
84c33861
VS
101 if ((ap->aio_sigevent.sigev_notify != SIGEV_NONE) &&
102 (ap->aio_sigevent.sigev_notify != SIGEV_THREAD))
ea3ab097
VS
103 return (ENOSYS);
104#endif
105
106 ap->_aio_val = pread(ap->aio_fildes,
107 (void *) ap->aio_buf,
108 ap->aio_nbytes,
109 ap->aio_offset);
110 ap->_aio_err = errno;
111
84c33861 112 _aio_notify(&ap->aio_sigevent);
ea3ab097
VS
113
114 return (0);
115}
116
117int
118aio_write(struct aiocb *ap)
119{
120#ifndef notyet
84c33861
VS
121 if ((ap->aio_sigevent.sigev_notify != SIGEV_NONE) &&
122 (ap->aio_sigevent.sigev_notify != SIGEV_THREAD))
ea3ab097
VS
123 return (ENOSYS);
124#endif
125
126 ap->_aio_val = pwrite(ap->aio_fildes,
127 (void *) ap->aio_buf,
128 ap->aio_nbytes,
129 ap->aio_offset);
130 ap->_aio_err = errno;
131
84c33861 132 _aio_notify(&ap->aio_sigevent);
ea3ab097
VS
133
134 return (0);
135}
136
137int
138aio_fsync(int op, struct aiocb *ap)
139{
140#ifndef notyet
84c33861
VS
141 if ((ap->aio_sigevent.sigev_notify != SIGEV_NONE) &&
142 (ap->aio_sigevent.sigev_notify != SIGEV_THREAD))
ea3ab097
VS
143 return (ENOSYS);
144#endif
145
146 ap->_aio_val = fsync(ap->aio_fildes);
147 ap->_aio_err = errno;
148
84c33861 149 _aio_notify(&ap->aio_sigevent);
ea3ab097
VS
150
151 return(0);
152}
153
154int
155lio_listio(int mode, struct aiocb *const apv[], int nent,
156 struct sigevent *sigevp)
157{
158 int i;
159
160#ifndef notyet
019e715a
VS
161 if (sigevp &&
162 (sigevp->sigev_notify != SIGEV_NONE) &&
84c33861 163 (sigevp->sigev_notify != SIGEV_THREAD))
ea3ab097
VS
164 return (ENOSYS);
165#endif
166
167 for (i = 0; i < nent; i++)
168 switch (apv[i]->aio_lio_opcode) {
169 case LIO_READ:
170 aio_read(apv[i]);
171 break;
172 case LIO_WRITE:
173 aio_write(apv[i]);
174 break;
175 case LIO_NOP:
176 break;
177 }
178
179 if (sigevp &&
84c33861 180 (mode == LIO_NOWAIT)
ea3ab097 181 ) {
84c33861 182 _aio_notify(sigevp);
ea3ab097
VS
183 }
184
185 return (0);
186}
187
188/*
189 * aio_error()
190 *
191 * Get I/O completion status
192 *
193 * Returns EINPROGRESS until I/O is complete. Returns ECANCELED if
194 * I/O is canceled. Returns I/O status if operation completed.
195 *
196 * This routine does not block.
197 */
198int
199aio_error(const struct aiocb *ap)
200{
201 return (ap->_aio_err);
202}
203
204/*
205 * aio_return()
206 *
207 * Finish up I/O, releasing I/O resources and returns the value
208 * that would have been associated with a synchronous request.
209 */
210ssize_t
211aio_return(struct aiocb *ap)
212{
213 return (ap->_aio_val);
214}
215
216int
217aio_cancel(int fildes, struct aiocb *aiocbp)
218{
789d6d70
SW
219 struct stat sb;
220
221 /* must be a valid file descriptor */
222 if (fstat(fildes, &sb)) {
223 errno = EBADF;
224 return -1;
225 }
ea3ab097
VS
226 return (AIO_ALLDONE);
227}
228
229int
230aio_suspend(const struct aiocb *const list[], int nent, const struct timespec *timo)
231{
232 return (0);
233}
234