/* * Copyright (c) 2006, 2019 Oracle and/or its affiliates. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU * General Public License (GPL) Version 2, available from the file * COPYING in the main directory of this source tree, or the * OpenIB.org BSD license below: * * Redistribution and use in source and binary forms, with or * without modification, are permitted provided that the following * conditions are met: * * - Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. * * - Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * */ #include <linux/module.h> #include <linux/errno.h> #include <linux/kernel.h> #include <linux/gfp.h> #include <linux/in.h> #include <linux/ipv6.h> #include <linux/poll.h> #include <net/sock.h> #include "rds.h" /* this is just used for stats gathering :/ */ static DEFINE_SPINLOCK(rds_sock_lock); static unsigned long rds_sock_count; static LIST_HEAD(rds_sock_list); DECLARE_WAIT_QUEUE_HEAD(…); /* * This is called as the final descriptor referencing this socket is closed. * We have to unbind the socket so that another socket can be bound to the * address it was using. * * We have to be careful about racing with the incoming path. sock_orphan() * sets SOCK_DEAD and we use that as an indicator to the rx path that new * messages shouldn't be queued. */ static int rds_release(struct socket *sock) { … } /* * Careful not to race with rds_release -> sock_orphan which clears sk_sleep. * _bh() isn't OK here, we're called from interrupt handlers. It's probably OK * to wake the waitqueue after sk_sleep is clear as we hold a sock ref, but * this seems more conservative. * NB - normally, one would use sk_callback_lock for this, but we can * get here from interrupts, whereas the network code grabs sk_callback_lock * with _lock_bh only - so relying on sk_callback_lock introduces livelocks. */ void rds_wake_sk_sleep(struct rds_sock *rs) { … } static int rds_getname(struct socket *sock, struct sockaddr *uaddr, int peer) { … } /* * RDS' poll is without a doubt the least intuitive part of the interface, * as EPOLLIN and EPOLLOUT do not behave entirely as you would expect from * a network protocol. * * EPOLLIN is asserted if * - there is data on the receive queue. * - to signal that a previously congested destination may have become * uncongested * - A notification has been queued to the socket (this can be a congestion * update, or a RDMA completion, or a MSG_ZEROCOPY completion). * * EPOLLOUT is asserted if there is room on the send queue. This does not mean * however, that the next sendmsg() call will succeed. If the application tries * to send to a congested destination, the system call may still fail (and * return ENOBUFS). */ static __poll_t rds_poll(struct file *file, struct socket *sock, poll_table *wait) { … } static int rds_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) { … } static int rds_cancel_sent_to(struct rds_sock *rs, sockptr_t optval, int len) { … } static int rds_set_bool_option(unsigned char *optvar, sockptr_t optval, int optlen) { … } static int rds_cong_monitor(struct rds_sock *rs, sockptr_t optval, int optlen) { … } static int rds_set_transport(struct rds_sock *rs, sockptr_t optval, int optlen) { … } static int rds_enable_recvtstamp(struct sock *sk, sockptr_t optval, int optlen, int optname) { … } static int rds_recv_track_latency(struct rds_sock *rs, sockptr_t optval, int optlen) { … } static int rds_setsockopt(struct socket *sock, int level, int optname, sockptr_t optval, unsigned int optlen) { … } static int rds_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen) { … } static int rds_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags) { … } static struct proto rds_proto = …; static const struct proto_ops rds_proto_ops = …; static void rds_sock_destruct(struct sock *sk) { … } static int __rds_create(struct socket *sock, struct sock *sk, int protocol) { … } static int rds_create(struct net *net, struct socket *sock, int protocol, int kern) { … } void rds_sock_addref(struct rds_sock *rs) { … } void rds_sock_put(struct rds_sock *rs) { … } static const struct net_proto_family rds_family_ops = …; static void rds_sock_inc_info(struct socket *sock, unsigned int len, struct rds_info_iterator *iter, struct rds_info_lengths *lens) { … } #if IS_ENABLED(CONFIG_IPV6) static void rds6_sock_inc_info(struct socket *sock, unsigned int len, struct rds_info_iterator *iter, struct rds_info_lengths *lens) { … } #endif static void rds_sock_info(struct socket *sock, unsigned int len, struct rds_info_iterator *iter, struct rds_info_lengths *lens) { … } #if IS_ENABLED(CONFIG_IPV6) static void rds6_sock_info(struct socket *sock, unsigned int len, struct rds_info_iterator *iter, struct rds_info_lengths *lens) { … } #endif static void rds_exit(void) { … } module_exit(rds_exit); u32 rds_gen_num; static int __init rds_init(void) { … } module_init(…) …; #define DRV_VERSION … #define DRV_RELDATE … MODULE_AUTHOR(…) …; MODULE_DESCRIPTION(…) …; MODULE_VERSION(…); MODULE_LICENSE(…) …; MODULE_ALIAS_NETPROTO(…);