/* * Destroy an RPC service */ void svc_destroy(struct svc_serv *serv) { struct svc_sock *svsk; dprintk("RPC: svc_destroy(%s, %d)\n", serv->sv_program->pg_name, serv->sv_nrthreads); if (serv->sv_nrthreads) { if (--(serv->sv_nrthreads) != 0) { svc_sock_update_bufs(serv); return; } } else printk("svc_destroy: no threads for serv=%p!\n", serv); while (!list_empty(&serv->sv_tempsocks)) { svsk = list_entry(serv->sv_tempsocks.next, struct svc_sock, sk_list); svc_delete_socket(svsk); } if (serv->sv_shutdown) serv->sv_shutdown(serv); while (!list_empty(&serv->sv_permsocks)) { svsk = list_entry(serv->sv_permsocks.next, struct svc_sock, sk_list); svc_delete_socket(svsk); } cache_clean_deferred(serv); /* Unregister service with the portmapper */ svc_register(serv, 0, 0); kfree(serv); }
/* * Destroy an RPC service */ void svc_destroy(struct svc_serv *serv) { struct svc_sock *svsk; dprintk("RPC: svc_destroy(%s, %d)\n", serv->sv_program->pg_name, serv->sv_nrthreads); if (serv->sv_nrthreads) { if (--(serv->sv_nrthreads) != 0) return; } else printk("svc_destroy: no threads for serv=%p!\n", serv); while ((svsk = serv->sv_allsocks) != NULL) svc_delete_socket(svsk); /* Unregister service with the portmapper */ svc_register(serv, 0, 0); kfree(serv); }
/* * Receive data from a TCP socket. */ static int svc_tcp_recvfrom(struct svc_rqst *rqstp) { struct svc_sock *svsk = rqstp->rq_sock; struct svc_serv *serv = svsk->sk_server; struct svc_buf *bufp = &rqstp->rq_argbuf; int len, ready, used; dprintk("svc: tcp_recv %p data %d conn %d close %d\n", svsk, svsk->sk_data, svsk->sk_conn, svsk->sk_close); if (svsk->sk_close) { svc_delete_socket(svsk); return 0; } if (svsk->sk_conn) { svc_tcp_accept(svsk); svc_sock_accepted(svsk); return 0; } ready = svsk->sk_data; /* Receive data. If we haven't got the record length yet, get * the next four bytes. Otherwise try to gobble up as much as * possible up to the complete record length. */ if (svsk->sk_tcplen < 4) { unsigned long want = 4 - svsk->sk_tcplen; struct iovec iov; iov.iov_base = ((char *) &svsk->sk_reclen) + svsk->sk_tcplen; iov.iov_len = want; if ((len = svc_recvfrom(rqstp, &iov, 1, want)) < 0) goto error; svsk->sk_tcplen += len; svsk->sk_reclen = ntohl(svsk->sk_reclen); if (!(svsk->sk_reclen & 0x80000000)) { /* FIXME: technically, a record can be fragmented, * and non-terminal fragments will not have the top * bit set in the fragment length header. * But apparently no known nfs clients send fragmented * records. */ /* FIXME: shutdown socket */ printk(KERN_NOTICE "RPC: bad TCP reclen %08lx", (unsigned long) svsk->sk_reclen); return -EIO; } svsk->sk_reclen &= 0x7fffffff; dprintk("svc: TCP record, %d bytes\n", svsk->sk_reclen); } /* Check whether enough data is available */ len = svc_recv_available(svsk); if (len < 0) goto error; if (len < svsk->sk_reclen) { /* FIXME: if sk_reclen > window-size, then we will * never be able to receive the record, so should * shutdown the connection */ dprintk("svc: incomplete TCP record (%d of %d)\n", len, svsk->sk_reclen); svc_sock_received(svsk, ready); return -EAGAIN; /* record not complete */ } /* if we think there is only one more record to read, but * it is bigger than we expect, then two records must have arrived * together, so pretend we aren't using the record.. */ if (len > svsk->sk_reclen && ready == 1) used = 0; else used = 1; /* Frob argbuf */ bufp->iov[0].iov_base += 4; bufp->iov[0].iov_len -= 4; /* Now receive data */ len = svc_recvfrom(rqstp, bufp->iov, bufp->nriov, svsk->sk_reclen); if (len < 0) goto error; dprintk("svc: TCP complete record (%d bytes)\n", len); /* Position reply write pointer immediately after * record length */ rqstp->rq_resbuf.buf += 1; rqstp->rq_resbuf.len = 1; rqstp->rq_skbuff = 0; rqstp->rq_argbuf.buf += 1; rqstp->rq_argbuf.len = (len >> 2); rqstp->rq_prot = IPPROTO_TCP; /* Reset TCP read info */ svsk->sk_reclen = 0; svsk->sk_tcplen = 0; svc_sock_received(svsk, used); if (serv->sv_stats) serv->sv_stats->nettcpcnt++; return len; error: if (len == -EAGAIN) { dprintk("RPC: TCP recvfrom got EAGAIN\n"); svc_sock_received(svsk, ready); /* Clear data ready */ } else { printk(KERN_NOTICE "%s: recvfrom returned errno %d\n", svsk->sk_server->sv_name, -len); svc_sock_received(svsk, 0); } return len; }
/* * Receive data from a TCP socket. */ static int svc_tcp_recvfrom(struct svc_rqst *rqstp) { struct svc_sock *svsk = rqstp->rq_sock; struct svc_serv *serv = svsk->sk_server; struct svc_buf *bufp = &rqstp->rq_argbuf; int len, ready; dprintk("svc: tcp_recv %p data %d conn %d close %d\n", svsk, svsk->sk_data, svsk->sk_conn, svsk->sk_close); if (svsk->sk_close) { svc_delete_socket(svsk); return 0; } if (svsk->sk_conn) { svc_tcp_accept(svsk); svc_sock_accepted(svsk); return 0; } ready = svsk->sk_data; /* Receive data. If we haven't got the record length yet, get * the next four bytes. Otherwise try to gobble up as much as * possible up to the complete record length. */ if (svsk->sk_tcplen < 4) { unsigned long want = 4 - svsk->sk_tcplen; struct iovec iov; iov.iov_base = ((u32 *) &svsk->sk_reclen) + svsk->sk_tcplen; iov.iov_len = want; if ((len = svc_recvfrom(rqstp, &iov, 1, want)) < 0) goto error; svsk->sk_tcplen += len; svsk->sk_reclen = ntohl(svsk->sk_reclen); if (!(svsk->sk_reclen & 0x80000000)) { /* FIXME: shutdown socket */ printk(KERN_NOTICE "RPC: bad TCP reclen %08lx", (unsigned long) svsk->sk_reclen); return -EIO; } svsk->sk_reclen &= 0x7fffffff; dprintk("svc: TCP record, %ld bytes\n", svsk->sk_reclen); } /* Check whether enough data is available */ len = svc_recv_available(svsk); if (len < 0) goto error; if (len < svsk->sk_reclen) { dprintk("svc: incomplete TCP record (%d of %ld)\n", len, svsk->sk_reclen); svc_sock_received(svsk, ready); len = -EAGAIN; /* record not complete */ } /* Frob argbuf */ bufp->iov[0].iov_base += 4; bufp->iov[0].iov_len -= 4; /* Now receive data */ len = svc_recvfrom(rqstp, bufp->iov, bufp->nriov, svsk->sk_reclen); if (len < 0) goto error; dprintk("svc: TCP complete record (%d bytes)\n", len); /* Position reply write pointer immediately after * record length */ rqstp->rq_resbuf.buf += 1; rqstp->rq_resbuf.len = 1; rqstp->rq_skbuff = 0; rqstp->rq_argbuf.buf += 1; rqstp->rq_argbuf.len = (len >> 2); rqstp->rq_prot = IPPROTO_TCP; /* Reset TCP read info */ svsk->sk_reclen = 0; svsk->sk_tcplen = 0; svc_sock_received(svsk, 1); if (serv->sv_stats) serv->sv_stats->nettcpcnt++; return len; error: if (len == -EAGAIN) { dprintk("RPC: TCP recvfrom got EAGAIN\n"); svc_sock_received(svsk, ready); /* Clear data ready */ } else { printk(KERN_NOTICE "%s: recvfrom returned errno %d\n", svsk->sk_server->sv_name, -len); svc_sock_received(svsk, 0); } return len; }