diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-03-23 07:06:43 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-03-23 07:06:43 -0400 |
commit | 7483d45f0aee3afc0646d185cabd4af9f6cab58c (patch) | |
tree | a312f7d77c34748bec62f0431df33007b10e4e7f /net/unix/af_unix.c | |
parent | 3e85fc1b9fc1c7e20b9a01f2314bb633bb10501a (diff) | |
parent | f92c97c8bd77992ff8bd6ef29a23dc82dca799cb (diff) |
Merge branch 'staging/for_v3.4' into v4l_for_linus
* staging/for_v3.4: (10117 commits)
[media] update CARDLIST.em28xx
[media] partially reverts changeset fa5527c
[media] stb0899: fix the limits for signal strength values
[media] em28xx: support for 2304:0242 PCTV QuatroStick (510e)
[media] em28xx: support for 2013:0251 PCTV QuatroStick nano (520e)
[media] -EINVAL -> -ENOTTY
[media] gspca - sn9c20x: Cleanup source
[media] gspca - sn9c20x: Simplify register write for capture start/stop
[media] gspca - sn9c20x: Add automatic JPEG compression mechanism
[media] gspca - sn9c20x: Greater delay in case of sensor no response
[media] gspca - sn9c20x: Optimize the code of write sequences
[media] gspca - sn9c20x: Add the JPEG compression quality control
[media] gspca - sn9c20x: Add a delay after Omnivision sensor reset
[media] gspca - sn9c20x: Propagate USB errors to higher level
[media] gspca - sn9c20x: Use the new video control mechanism
[media] gspca - sn9c20x: Fix loss of frame start
[media] gspca - zc3xx: Lack of register 08 value for sensor cs2102k
[media] gspca - ov534_9: Add brightness to OmniVision 5621 sensor
[media] gspca - zc3xx: Add V4L2_CID_JPEG_COMPRESSION_QUALITY control support
[media] pvrusb2: fix 7MHz & 8MHz DVB-T tuner support for HVR1900 rev D1F5
...
Diffstat (limited to 'net/unix/af_unix.c')
-rw-r--r-- | net/unix/af_unix.c | 89 |
1 files changed, 47 insertions, 42 deletions
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index b595a3d8679f..85d3bb7490aa 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 |
@@ -1915,7 +1918,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1915 | struct sk_buff *skb; | 1918 | struct sk_buff *skb; |
1916 | 1919 | ||
1917 | unix_state_lock(sk); | 1920 | unix_state_lock(sk); |
1918 | skb = skb_dequeue(&sk->sk_receive_queue); | 1921 | skb = skb_peek(&sk->sk_receive_queue); |
1919 | if (skb == NULL) { | 1922 | if (skb == NULL) { |
1920 | unix_sk(sk)->recursion_level = 0; | 1923 | unix_sk(sk)->recursion_level = 0; |
1921 | if (copied >= target) | 1924 | if (copied >= target) |
@@ -1955,11 +1958,8 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1955 | if (check_creds) { | 1958 | if (check_creds) { |
1956 | /* Never glue messages from different writers */ | 1959 | /* Never glue messages from different writers */ |
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); | ||
1960 | sk->sk_data_ready(sk, skb->len); | ||
1961 | break; | 1962 | break; |
1962 | } | ||
1963 | } else { | 1963 | } else { |
1964 | /* Copy credentials */ | 1964 | /* Copy credentials */ |
1965 | scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).cred); | 1965 | scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).cred); |
@@ -1974,8 +1974,6 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1974 | 1974 | ||
1975 | chunk = min_t(unsigned int, skb->len, size); | 1975 | chunk = min_t(unsigned int, skb->len, size); |
1976 | if (memcpy_toiovec(msg->msg_iov, skb->data, chunk)) { | 1976 | if (memcpy_toiovec(msg->msg_iov, skb->data, chunk)) { |
1977 | skb_queue_head(&sk->sk_receive_queue, skb); | ||
1978 | sk->sk_data_ready(sk, skb->len); | ||
1979 | if (copied == 0) | 1977 | if (copied == 0) |
1980 | copied = -EFAULT; | 1978 | copied = -EFAULT; |
1981 | break; | 1979 | break; |
@@ -1990,13 +1988,10 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1990 | if (UNIXCB(skb).fp) | 1988 | if (UNIXCB(skb).fp) |
1991 | unix_detach_fds(siocb->scm, skb); | 1989 | unix_detach_fds(siocb->scm, skb); |
1992 | 1990 | ||
1993 | /* put the skb back if we didn't use it up.. */ | 1991 | if (skb->len) |
1994 | if (skb->len) { | ||
1995 | skb_queue_head(&sk->sk_receive_queue, skb); | ||
1996 | sk->sk_data_ready(sk, skb->len); | ||
1997 | break; | 1992 | break; |
1998 | } | ||
1999 | 1993 | ||
1994 | skb_unlink(skb, &sk->sk_receive_queue); | ||
2000 | consume_skb(skb); | 1995 | consume_skb(skb); |
2001 | 1996 | ||
2002 | if (siocb->scm->fp) | 1997 | if (siocb->scm->fp) |
@@ -2007,9 +2002,6 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
2007 | if (UNIXCB(skb).fp) | 2002 | if (UNIXCB(skb).fp) |
2008 | siocb->scm->fp = scm_fp_dup(UNIXCB(skb).fp); | 2003 | siocb->scm->fp = scm_fp_dup(UNIXCB(skb).fp); |
2009 | 2004 | ||
2010 | /* put message back and return */ | ||
2011 | skb_queue_head(&sk->sk_receive_queue, skb); | ||
2012 | sk->sk_data_ready(sk, skb->len); | ||
2013 | break; | 2005 | break; |
2014 | } | 2006 | } |
2015 | } while (size); | 2007 | } while (size); |
@@ -2062,6 +2054,36 @@ static int unix_shutdown(struct socket *sock, int mode) | |||
2062 | return 0; | 2054 | return 0; |
2063 | } | 2055 | } |
2064 | 2056 | ||
2057 | long unix_inq_len(struct sock *sk) | ||
2058 | { | ||
2059 | struct sk_buff *skb; | ||
2060 | long amount = 0; | ||
2061 | |||
2062 | if (sk->sk_state == TCP_LISTEN) | ||
2063 | return -EINVAL; | ||
2064 | |||
2065 | spin_lock(&sk->sk_receive_queue.lock); | ||
2066 | if (sk->sk_type == SOCK_STREAM || | ||
2067 | sk->sk_type == SOCK_SEQPACKET) { | ||
2068 | skb_queue_walk(&sk->sk_receive_queue, skb) | ||
2069 | amount += skb->len; | ||
2070 | } else { | ||
2071 | skb = skb_peek(&sk->sk_receive_queue); | ||
2072 | if (skb) | ||
2073 | amount = skb->len; | ||
2074 | } | ||
2075 | spin_unlock(&sk->sk_receive_queue.lock); | ||
2076 | |||
2077 | return amount; | ||
2078 | } | ||
2079 | EXPORT_SYMBOL_GPL(unix_inq_len); | ||
2080 | |||
2081 | long unix_outq_len(struct sock *sk) | ||
2082 | { | ||
2083 | return sk_wmem_alloc_get(sk); | ||
2084 | } | ||
2085 | EXPORT_SYMBOL_GPL(unix_outq_len); | ||
2086 | |||
2065 | static int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | 2087 | static int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) |
2066 | { | 2088 | { |
2067 | struct sock *sk = sock->sk; | 2089 | struct sock *sk = sock->sk; |
@@ -2070,33 +2092,16 @@ static int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
2070 | 2092 | ||
2071 | switch (cmd) { | 2093 | switch (cmd) { |
2072 | case SIOCOUTQ: | 2094 | case SIOCOUTQ: |
2073 | amount = sk_wmem_alloc_get(sk); | 2095 | amount = unix_outq_len(sk); |
2074 | err = put_user(amount, (int __user *)arg); | 2096 | err = put_user(amount, (int __user *)arg); |
2075 | break; | 2097 | break; |
2076 | case SIOCINQ: | 2098 | case SIOCINQ: |
2077 | { | 2099 | amount = unix_inq_len(sk); |
2078 | struct sk_buff *skb; | 2100 | if (amount < 0) |
2079 | 2101 | err = amount; | |
2080 | if (sk->sk_state == TCP_LISTEN) { | 2102 | else |
2081 | err = -EINVAL; | ||
2082 | break; | ||
2083 | } | ||
2084 | |||
2085 | spin_lock(&sk->sk_receive_queue.lock); | ||
2086 | if (sk->sk_type == SOCK_STREAM || | ||
2087 | sk->sk_type == SOCK_SEQPACKET) { | ||
2088 | skb_queue_walk(&sk->sk_receive_queue, skb) | ||
2089 | amount += skb->len; | ||
2090 | } else { | ||
2091 | skb = skb_peek(&sk->sk_receive_queue); | ||
2092 | if (skb) | ||
2093 | amount = skb->len; | ||
2094 | } | ||
2095 | spin_unlock(&sk->sk_receive_queue.lock); | ||
2096 | err = put_user(amount, (int __user *)arg); | 2103 | err = put_user(amount, (int __user *)arg); |
2097 | break; | 2104 | break; |
2098 | } | ||
2099 | |||
2100 | default: | 2105 | default: |
2101 | err = -ENOIOCTLCMD; | 2106 | err = -ENOIOCTLCMD; |
2102 | break; | 2107 | break; |