2 * This Cplant(TM) source code is the property of Sandia National
5 * This Cplant(TM) source code is copyrighted by Sandia National
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)
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
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.
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.
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
34 * Questions or comments about this library should be sent to:
37 * Sandia National Laboratories, New Mexico
39 * Albuquerque, NM 87185-1110
48 #include <stdio.h> /* for NULL */
57 #include <sys/types.h>
59 #include <sys/fcntl.h>
60 #include <sys/syscall.h>
61 #include <sys/socket.h>
62 #include <linux/net.h>
64 #include <sys/queue.h>
71 #include "dev.h" /* _sysio_nodev_ops */
74 * Sockets interface driver
78 * Sockets file identifiers format.
80 struct sockets_ino_identifier {
81 ino_t inum; /* i-number */
85 * Driver-private i-node information we keep about in-use sockets.
88 struct sockets_ino_identifier ski_ident; /* unique identifier */
89 struct file_identifier ski_fileid; /* ditto */
90 int ski_fd; /* host fildes */
93 static int sockets_inop_close(struct inode *ino);
94 static int sockets_inop_read(struct inode *ino,
96 static int sockets_inop_write(struct inode *ino,
97 struct ioctx *ioctxp);
98 static _SYSIO_OFF_T sockets_inop_pos(struct inode *ino,
100 static int sockets_inop_iodone(struct ioctx *ioctx);
101 static int sockets_inop_sync(struct inode *ino);
102 static int sockets_inop_datasync(struct inode *ino);
103 static int sockets_inop_fcntl(struct inode *ino, int cmd, va_list ap, int *rtn);
104 static int sockets_inop_ioctl(struct inode *ino,
105 unsigned long int request,
107 static void sockets_inop_gone(struct inode *ino);
108 static void sockets_illop(void);
111 * Given i-node, return driver private part.
113 #define I2SKI(ino) ((struct socket_info *)((ino)->i_private))
115 struct filesys_ops sockets_filesys_ops = {
116 (void (*)(struct filesys *))sockets_illop
119 static struct filesys *sockets_fs;
121 static struct inode_ops sockets_i_ops;
124 * Initialize this driver.
127 _sysio_sockets_init()
130 sockets_i_ops = _sysio_nodev_ops;
131 sockets_i_ops.inop_close = sockets_inop_close;
132 sockets_i_ops.inop_read = sockets_inop_read;
133 sockets_i_ops.inop_write = sockets_inop_write;
134 sockets_i_ops.inop_pos = sockets_inop_pos;
135 sockets_i_ops.inop_iodone = sockets_inop_iodone;
136 sockets_i_ops.inop_fcntl = sockets_inop_fcntl;
137 sockets_i_ops.inop_sync = sockets_inop_sync;
138 sockets_i_ops.inop_datasync = sockets_inop_datasync;
139 sockets_i_ops.inop_ioctl = sockets_inop_ioctl;
140 sockets_i_ops.inop_gone = sockets_inop_gone;
142 sockets_fs = _sysio_fs_new(&sockets_filesys_ops, 0, NULL);
150 sockets_inop_close(struct inode *ino)
152 struct socket_info *ski = I2SKI(ino);
158 err = syscall(SYS_close, ski->ski_fd);
166 * A helper function performing the real IO operation work.
168 * We don't really have async IO. We'll just perform the function
172 doio(ssize_t (*f)(int, const struct iovec *, int),
176 struct socket_info *ski = I2SKI(ino);
178 assert(ski->ski_fd >= 0);
180 /* XXX there's no way to check the position
181 * here we only could ingore the extends
183 if (ioctx->ioctx_xtvlen != 1)
186 if (ioctx->ioctx_iovlen && (int) ioctx->ioctx_iovlen < 0)
190 * Call the appropriate (read/write) IO function to
191 * transfer the data now.
194 (*f)(ski->ski_fd, ioctx->ioctx_iov, ioctx->ioctx_iovlen);
195 if (ioctx->ioctx_cc < 0)
196 ioctx->ioctx_errno = errno;
198 ioctx->ioctx_done = 1;
203 * Helper function passed to doio(), above, to accomplish a real readv.
206 _readv(int fd, const struct iovec *vector, int count)
209 return syscall(SYS_readv, fd, vector, count);
213 sockets_inop_read(struct inode *ino,
217 return doio(_readv, ino, ioctx);
221 * Helper function passed to doio(), above, to accomplish a real writev.
224 _writev(int fd, const struct iovec *vector, int count)
227 return syscall(SYS_writev, fd, vector, count);
231 sockets_inop_write(struct inode *ino,
235 return doio(_writev, ino, ioctx);
239 sockets_inop_pos(struct inode *ino __IS_UNUSED, _SYSIO_OFF_T off __IS_UNUSED)
245 sockets_inop_iodone(struct ioctx *ioctxp __IS_UNUSED)
249 * It's always done in this driver. It completed when posted.
255 sockets_inop_fcntl(struct inode *ino __IS_UNUSED,
257 va_list ap __IS_UNUSED,
262 assert(I2SKI(ino)->ski_fd >= 0);
268 *rtn = syscall(SYS_fcntl, I2SKI(ino)->ski_fd, cmd);
277 arg = va_arg(ap, long);
278 *rtn = syscall(SYS_fcntl, I2SKI(ino)->ski_fd, cmd, arg);
284 return *rtn == -1 ? -errno : 0;
288 sockets_inop_sync(struct inode *ino)
291 assert(I2SKI(ino)->ski_fd >= 0);
293 return syscall(SYS_fsync, I2SKI(ino)->ski_fd);
297 sockets_inop_datasync(struct inode *ino)
300 assert(I2SKI(ino)->ski_fd >= 0);
302 return syscall(SYS_fdatasync, I2SKI(ino)->ski_fd);
305 #ifdef HAVE_LUSTRE_HACK
307 * we blindly extract 4 params and pass to host kernel, the stack
308 * should be ok. hope no ioctl will consume more then 4 params...
311 sockets_inop_ioctl(struct inode *ino,
312 unsigned long int request,
315 long arg1, arg2, arg3, arg4;
317 assert(I2SKI(ino)->ski_fd >= 0);
319 arg1 = va_arg(ap, long);
320 arg2 = va_arg(ap, long);
321 arg3 = va_arg(ap, long);
322 arg4 = va_arg(ap, long);
324 return syscall(SYS_ioctl, I2SKI(ino)->ski_fd, request,
325 arg1, arg2, arg3, arg4);
329 sockets_inop_ioctl(struct inode *ino __IS_UNUSED,
330 unsigned long int request __IS_UNUSED,
331 va_list ap __IS_UNUSED)
334 * I'm lazy. Maybe implemented later.
341 sockets_inop_gone(struct inode *ino)
344 (void )sockets_inop_close(ino);
345 free(ino->i_private);
355 static struct inode *
356 _sysio_sockets_inew()
358 static ino_t inum = 1;
359 struct socket_info *ski;
362 ski = malloc(sizeof(struct socket_info));
365 ski->ski_ident.inum = inum++;
366 ski->ski_fileid.fid_data = &ski->ski_ident;
367 ski->ski_fileid.fid_len = sizeof(ski->ski_ident);
371 _sysio_i_new(sockets_fs,
385 socket(int domain, int type, int protocol)
389 struct socket_info *ski;
395 ino = _sysio_sockets_inew();
402 #ifndef SYS_socketcall
403 ski->ski_fd = syscall(SYS_socket, domain, type, protocol);
406 unsigned long avec[3] = {domain, type, protocol};
407 ski->ski_fd = syscall(SYS_socketcall, SYS_SOCKET, avec);
410 if (ski->ski_fd < 0) {
415 fil = _sysio_fnew(ino, O_RDWR);
421 #ifdef HAVE_LUSTRE_HACK
422 err = _sysio_fd_set(fil, ski->ski_fd, 1);
424 err = _sysio_fd_set(fil, -1, 0);
442 accept(int s, struct sockaddr *addr, socklen_t *addrlen)
446 struct socket_info *ski;
447 struct file *ofil, *nfil;
453 ofil = _sysio_fd_find(s);
459 ino = _sysio_sockets_inew();
465 nfil = _sysio_fnew(ino, O_RDWR);
472 #ifndef SYS_socketcall
473 ski->ski_fd = syscall(SYS_accept, I2SKI(ofil->f_ino)->ski_fd,
477 unsigned long avec[3] = {
478 (unsigned long) I2SKI(ofil->f_ino)->ski_fd,
479 (unsigned long) addr,
480 (unsigned long) addrlen};
481 ski->ski_fd = syscall(SYS_socketcall, SYS_ACCEPT, avec);
484 if (ski->ski_fd < 0) {
489 #ifdef HAVE_LUSTRE_HACK
490 err = _sysio_fd_set(nfil, ski->ski_fd, 1);
492 err = _sysio_fd_set(nfil, -1, 0);
510 bind(int sockfd, const struct sockaddr *my_addr, socklen_t addrlen)
514 unsigned long avec[3];
518 fil = _sysio_fd_find(sockfd);
524 #ifndef SYS_socketcall
525 if (syscall(SYS_bind, I2SKI(fil->f_ino)->ski_fd, my_addr, addrlen)) {
527 avec[0] = I2SKI(fil->f_ino)->ski_fd;
528 avec[1] = (unsigned long )my_addr;
530 if (syscall(SYS_socketcall, SYS_BIND, avec) != 0) {
543 listen(int s, int backlog)
547 unsigned long avec[2];
551 fil = _sysio_fd_find(s);
557 #ifndef SYS_socketcall
558 if (syscall(SYS_listen, I2SKI(fil->f_ino)->ski_fd, backlog) != 0) {
560 avec[0] = I2SKI(fil->f_ino)->ski_fd;
562 if (syscall(SYS_socketcall, SYS_LISTEN, avec) != 0) {
575 connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen)
579 unsigned long avec[3];
583 fil = _sysio_fd_find(sockfd);
589 #ifndef SYS_socketcall
590 if (syscall(SYS_connect, I2SKI(fil->f_ino)->ski_fd,
591 serv_addr, addrlen) != 0) {
593 avec[0] = I2SKI(fil->f_ino)->ski_fd;
594 avec[1] = (unsigned long )serv_addr;
596 if (syscall(SYS_socketcall, SYS_CONNECT, avec) != 0) {