Whamcloud - gitweb
Land b_release_1_4_6 onto HEAD (20060223_1455)
[fs/lustre-release.git] / libsysio / dev / stdfd / stdfd.c
1 /*
2  *    This Cplant(TM) source code is the property of Sandia National
3  *    Laboratories.
4  *
5  *    This Cplant(TM) source code is copyrighted by Sandia National
6  *    Laboratories.
7  *
8  *    The redistribution of this Cplant(TM) source code is subject to the
9  *    terms of the GNU Lesser General Public License
10  *    (see cit/LGPL or http://www.gnu.org/licenses/lgpl.html)
11  *
12  *    Cplant(TM) Copyright 1998-2003 Sandia Corporation. 
13  *    Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
14  *    license for use of this work by or on behalf of the US Government.
15  *    Export of this program may require a license from the United States
16  *    Government.
17  */
18
19 /*
20  * This library is free software; you can redistribute it and/or
21  * modify it under the terms of the GNU Lesser General Public
22  * License as published by the Free Software Foundation; either
23  * version 2.1 of the License, or (at your option) any later version.
24  * 
25  * This library is distributed in the hope that it will be useful,
26  * but WITHOUT ANY WARRANTY; without even the implied warranty of
27  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28  * Lesser General Public License for more details.
29  * 
30  * You should have received a copy of the GNU Lesser General Public
31  * License along with this library; if not, write to the Free Software
32  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
33  *
34  * Questions or comments about this library should be sent to:
35  *
36  * Lee Ward
37  * Sandia National Laboratories, New Mexico
38  * P.O. Box 5800
39  * Albuquerque, NM 87185-1110
40  *
41  * lee@sandia.gov
42  */
43
44 #ifdef __linux__
45 #define _BSD_SOURCE
46 #endif
47
48 #include <errno.h>
49 #include <stdarg.h>
50 #include <sys/syscall.h>
51 #include <unistd.h>
52 #include <fcntl.h>
53 #include <sys/types.h>
54 #include <sys/stat.h>
55 #include <sys/queue.h>
56
57 #include "sysio.h"
58 #include "xtio.h"
59 #include "native.h"
60 #include "inode.h"
61 #include "dev.h"
62
63 #include "stdfd.h"
64
65 #ifdef CPLANT_YOD
66 #include <sys/statfs.h>
67 #include "cplant-yod.h"
68 #define dowrite(f, b, n) write_yod(f, b, n)
69 #define doread(f, b, n) read_yod(f, b, n)
70 #else
71 #define dowrite(f, b, n) syscall(SYSIO_SYS_write, f, b, n)
72 #define doread(f, b, n) syscall(SYSIO_SYS_read, f, b, n)
73 #endif
74
75 /*
76  * Pre-opened standard file descriptors driver.
77  */
78
79 static int stdfd_open(struct pnode *pno, int flags, mode_t mode);
80 static int stdfd_close(struct inode *ino);
81 static int stdfd_read(struct inode *ino, struct ioctx *ioctx);
82 static int stdfd_write(struct inode *ino, struct ioctx *ioctx);
83 static int stdfd_iodone(struct ioctx *ioctx);
84 static int stdfd_datasync(struct inode *ino);
85 static int stdfd_fcntl(struct inode *ino, int cmd, va_list ap, int *rtn);
86 static int stdfd_ioctl(struct inode *ino,
87                        unsigned long int request,
88                        va_list ap);
89
90 int
91 _sysio_stdfd_init()
92 {
93         struct inode_ops stdfd_operations;
94
95         stdfd_operations = _sysio_nodev_ops;
96         stdfd_operations.inop_open = stdfd_open;
97         stdfd_operations.inop_close = stdfd_close;
98         stdfd_operations.inop_read = stdfd_read;
99         stdfd_operations.inop_write = stdfd_write;
100         stdfd_operations.inop_iodone = stdfd_iodone;
101         stdfd_operations.inop_fcntl = stdfd_fcntl;
102         stdfd_operations.inop_datasync = stdfd_datasync;
103         stdfd_operations.inop_ioctl = stdfd_ioctl;
104
105         return _sysio_char_dev_register(SYSIO_C_STDFD_MAJOR,
106                                         "stdfd",
107                                         &stdfd_operations);
108 }
109
110 static int
111 stdfd_open(struct pnode *pno __IS_UNUSED,
112            int flags __IS_UNUSED,
113            mode_t mode __IS_UNUSED)
114 {
115
116         return 0;
117 }
118
119 static int
120 stdfd_close(struct inode *ino __IS_UNUSED)
121 {
122
123         return 0;
124 }
125
126 static int
127 doio(ssize_t (*f)(void *, size_t, _SYSIO_OFF_T, struct inode *),
128      struct inode *ino,
129      struct ioctx *ioctx)
130 {
131
132         if (ioctx->ioctx_xtvlen != 1) {
133                 /*
134                  * No scatter/gather to "file" address space (we're not
135                  * seekable) and "nowhere" makes no sense.
136                  */
137                 return -EINVAL;
138         }
139         ioctx->ioctx_cc =
140             _sysio_doio(ioctx->ioctx_xtv, ioctx->ioctx_xtvlen,
141                         ioctx->ioctx_iov, ioctx->ioctx_iovlen,
142                         (ssize_t (*)(void *, size_t, _SYSIO_OFF_T, void *))f,
143                         ino);
144         if (ioctx->ioctx_cc < 0) {
145                 ioctx->ioctx_errno = -ioctx->ioctx_cc;
146                 ioctx->ioctx_cc = -1;
147         }
148         return 0;
149 }
150
151 static ssize_t
152 stdfd_read_simple(void *buf,
153                   size_t nbytes,
154                   _SYSIO_OFF_T off __IS_UNUSED,
155                   struct inode *ino)
156 {
157         int     fd = SYSIO_MINOR_DEV(ino->i_stbuf.st_rdev);
158         int     cc;
159
160         cc = doread(fd, buf, nbytes);
161         if (cc < 0)
162                 cc = -errno;
163         return cc;
164 }
165
166 static int
167 stdfd_read(struct inode *ino, struct ioctx *ioctx)
168 {
169
170         return doio(stdfd_read_simple, ino, ioctx);
171 }
172
173 static ssize_t
174 stdfd_write_simple(const void *buf,
175                    size_t nbytes,
176                    _SYSIO_OFF_T off __IS_UNUSED,
177                    struct inode *ino)
178 {
179         int     fd = SYSIO_MINOR_DEV(ino->i_stbuf.st_rdev);
180         int     cc;
181
182         cc = dowrite(fd, buf, nbytes);
183         if (cc < 0)
184                 cc = -errno;
185         return cc;
186 }
187
188 static int
189 stdfd_write(struct inode *ino, struct ioctx *ioctx)
190 {
191
192         return doio((ssize_t (*)(void *,
193                                  size_t,
194                                  _SYSIO_OFF_T,
195                                  struct inode *))stdfd_write_simple,
196                     ino,
197                     ioctx);
198 }
199
200 static int
201 stdfd_iodone(struct ioctx *iocp __IS_UNUSED)
202 {
203
204         /*
205          * It's always done in this driver. It completed when posted.
206          */
207         return 1;
208 }
209
210 static int
211 stdfd_fcntl(struct inode *ino,
212             int cmd,
213             va_list ap,
214             int *rtn)
215 {
216         int     err;
217         int     fd = SYSIO_MINOR_DEV(ino->i_stbuf.st_rdev);
218         long    arg;
219
220         err = 0;
221         switch (cmd) {
222         case F_GETFL:
223                 *rtn = syscall(SYS_fcntl, fd, cmd);
224                 if (*rtn == -1)
225                         err = -errno;
226                 break;
227         case F_SETFL:
228                 arg = va_arg(ap, long);
229                 *rtn = syscall(SYS_fcntl, fd, cmd, arg);
230                 if (*rtn == -1)
231                         err = -errno;
232                 va_end(ap);
233                 break;
234         default:
235                 *rtn = -1;
236                 err = -EINVAL;
237         }
238         return err;
239 }
240
241 static int
242 stdfd_datasync(struct inode *ino __IS_UNUSED)
243 {
244
245         /*
246          * We don't buffer, so nothing to do.
247          */
248         return 0;
249 }
250
251 static int
252 stdfd_ioctl(struct inode *ino __IS_UNUSED,
253             unsigned long int request __IS_UNUSED,
254             va_list ap __IS_UNUSED)
255 {
256
257         return -ENOTTY;
258 }