diff options
author | Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | 2012-01-27 11:14:02 -0500 |
---|---|---|
committer | Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | 2012-01-27 11:14:02 -0500 |
commit | 6c02b7b1610f873888af20f291c07730889ff0f9 (patch) | |
tree | 1b33e6642cc81605b8d37c0bda0abff0ba64fa2d /net/unix/af_unix.c | |
parent | 7a7546b377bdaa25ac77f33d9433c59f259b9688 (diff) | |
parent | dcd6c92267155e70a94b3927bce681ce74b80d1f (diff) |
Merge commit 'v3.3-rc1' into stable/for-linus-fixes-3.3
* commit 'v3.3-rc1': (9775 commits)
Linux 3.3-rc1
x86, syscall: Need __ARCH_WANT_SYS_IPC for 32 bits
qnx4: don't leak ->BitMap on late failure exits
qnx4: reduce the insane nesting in qnx4_checkroot()
qnx4: di_fname is an array, for crying out loud...
KEYS: Permit key_serial() to be called with a const key pointer
keys: fix user_defined key sparse messages
ima: fix cred sparse warning
uml: fix compile for x86-64
MPILIB: Add a missing ENOMEM check
tpm: fix (ACPI S3) suspend regression
nvme: fix merge error due to change of 'make_request_fn' fn type
xen: using EXPORT_SYMBOL requires including export.h
gpio: tps65910: Use correct offset for gpio initialization
acpi/apei/einj: Add extensions to EINJ from rev 5.0 of acpi spec
intel_idle: Split up and provide per CPU initialization func
ACPI processor: Remove unneeded variable passed by acpi_processor_hotadd_init V2
tg3: Fix single-vector MSI-X code
openvswitch: Fix multipart datapath dumps.
ipv6: fix per device IP snmp counters
...
Diffstat (limited to 'net/unix/af_unix.c')
-rw-r--r-- | net/unix/af_unix.c | 74 |
1 files changed, 47 insertions, 27 deletions
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 466fbcc5cf77..aad8fb699989 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
@@ -115,8 +115,10 @@ | |||
115 | #include <net/checksum.h> | 115 | #include <net/checksum.h> |
116 | #include <linux/security.h> | 116 | #include <linux/security.h> |
117 | 117 | ||
118 | static struct hlist_head unix_socket_table[UNIX_HASH_SIZE + 1]; | 118 | struct hlist_head unix_socket_table[UNIX_HASH_SIZE + 1]; |
119 | static DEFINE_SPINLOCK(unix_table_lock); | 119 | EXPORT_SYMBOL_GPL(unix_socket_table); |
120 | DEFINE_SPINLOCK(unix_table_lock); | ||
121 | EXPORT_SYMBOL_GPL(unix_table_lock); | ||
120 | static atomic_long_t unix_nr_socks; | 122 | static atomic_long_t unix_nr_socks; |
121 | 123 | ||
122 | #define unix_sockets_unbound (&unix_socket_table[UNIX_HASH_SIZE]) | 124 | #define unix_sockets_unbound (&unix_socket_table[UNIX_HASH_SIZE]) |
@@ -172,7 +174,7 @@ static inline int unix_recvq_full(struct sock const *sk) | |||
172 | return skb_queue_len(&sk->sk_receive_queue) > sk->sk_max_ack_backlog; | 174 | return skb_queue_len(&sk->sk_receive_queue) > sk->sk_max_ack_backlog; |
173 | } | 175 | } |
174 | 176 | ||
175 | static struct sock *unix_peer_get(struct sock *s) | 177 | struct sock *unix_peer_get(struct sock *s) |
176 | { | 178 | { |
177 | struct sock *peer; | 179 | struct sock *peer; |
178 | 180 | ||
@@ -183,6 +185,7 @@ static struct sock *unix_peer_get(struct sock *s) | |||
183 | unix_state_unlock(s); | 185 | unix_state_unlock(s); |
184 | return peer; | 186 | return peer; |
185 | } | 187 | } |
188 | EXPORT_SYMBOL_GPL(unix_peer_get); | ||
186 | 189 | ||
187 | static inline void unix_release_addr(struct unix_address *addr) | 190 | static inline void unix_release_addr(struct unix_address *addr) |
188 | { | 191 | { |
@@ -847,7 +850,7 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
847 | atomic_set(&addr->refcnt, 1); | 850 | atomic_set(&addr->refcnt, 1); |
848 | 851 | ||
849 | if (sun_path[0]) { | 852 | if (sun_path[0]) { |
850 | unsigned int mode; | 853 | umode_t mode; |
851 | err = 0; | 854 | err = 0; |
852 | /* | 855 | /* |
853 | * Get the parent directory, calculate the hash for last | 856 | * Get the parent directory, calculate the hash for last |
@@ -1957,6 +1960,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1957 | if ((UNIXCB(skb).pid != siocb->scm->pid) || | 1960 | if ((UNIXCB(skb).pid != siocb->scm->pid) || |
1958 | (UNIXCB(skb).cred != siocb->scm->cred)) { | 1961 | (UNIXCB(skb).cred != siocb->scm->cred)) { |
1959 | skb_queue_head(&sk->sk_receive_queue, skb); | 1962 | skb_queue_head(&sk->sk_receive_queue, skb); |
1963 | sk->sk_data_ready(sk, skb->len); | ||
1960 | break; | 1964 | break; |
1961 | } | 1965 | } |
1962 | } else { | 1966 | } else { |
@@ -1974,6 +1978,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1974 | chunk = min_t(unsigned int, skb->len, size); | 1978 | chunk = min_t(unsigned int, skb->len, size); |
1975 | if (memcpy_toiovec(msg->msg_iov, skb->data, chunk)) { | 1979 | if (memcpy_toiovec(msg->msg_iov, skb->data, chunk)) { |
1976 | skb_queue_head(&sk->sk_receive_queue, skb); | 1980 | skb_queue_head(&sk->sk_receive_queue, skb); |
1981 | sk->sk_data_ready(sk, skb->len); | ||
1977 | if (copied == 0) | 1982 | if (copied == 0) |
1978 | copied = -EFAULT; | 1983 | copied = -EFAULT; |
1979 | break; | 1984 | break; |
@@ -1991,6 +1996,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1991 | /* put the skb back if we didn't use it up.. */ | 1996 | /* put the skb back if we didn't use it up.. */ |
1992 | if (skb->len) { | 1997 | if (skb->len) { |
1993 | skb_queue_head(&sk->sk_receive_queue, skb); | 1998 | skb_queue_head(&sk->sk_receive_queue, skb); |
1999 | sk->sk_data_ready(sk, skb->len); | ||
1994 | break; | 2000 | break; |
1995 | } | 2001 | } |
1996 | 2002 | ||
@@ -2006,6 +2012,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
2006 | 2012 | ||
2007 | /* put message back and return */ | 2013 | /* put message back and return */ |
2008 | skb_queue_head(&sk->sk_receive_queue, skb); | 2014 | skb_queue_head(&sk->sk_receive_queue, skb); |
2015 | sk->sk_data_ready(sk, skb->len); | ||
2009 | break; | 2016 | break; |
2010 | } | 2017 | } |
2011 | } while (size); | 2018 | } while (size); |
@@ -2058,6 +2065,36 @@ static int unix_shutdown(struct socket *sock, int mode) | |||
2058 | return 0; | 2065 | return 0; |
2059 | } | 2066 | } |
2060 | 2067 | ||
2068 | long unix_inq_len(struct sock *sk) | ||
2069 | { | ||
2070 | struct sk_buff *skb; | ||
2071 | long amount = 0; | ||
2072 | |||
2073 | if (sk->sk_state == TCP_LISTEN) | ||
2074 | return -EINVAL; | ||
2075 | |||
2076 | spin_lock(&sk->sk_receive_queue.lock); | ||
2077 | if (sk->sk_type == SOCK_STREAM || | ||
2078 | sk->sk_type == SOCK_SEQPACKET) { | ||
2079 | skb_queue_walk(&sk->sk_receive_queue, skb) | ||
2080 | amount += skb->len; | ||
2081 | } else { | ||
2082 | skb = skb_peek(&sk->sk_receive_queue); | ||
2083 | if (skb) | ||
2084 | amount = skb->len; | ||
2085 | } | ||
2086 | spin_unlock(&sk->sk_receive_queue.lock); | ||
2087 | |||
2088 | return amount; | ||
2089 | } | ||
2090 | EXPORT_SYMBOL_GPL(unix_inq_len); | ||
2091 | |||
2092 | long unix_outq_len(struct sock *sk) | ||
2093 | { | ||
2094 | return sk_wmem_alloc_get(sk); | ||
2095 | } | ||
2096 | EXPORT_SYMBOL_GPL(unix_outq_len); | ||
2097 | |||
2061 | static int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | 2098 | static int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) |
2062 | { | 2099 | { |
2063 | struct sock *sk = sock->sk; | 2100 | struct sock *sk = sock->sk; |
@@ -2066,33 +2103,16 @@ static int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
2066 | 2103 | ||
2067 | switch (cmd) { | 2104 | switch (cmd) { |
2068 | case SIOCOUTQ: | 2105 | case SIOCOUTQ: |
2069 | amount = sk_wmem_alloc_get(sk); | 2106 | amount = unix_outq_len(sk); |
2070 | err = put_user(amount, (int __user *)arg); | 2107 | err = put_user(amount, (int __user *)arg); |
2071 | break; | 2108 | break; |
2072 | case SIOCINQ: | 2109 | case SIOCINQ: |
2073 | { | 2110 | amount = unix_inq_len(sk); |
2074 | struct sk_buff *skb; | 2111 | if (amount < 0) |
2075 | 2112 | err = amount; | |
2076 | if (sk->sk_state == TCP_LISTEN) { | 2113 | else |
2077 | err = -EINVAL; | ||
2078 | break; | ||
2079 | } | ||
2080 | |||
2081 | spin_lock(&sk->sk_receive_queue.lock); | ||
2082 | if (sk->sk_type == SOCK_STREAM || | ||
2083 | sk->sk_type == SOCK_SEQPACKET) { | ||
2084 | skb_queue_walk(&sk->sk_receive_queue, skb) | ||
2085 | amount += skb->len; | ||
2086 | } else { | ||
2087 | skb = skb_peek(&sk->sk_receive_queue); | ||
2088 | if (skb) | ||
2089 | amount = skb->len; | ||
2090 | } | ||
2091 | spin_unlock(&sk->sk_receive_queue.lock); | ||
2092 | err = put_user(amount, (int __user *)arg); | 2114 | err = put_user(amount, (int __user *)arg); |
2093 | break; | 2115 | break; |
2094 | } | ||
2095 | |||
2096 | default: | 2116 | default: |
2097 | err = -ENOIOCTLCMD; | 2117 | err = -ENOIOCTLCMD; |
2098 | break; | 2118 | break; |