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 */
56 #include <sys/syscall.h>
57 #include <sys/types.h>
59 #include <sys/fcntl.h>
60 #include <sys/syscall.h>
61 #include <sys/socket.h>
63 #include <linux/net.h>
66 #include <sys/queue.h>
74 #include "dev.h" /* _sysio_nodev_ops */
77 * Sockets interface driver
81 * Sockets file identifiers format.
83 struct sockets_ino_identifier {
84 ino_t inum; /* i-number */
88 * Driver-private i-node information we keep about in-use sockets.
91 struct sockets_ino_identifier ski_ident; /* unique identifier */
92 struct file_identifier ski_fileid; /* ditto */
93 int ski_fd; /* host fildes */
96 static int sockets_inop_close(struct inode *ino);
97 static int sockets_inop_read(struct inode *ino,
99 static int sockets_inop_write(struct inode *ino,
100 struct ioctx *ioctxp);
101 static _SYSIO_OFF_T sockets_inop_pos(struct inode *ino,
103 static int sockets_inop_iodone(struct ioctx *ioctx);
104 static int sockets_inop_sync(struct inode *ino);
105 static int sockets_inop_datasync(struct inode *ino);
106 static int sockets_inop_fcntl(struct inode *ino, int cmd, va_list ap, int *rtn);
107 static int sockets_inop_ioctl(struct inode *ino,
108 unsigned long int request,
110 static void sockets_inop_gone(struct inode *ino);
111 static void sockets_illop(void);
114 * Given i-node, return driver private part.
116 #define I2SKI(ino) ((struct socket_info *)((ino)->i_private))
118 struct filesys_ops sockets_filesys_ops = {
119 (void (*)(struct filesys *))sockets_illop
122 static struct filesys *sockets_fs = NULL;
124 static struct inode_ops sockets_i_ops;
127 * Initialize this driver.
130 _sysio_sockets_init()
135 sockets_i_ops = _sysio_nodev_ops;
136 sockets_i_ops.inop_close = sockets_inop_close;
137 sockets_i_ops.inop_read = sockets_inop_read;
138 sockets_i_ops.inop_write = sockets_inop_write;
139 sockets_i_ops.inop_pos = sockets_inop_pos;
140 sockets_i_ops.inop_iodone = sockets_inop_iodone;
141 sockets_i_ops.inop_fcntl = sockets_inop_fcntl;
142 sockets_i_ops.inop_sync = sockets_inop_sync;
143 sockets_i_ops.inop_datasync = sockets_inop_datasync;
144 sockets_i_ops.inop_ioctl = sockets_inop_ioctl;
145 sockets_i_ops.inop_gone = sockets_inop_gone;
147 sockets_fs = _sysio_fs_new(&sockets_filesys_ops, 0, NULL);
155 sockets_inop_close(struct inode *ino)
157 struct socket_info *ski = I2SKI(ino);
163 err = syscall(SYSIO_SYS_close, ski->ski_fd);
171 * A helper function performing the real IO operation work.
173 * We don't really have async IO. We'll just perform the function
177 doio(ssize_t (*f)(int, const struct iovec *, int),
181 struct socket_info *ski = I2SKI(ino);
183 assert(ski->ski_fd >= 0);
185 /* XXX there's no way to check the position
186 * here we only could ingore the extends
188 if (ioctx->ioctx_xtvlen != 1)
191 if (ioctx->ioctx_iovlen && (int) ioctx->ioctx_iovlen < 0)
195 * Call the appropriate (read/write) IO function to
196 * transfer the data now.
199 (*f)(ski->ski_fd, ioctx->ioctx_iov, ioctx->ioctx_iovlen);
200 if (ioctx->ioctx_cc < 0)
201 ioctx->ioctx_errno = errno;
203 ioctx->ioctx_done = 1;
208 * Helper function passed to doio(), above, to accomplish a real readv.
211 _readv(int fd, const struct iovec *vector, int count)
214 return syscall(SYSIO_SYS_readv, fd, vector, count);
218 sockets_inop_read(struct inode *ino,
222 return doio(_readv, ino, ioctx);
226 * Helper function passed to doio(), above, to accomplish a real writev.
229 _writev(int fd, const struct iovec *vector, int count)
232 return syscall(SYSIO_SYS_writev, fd, vector, count);
236 sockets_inop_write(struct inode *ino,
240 return doio(_writev, ino, ioctx);
244 sockets_inop_pos(struct inode *ino __IS_UNUSED, _SYSIO_OFF_T off __IS_UNUSED)
250 sockets_inop_iodone(struct ioctx *ioctxp __IS_UNUSED)
254 * It's always done in this driver. It completed when posted.
260 sockets_inop_fcntl(struct inode *ino __IS_UNUSED,
262 va_list ap __IS_UNUSED,
267 assert(I2SKI(ino)->ski_fd >= 0);
273 *rtn = syscall(SYSIO_SYS_fcntl, I2SKI(ino)->ski_fd, cmd);
282 arg = va_arg(ap, long);
283 *rtn = syscall(SYSIO_SYS_fcntl, I2SKI(ino)->ski_fd, cmd, arg);
289 return *rtn == -1 ? -errno : 0;
293 sockets_inop_sync(struct inode *ino)
296 assert(I2SKI(ino)->ski_fd >= 0);
298 return syscall(SYSIO_SYS_fsync, I2SKI(ino)->ski_fd);
302 sockets_inop_datasync(struct inode *ino)
305 assert(I2SKI(ino)->ski_fd >= 0);
307 return syscall(SYSIO_SYS_fdatasync, I2SKI(ino)->ski_fd);
310 #ifdef HAVE_LUSTRE_HACK
312 * we blindly extract 4 params and pass to host kernel, the stack
313 * should be ok. hope no ioctl will consume more then 4 params...
316 sockets_inop_ioctl(struct inode *ino,
317 unsigned long int request,
320 long arg1, arg2, arg3, arg4;
322 assert(I2SKI(ino)->ski_fd >= 0);
324 arg1 = va_arg(ap, long);
325 arg2 = va_arg(ap, long);
326 arg3 = va_arg(ap, long);
327 arg4 = va_arg(ap, long);
329 return syscall(SYSIO_SYS_ioctl, I2SKI(ino)->ski_fd, request,
330 arg1, arg2, arg3, arg4);
334 sockets_inop_ioctl(struct inode *ino __IS_UNUSED,
335 unsigned long int request __IS_UNUSED,
336 va_list ap __IS_UNUSED)
339 * I'm lazy. Maybe implemented later.
346 sockets_inop_gone(struct inode *ino)
349 (void )sockets_inop_close(ino);
350 free(ino->i_private);
360 static struct inode *
361 _sysio_sockets_inew()
363 static ino_t inum = 1;
364 struct socket_info *ski;
366 static struct intnl_stat zero_stat;
368 ski = malloc(sizeof(struct socket_info));
371 ski->ski_ident.inum = inum++;
372 ski->ski_fileid.fid_data = &ski->ski_ident;
373 ski->ski_fileid.fid_len = sizeof(ski->ski_ident);
377 _sysio_i_new(sockets_fs,
390 SYSIO_INTERFACE_NAME(socket)(int domain, int type, int protocol)
394 struct socket_info *ski;
400 ino = _sysio_sockets_inew();
407 #ifndef SYSIO_SYS_socketcall
408 ski->ski_fd = syscall(SYSIO_SYS_socket, domain, type, protocol);
411 unsigned long avec[3] = {domain, type, protocol};
413 syscall(SYSIO_SYS_socketcall, SYS_SOCKET, avec);
416 if (ski->ski_fd < 0) {
421 fil = _sysio_fnew(ino, O_RDWR);
427 #ifdef HAVE_LUSTRE_HACK
428 err = _sysio_fd_set(fil, ski->ski_fd, 1);
430 err = _sysio_fd_set(fil, -1, 0);
448 SYSIO_INTERFACE_NAME(accept)(int s, struct sockaddr *addr, socklen_t *addrlen)
452 struct socket_info *ski;
453 struct file *ofil, *nfil;
459 ofil = _sysio_fd_find(s);
465 ino = _sysio_sockets_inew();
471 nfil = _sysio_fnew(ino, O_RDWR);
478 #ifndef SYSIO_SYS_socketcall
480 syscall(SYSIO_SYS_accept,
481 I2SKI(ofil->f_ino)->ski_fd,
486 unsigned long avec[3] = {
487 (unsigned long) I2SKI(ofil->f_ino)->ski_fd,
488 (unsigned long) addr,
489 (unsigned long) addrlen};
491 syscall(SYSIO_SYS_socketcall, SYS_ACCEPT, avec);
494 if (ski->ski_fd < 0) {
499 #ifdef HAVE_LUSTRE_HACK
500 err = _sysio_fd_set(nfil, ski->ski_fd, 1);
502 err = _sysio_fd_set(nfil, -1, 0);
520 SYSIO_INTERFACE_NAME(bind)(int sockfd,
521 const struct sockaddr *my_addr,
526 #ifdef SYSIO_SYS_socketcall
527 unsigned long avec[3];
532 fil = _sysio_fd_find(sockfd);
538 #ifndef SYSIO_SYS_socketcall
539 if (syscall(SYSIO_SYS_bind,
540 I2SKI(fil->f_ino)->ski_fd,
544 avec[0] = I2SKI(fil->f_ino)->ski_fd;
545 avec[1] = (unsigned long )my_addr;
547 if (syscall(SYSIO_SYS_socketcall, SYS_BIND, avec) != 0) {
560 SYSIO_INTERFACE_NAME(listen)(int s, int backlog)
564 #ifdef SYSIO_SYS_socketcall
565 unsigned long avec[2];
570 fil = _sysio_fd_find(s);
576 #ifndef SYSIO_SYS_socketcall
577 if (syscall(SYSIO_SYS_listen,
578 I2SKI(fil->f_ino)->ski_fd,
581 avec[0] = I2SKI(fil->f_ino)->ski_fd;
583 if (syscall(SYSIO_SYS_socketcall, SYS_LISTEN, avec) != 0) {
596 SYSIO_INTERFACE_NAME(connect)(int sockfd,
597 const struct sockaddr *serv_addr,
602 #ifdef SYSIO_SYS_socketcall
603 unsigned long avec[3];
608 fil = _sysio_fd_find(sockfd);
614 #ifndef SYSIO_SYS_socketcall
615 if (syscall(SYSIO_SYS_connect,
616 I2SKI(fil->f_ino)->ski_fd,
620 avec[0] = I2SKI(fil->f_ino)->ski_fd;
621 avec[1] = (unsigned long )serv_addr;
623 if (syscall(SYSIO_SYS_socketcall, SYS_CONNECT, avec) != 0) {