#include <linux/slab.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
+#include <linux/file.h>
#include <net/sock.h>
#include <net/checksum.h>
#include <net/ip.h>
/* send head */
if (slen == xdr->head[0].iov_len)
flags = 0;
- len = sock->ops->sendpage(sock, rqstp->rq_respages[0], 0, xdr->head[0].iov_len, flags);
+ len = kernel_sendpage(sock, rqstp->rq_respages[0], 0, xdr->head[0].iov_len, flags);
if (len != xdr->head[0].iov_len)
goto out;
slen -= xdr->head[0].iov_len;
while (pglen > 0) {
if (slen == size)
flags = 0;
- result = sock->ops->sendpage(sock, *ppage, base, size, flags);
+ result = kernel_sendpage(sock, *ppage, base, size, flags);
if (result > 0)
len += result;
if (result != size)
}
/* send tail */
if (xdr->tail[0].iov_len) {
- result = sock->ops->sendpage(sock, rqstp->rq_respages[rqstp->rq_restailpage],
+ result = kernel_sendpage(sock, rqstp->rq_respages[rqstp->rq_restailpage],
((unsigned long)xdr->tail[0].iov_base)& (PAGE_SIZE-1),
xdr->tail[0].iov_len, 0);
return len;
}
+/*
+ * Report socket names for nfsdfs
+ */
+static int one_sock_name(char *buf, struct svc_sock *svsk)
+{
+ int len;
+
+ switch(svsk->sk_sk->sk_family) {
+ case AF_INET:
+ len = sprintf(buf, "ipv4 %s %u.%u.%u.%u %d\n",
+ svsk->sk_sk->sk_protocol==IPPROTO_UDP?
+ "udp" : "tcp",
+ NIPQUAD(inet_sk(svsk->sk_sk)->rcv_saddr),
+ inet_sk(svsk->sk_sk)->num);
+ break;
+ default:
+ len = sprintf(buf, "*unknown-%d*\n",
+ svsk->sk_sk->sk_family);
+ }
+ return len;
+}
+
+int
+svc_sock_names(char *buf, struct svc_serv *serv, char *toclose)
+{
+ struct svc_sock *svsk, *closesk = NULL;
+ int len = 0;
+
+ if (!serv)
+ return 0;
+ spin_lock(&serv->sv_lock);
+ list_for_each_entry(svsk, &serv->sv_permsocks, sk_list) {
+ int onelen = one_sock_name(buf+len, svsk);
+ if (toclose && strcmp(toclose, buf+len) == 0)
+ closesk = svsk;
+ else
+ len += onelen;
+ }
+ spin_unlock(&serv->sv_lock);
+ if (closesk)
+ svc_delete_socket(closesk);
+ return len;
+}
+EXPORT_SYMBOL(svc_sock_names);
+
/*
* Check input queue length
*/
static int
svc_recv_available(struct svc_sock *svsk)
{
- mm_segment_t oldfs;
struct socket *sock = svsk->sk_sock;
int avail, err;
- oldfs = get_fs(); set_fs(KERNEL_DS);
- err = sock->ops->ioctl(sock, TIOCINQ, (unsigned long) &avail);
- set_fs(oldfs);
+ err = kernel_sock_ioctl(sock, TIOCINQ, (unsigned long) &avail);
return (err >= 0)? avail : err;
}
* at accept time. FIXME
*/
alen = sizeof(rqstp->rq_addr);
- sock->ops->getname(sock, (struct sockaddr *)&rqstp->rq_addr, &alen, 1);
+ kernel_getpeername(sock, (struct sockaddr *)&rqstp->rq_addr, &alen);
dprintk("svc: socket %p recvfrom(%p, %Zu) = %d\n",
rqstp->rq_sock, iov[0].iov_base, iov[0].iov_len, len);
struct svc_serv *serv = svsk->sk_server;
struct socket *sock = svsk->sk_sock;
struct socket *newsock;
- const struct proto_ops *ops;
struct svc_sock *newsvsk;
int err, slen;
if (!sock)
return;
- err = sock_create_lite(PF_INET, SOCK_STREAM, IPPROTO_TCP, &newsock);
- if (err) {
+ clear_bit(SK_CONN, &svsk->sk_flags);
+ err = kernel_accept(sock, &newsock, O_NONBLOCK);
+ if (err < 0) {
if (err == -ENOMEM)
printk(KERN_WARNING "%s: no more sockets!\n",
serv->sv_name);
- return;
- }
-
- dprintk("svc: tcp_accept %p allocated\n", newsock);
- newsock->ops = ops = sock->ops;
-
- clear_bit(SK_CONN, &svsk->sk_flags);
- if ((err = ops->accept(sock, newsock, O_NONBLOCK)) < 0) {
- if (err != -EAGAIN && net_ratelimit())
+ else if (err != -EAGAIN && net_ratelimit())
printk(KERN_WARNING "%s: accept failed (err %d)!\n",
serv->sv_name, -err);
- goto failed; /* aborted connection or whatever */
+ return;
}
+
set_bit(SK_CONN, &svsk->sk_flags);
svc_sock_enqueue(svsk);
slen = sizeof(sin);
- err = ops->getname(newsock, (struct sockaddr *) &sin, &slen, 1);
+ err = kernel_getpeername(newsock, (struct sockaddr *) &sin, &slen);
if (err < 0) {
if (net_ratelimit())
printk(KERN_WARNING "%s: peername failed (err %d)!\n",
{
struct xdr_buf *xbufp = &rqstp->rq_res;
int sent;
- u32 reclen;
+ __be32 reclen;
/* Set up the first element of the reply kvec.
* Any other kvecs that may be in use have been taken
* Receive the next request on any socket.
*/
int
-svc_recv(struct svc_serv *serv, struct svc_rqst *rqstp, long timeout)
+svc_recv(struct svc_rqst *rqstp, long timeout)
{
struct svc_sock *svsk =NULL;
+ struct svc_serv *serv = rqstp->rq_server;
int len;
int pages;
struct xdr_buf *arg;
xb->page_len +
xb->tail[0].iov_len;
- /* Grab svsk->sk_sem to serialize outgoing data. */
- down(&svsk->sk_sem);
+ /* Grab svsk->sk_mutex to serialize outgoing data. */
+ mutex_lock(&svsk->sk_mutex);
if (test_bit(SK_DEAD, &svsk->sk_flags))
len = -ENOTCONN;
else
len = svsk->sk_sendto(rqstp);
- up(&svsk->sk_sem);
+ mutex_unlock(&svsk->sk_mutex);
svc_sock_release(rqstp);
if (len == -ECONNREFUSED || len == -ENOTCONN || len == -EAGAIN)
struct sock *inet;
dprintk("svc: svc_setup_socket %p\n", sock);
- if (!(svsk = kmalloc(sizeof(*svsk), GFP_KERNEL))) {
+ if (!(svsk = kzalloc(sizeof(*svsk), GFP_KERNEL))) {
*errp = -ENOMEM;
return NULL;
}
- memset(svsk, 0, sizeof(*svsk));
inet = sock->sk;
svsk->sk_lastrecv = get_seconds();
INIT_LIST_HEAD(&svsk->sk_deferred);
INIT_LIST_HEAD(&svsk->sk_ready);
- sema_init(&svsk->sk_sem, 1);
+ mutex_init(&svsk->sk_mutex);
/* Initialize the socket */
if (sock->type == SOCK_DGRAM)
return svsk;
}
+int svc_addsock(struct svc_serv *serv,
+ int fd,
+ char *name_return,
+ int *proto)
+{
+ int err = 0;
+ struct socket *so = sockfd_lookup(fd, &err);
+ struct svc_sock *svsk = NULL;
+
+ if (!so)
+ return err;
+ if (so->sk->sk_family != AF_INET)
+ err = -EAFNOSUPPORT;
+ else if (so->sk->sk_protocol != IPPROTO_TCP &&
+ so->sk->sk_protocol != IPPROTO_UDP)
+ err = -EPROTONOSUPPORT;
+ else if (so->state > SS_UNCONNECTED)
+ err = -EISCONN;
+ else {
+ svsk = svc_setup_socket(serv, so, &err, 1);
+ if (svsk)
+ err = 0;
+ }
+ if (err) {
+ sockfd_put(so);
+ return err;
+ }
+ if (proto) *proto = so->sk->sk_protocol;
+ return one_sock_name(name_return, svsk);
+}
+EXPORT_SYMBOL_GPL(svc_addsock);
+
/*
* Create socket for RPC service.
*/
if ((error = sock_create_kern(PF_INET, type, protocol, &sock)) < 0)
return error;
- if (sin != NULL) {
- if (type == SOCK_STREAM)
- sock->sk->sk_reuse = 1; /* allow address reuse */
- error = sock->ops->bind(sock, (struct sockaddr *) sin,
- sizeof(*sin));
- if (error < 0)
- goto bummer;
- }
+ if (type == SOCK_STREAM)
+ sock->sk->sk_reuse = 1; /* allow address reuse */
+ error = kernel_bind(sock, (struct sockaddr *) sin,
+ sizeof(*sin));
+ if (error < 0)
+ goto bummer;
if (protocol == IPPROTO_TCP) {
- if ((error = sock->ops->listen(sock, 64)) < 0)
+ if ((error = kernel_listen(sock, 64)) < 0)
goto bummer;
}
if (!svsk->sk_inuse) {
spin_unlock_bh(&serv->sv_lock);
- sock_release(svsk->sk_sock);
+ if (svsk->sk_sock->file)
+ sockfd_put(svsk->sk_sock);
+ else
+ sock_release(svsk->sk_sock);
kfree(svsk);
} else {
spin_unlock_bh(&serv->sv_lock);
dr->handle.owner = rqstp->rq_server;
dr->prot = rqstp->rq_prot;
dr->addr = rqstp->rq_addr;
+ dr->daddr = rqstp->rq_daddr;
dr->argslen = rqstp->rq_arg.len >> 2;
memcpy(dr->args, rqstp->rq_arg.head[0].iov_base-skip, dr->argslen<<2);
}
rqstp->rq_arg.len = dr->argslen<<2;
rqstp->rq_prot = dr->prot;
rqstp->rq_addr = dr->addr;
+ rqstp->rq_daddr = dr->daddr;
return dr->argslen<<2;
}