mirror of
https://github.com/tbsdtv/linux_media.git
synced 2025-07-23 20:51:03 +02:00
Merge branch 'for-2.6.31' of git://fieldses.org/git/linux-nfsd
* 'for-2.6.31' of git://fieldses.org/git/linux-nfsd: (60 commits) SUNRPC: Fix the TCP server's send buffer accounting nfsd41: Backchannel: minorversion support for the back channel nfsd41: Backchannel: cleanup nfs4.0 callback encode routines nfsd41: Remove ip address collision detection case nfsd: optimise the starting of zero threads when none are running. nfsd: don't take nfsd_mutex twice when setting number of threads. nfsd41: sanity check client drc maxreqs nfsd41: move channel attributes from nfsd4_session to a nfsd4_channel_attr struct NFS: kill off complicated macro 'PROC' sunrpc: potential memory leak in function rdma_read_xdr nfsd: minor nfsd_vfs_write cleanup nfsd: Pull write-gathering code out of nfsd_vfs_write nfsd: track last inode only in use_wgather case sunrpc: align cache_clean work's timer nfsd: Use write gathering only with NFSv2 NFSv4: kill off complicated macro 'PROC' NFSv4: do exact check about attribute specified knfsd: remove unreported filehandle stats counters knfsd: fix reply cache memory corruption knfsd: reply cache cleanups ...
This commit is contained in:
@@ -240,42 +240,76 @@ out:
|
||||
/*
|
||||
* Report socket names for nfsdfs
|
||||
*/
|
||||
static int one_sock_name(char *buf, struct svc_sock *svsk)
|
||||
static int svc_one_sock_name(struct svc_sock *svsk, char *buf, int remaining)
|
||||
{
|
||||
const struct sock *sk = svsk->sk_sk;
|
||||
const char *proto_name = sk->sk_protocol == IPPROTO_UDP ?
|
||||
"udp" : "tcp";
|
||||
int len;
|
||||
|
||||
switch(svsk->sk_sk->sk_family) {
|
||||
case AF_INET:
|
||||
len = sprintf(buf, "ipv4 %s %pI4 %d\n",
|
||||
svsk->sk_sk->sk_protocol == IPPROTO_UDP ?
|
||||
"udp" : "tcp",
|
||||
&inet_sk(svsk->sk_sk)->rcv_saddr,
|
||||
inet_sk(svsk->sk_sk)->num);
|
||||
switch (sk->sk_family) {
|
||||
case PF_INET:
|
||||
len = snprintf(buf, remaining, "ipv4 %s %pI4 %d\n",
|
||||
proto_name,
|
||||
&inet_sk(sk)->rcv_saddr,
|
||||
inet_sk(sk)->num);
|
||||
break;
|
||||
case PF_INET6:
|
||||
len = snprintf(buf, remaining, "ipv6 %s %pI6 %d\n",
|
||||
proto_name,
|
||||
&inet6_sk(sk)->rcv_saddr,
|
||||
inet_sk(sk)->num);
|
||||
break;
|
||||
default:
|
||||
len = sprintf(buf, "*unknown-%d*\n",
|
||||
svsk->sk_sk->sk_family);
|
||||
len = snprintf(buf, remaining, "*unknown-%d*\n",
|
||||
sk->sk_family);
|
||||
}
|
||||
|
||||
if (len >= remaining) {
|
||||
*buf = '\0';
|
||||
return -ENAMETOOLONG;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
int
|
||||
svc_sock_names(char *buf, struct svc_serv *serv, char *toclose)
|
||||
/**
|
||||
* svc_sock_names - construct a list of listener names in a string
|
||||
* @serv: pointer to RPC service
|
||||
* @buf: pointer to a buffer to fill in with socket names
|
||||
* @buflen: size of the buffer to be filled
|
||||
* @toclose: pointer to '\0'-terminated C string containing the name
|
||||
* of a listener to be closed
|
||||
*
|
||||
* Fills in @buf with a '\n'-separated list of names of listener
|
||||
* sockets. If @toclose is not NULL, the socket named by @toclose
|
||||
* is closed, and is not included in the output list.
|
||||
*
|
||||
* Returns positive length of the socket name string, or a negative
|
||||
* errno value on error.
|
||||
*/
|
||||
int svc_sock_names(struct svc_serv *serv, char *buf, const size_t buflen,
|
||||
const char *toclose)
|
||||
{
|
||||
struct svc_sock *svsk, *closesk = NULL;
|
||||
int len = 0;
|
||||
|
||||
if (!serv)
|
||||
return 0;
|
||||
|
||||
spin_lock_bh(&serv->sv_lock);
|
||||
list_for_each_entry(svsk, &serv->sv_permsocks, sk_xprt.xpt_list) {
|
||||
int onelen = one_sock_name(buf+len, svsk);
|
||||
if (toclose && strcmp(toclose, buf+len) == 0)
|
||||
int onelen = svc_one_sock_name(svsk, buf + len, buflen - len);
|
||||
if (onelen < 0) {
|
||||
len = onelen;
|
||||
break;
|
||||
}
|
||||
if (toclose && strcmp(toclose, buf + len) == 0)
|
||||
closesk = svsk;
|
||||
else
|
||||
len += onelen;
|
||||
}
|
||||
spin_unlock_bh(&serv->sv_lock);
|
||||
|
||||
if (closesk)
|
||||
/* Should unregister with portmap, but you cannot
|
||||
* unregister just one protocol...
|
||||
@@ -346,6 +380,7 @@ static void svc_sock_setbufsize(struct socket *sock, unsigned int snd,
|
||||
sock->sk->sk_sndbuf = snd * 2;
|
||||
sock->sk->sk_rcvbuf = rcv * 2;
|
||||
sock->sk->sk_userlocks |= SOCK_SNDBUF_LOCK|SOCK_RCVBUF_LOCK;
|
||||
sock->sk->sk_write_space(sock->sk);
|
||||
release_sock(sock->sk);
|
||||
#endif
|
||||
}
|
||||
@@ -387,6 +422,15 @@ static void svc_write_space(struct sock *sk)
|
||||
}
|
||||
}
|
||||
|
||||
static void svc_tcp_write_space(struct sock *sk)
|
||||
{
|
||||
struct socket *sock = sk->sk_socket;
|
||||
|
||||
if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk) && sock)
|
||||
clear_bit(SOCK_NOSPACE, &sock->flags);
|
||||
svc_write_space(sk);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy the UDP datagram's destination address to the rqstp structure.
|
||||
* The 'destination' address in this case is the address to which the
|
||||
@@ -427,13 +471,14 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp)
|
||||
long all[SVC_PKTINFO_SPACE / sizeof(long)];
|
||||
} buffer;
|
||||
struct cmsghdr *cmh = &buffer.hdr;
|
||||
int err, len;
|
||||
struct msghdr msg = {
|
||||
.msg_name = svc_addr(rqstp),
|
||||
.msg_control = cmh,
|
||||
.msg_controllen = sizeof(buffer),
|
||||
.msg_flags = MSG_DONTWAIT,
|
||||
};
|
||||
size_t len;
|
||||
int err;
|
||||
|
||||
if (test_and_clear_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags))
|
||||
/* udp sockets need large rcvbuf as all pending
|
||||
@@ -465,8 +510,8 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp)
|
||||
return -EAGAIN;
|
||||
}
|
||||
len = svc_addr_len(svc_addr(rqstp));
|
||||
if (len < 0)
|
||||
return len;
|
||||
if (len == 0)
|
||||
return -EAFNOSUPPORT;
|
||||
rqstp->rq_addrlen = len;
|
||||
if (skb->tstamp.tv64 == 0) {
|
||||
skb->tstamp = ktime_get_real();
|
||||
@@ -980,25 +1025,16 @@ static void svc_tcp_prep_reply_hdr(struct svc_rqst *rqstp)
|
||||
static int svc_tcp_has_wspace(struct svc_xprt *xprt)
|
||||
{
|
||||
struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt);
|
||||
struct svc_serv *serv = svsk->sk_xprt.xpt_server;
|
||||
struct svc_serv *serv = svsk->sk_xprt.xpt_server;
|
||||
int required;
|
||||
int wspace;
|
||||
|
||||
/*
|
||||
* Set the SOCK_NOSPACE flag before checking the available
|
||||
* sock space.
|
||||
*/
|
||||
if (test_bit(XPT_LISTENER, &xprt->xpt_flags))
|
||||
return 1;
|
||||
required = atomic_read(&xprt->xpt_reserved) + serv->sv_max_mesg;
|
||||
if (sk_stream_wspace(svsk->sk_sk) >= required)
|
||||
return 1;
|
||||
set_bit(SOCK_NOSPACE, &svsk->sk_sock->flags);
|
||||
required = atomic_read(&svsk->sk_xprt.xpt_reserved) + serv->sv_max_mesg;
|
||||
wspace = sk_stream_wspace(svsk->sk_sk);
|
||||
|
||||
if (wspace < sk_stream_min_wspace(svsk->sk_sk))
|
||||
return 0;
|
||||
if (required * 2 > wspace)
|
||||
return 0;
|
||||
|
||||
clear_bit(SOCK_NOSPACE, &svsk->sk_sock->flags);
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct svc_xprt *svc_tcp_create(struct svc_serv *serv,
|
||||
@@ -1054,7 +1090,7 @@ static void svc_tcp_init(struct svc_sock *svsk, struct svc_serv *serv)
|
||||
dprintk("setting up TCP socket for reading\n");
|
||||
sk->sk_state_change = svc_tcp_state_change;
|
||||
sk->sk_data_ready = svc_tcp_data_ready;
|
||||
sk->sk_write_space = svc_write_space;
|
||||
sk->sk_write_space = svc_tcp_write_space;
|
||||
|
||||
svsk->sk_reclen = 0;
|
||||
svsk->sk_tcplen = 0;
|
||||
@@ -1148,9 +1184,19 @@ static struct svc_sock *svc_setup_socket(struct svc_serv *serv,
|
||||
return svsk;
|
||||
}
|
||||
|
||||
int svc_addsock(struct svc_serv *serv,
|
||||
int fd,
|
||||
char *name_return)
|
||||
/**
|
||||
* svc_addsock - add a listener socket to an RPC service
|
||||
* @serv: pointer to RPC service to which to add a new listener
|
||||
* @fd: file descriptor of the new listener
|
||||
* @name_return: pointer to buffer to fill in with name of listener
|
||||
* @len: size of the buffer
|
||||
*
|
||||
* Fills in socket name and returns positive length of name if successful.
|
||||
* Name is terminated with '\n'. On error, returns a negative errno
|
||||
* value.
|
||||
*/
|
||||
int svc_addsock(struct svc_serv *serv, const int fd, char *name_return,
|
||||
const size_t len)
|
||||
{
|
||||
int err = 0;
|
||||
struct socket *so = sockfd_lookup(fd, &err);
|
||||
@@ -1190,7 +1236,7 @@ int svc_addsock(struct svc_serv *serv,
|
||||
sockfd_put(so);
|
||||
return err;
|
||||
}
|
||||
return one_sock_name(name_return, svsk);
|
||||
return svc_one_sock_name(svsk, name_return, len);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(svc_addsock);
|
||||
|
||||
|
Reference in New Issue
Block a user