diff options
author | Len Brown <len.brown@intel.com> | 2012-04-06 21:48:59 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2012-04-06 21:48:59 -0400 |
commit | eeaab2d8af2cf1d36d7086f22e9de42d6dd2995c (patch) | |
tree | 369b9c91a6d808944f07d2290fec6f9fe2731904 /net/unix | |
parent | ee01e663373343c63e0e3d364d09f6155378dbcc (diff) | |
parent | aaef292acf3a78d9c0bb6fb72226077d286b45d7 (diff) |
Merge branches 'idle-fix' and 'misc' into release
Diffstat (limited to 'net/unix')
-rw-r--r-- | net/unix/af_unix.c | 91 | ||||
-rw-r--r-- | net/unix/diag.c | 12 |
2 files changed, 68 insertions, 35 deletions
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 85d3bb7490aa..d510353ef431 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
@@ -293,7 +293,7 @@ static struct sock *unix_find_socket_byinode(struct inode *i) | |||
293 | spin_lock(&unix_table_lock); | 293 | spin_lock(&unix_table_lock); |
294 | sk_for_each(s, node, | 294 | sk_for_each(s, node, |
295 | &unix_socket_table[i->i_ino & (UNIX_HASH_SIZE - 1)]) { | 295 | &unix_socket_table[i->i_ino & (UNIX_HASH_SIZE - 1)]) { |
296 | struct dentry *dentry = unix_sk(s)->dentry; | 296 | struct dentry *dentry = unix_sk(s)->path.dentry; |
297 | 297 | ||
298 | if (dentry && dentry->d_inode == i) { | 298 | if (dentry && dentry->d_inode == i) { |
299 | sock_hold(s); | 299 | sock_hold(s); |
@@ -377,8 +377,7 @@ static void unix_sock_destructor(struct sock *sk) | |||
377 | static int unix_release_sock(struct sock *sk, int embrion) | 377 | static int unix_release_sock(struct sock *sk, int embrion) |
378 | { | 378 | { |
379 | struct unix_sock *u = unix_sk(sk); | 379 | struct unix_sock *u = unix_sk(sk); |
380 | struct dentry *dentry; | 380 | struct path path; |
381 | struct vfsmount *mnt; | ||
382 | struct sock *skpair; | 381 | struct sock *skpair; |
383 | struct sk_buff *skb; | 382 | struct sk_buff *skb; |
384 | int state; | 383 | int state; |
@@ -389,10 +388,9 @@ static int unix_release_sock(struct sock *sk, int embrion) | |||
389 | unix_state_lock(sk); | 388 | unix_state_lock(sk); |
390 | sock_orphan(sk); | 389 | sock_orphan(sk); |
391 | sk->sk_shutdown = SHUTDOWN_MASK; | 390 | sk->sk_shutdown = SHUTDOWN_MASK; |
392 | dentry = u->dentry; | 391 | path = u->path; |
393 | u->dentry = NULL; | 392 | u->path.dentry = NULL; |
394 | mnt = u->mnt; | 393 | u->path.mnt = NULL; |
395 | u->mnt = NULL; | ||
396 | state = sk->sk_state; | 394 | state = sk->sk_state; |
397 | sk->sk_state = TCP_CLOSE; | 395 | sk->sk_state = TCP_CLOSE; |
398 | unix_state_unlock(sk); | 396 | unix_state_unlock(sk); |
@@ -425,10 +423,8 @@ static int unix_release_sock(struct sock *sk, int embrion) | |||
425 | kfree_skb(skb); | 423 | kfree_skb(skb); |
426 | } | 424 | } |
427 | 425 | ||
428 | if (dentry) { | 426 | if (path.dentry) |
429 | dput(dentry); | 427 | path_put(&path); |
430 | mntput(mnt); | ||
431 | } | ||
432 | 428 | ||
433 | sock_put(sk); | 429 | sock_put(sk); |
434 | 430 | ||
@@ -530,6 +526,16 @@ static int unix_seqpacket_sendmsg(struct kiocb *, struct socket *, | |||
530 | static int unix_seqpacket_recvmsg(struct kiocb *, struct socket *, | 526 | static int unix_seqpacket_recvmsg(struct kiocb *, struct socket *, |
531 | struct msghdr *, size_t, int); | 527 | struct msghdr *, size_t, int); |
532 | 528 | ||
529 | static void unix_set_peek_off(struct sock *sk, int val) | ||
530 | { | ||
531 | struct unix_sock *u = unix_sk(sk); | ||
532 | |||
533 | mutex_lock(&u->readlock); | ||
534 | sk->sk_peek_off = val; | ||
535 | mutex_unlock(&u->readlock); | ||
536 | } | ||
537 | |||
538 | |||
533 | static const struct proto_ops unix_stream_ops = { | 539 | static const struct proto_ops unix_stream_ops = { |
534 | .family = PF_UNIX, | 540 | .family = PF_UNIX, |
535 | .owner = THIS_MODULE, | 541 | .owner = THIS_MODULE, |
@@ -549,6 +555,7 @@ static const struct proto_ops unix_stream_ops = { | |||
549 | .recvmsg = unix_stream_recvmsg, | 555 | .recvmsg = unix_stream_recvmsg, |
550 | .mmap = sock_no_mmap, | 556 | .mmap = sock_no_mmap, |
551 | .sendpage = sock_no_sendpage, | 557 | .sendpage = sock_no_sendpage, |
558 | .set_peek_off = unix_set_peek_off, | ||
552 | }; | 559 | }; |
553 | 560 | ||
554 | static const struct proto_ops unix_dgram_ops = { | 561 | static const struct proto_ops unix_dgram_ops = { |
@@ -570,6 +577,7 @@ static const struct proto_ops unix_dgram_ops = { | |||
570 | .recvmsg = unix_dgram_recvmsg, | 577 | .recvmsg = unix_dgram_recvmsg, |
571 | .mmap = sock_no_mmap, | 578 | .mmap = sock_no_mmap, |
572 | .sendpage = sock_no_sendpage, | 579 | .sendpage = sock_no_sendpage, |
580 | .set_peek_off = unix_set_peek_off, | ||
573 | }; | 581 | }; |
574 | 582 | ||
575 | static const struct proto_ops unix_seqpacket_ops = { | 583 | static const struct proto_ops unix_seqpacket_ops = { |
@@ -591,6 +599,7 @@ static const struct proto_ops unix_seqpacket_ops = { | |||
591 | .recvmsg = unix_seqpacket_recvmsg, | 599 | .recvmsg = unix_seqpacket_recvmsg, |
592 | .mmap = sock_no_mmap, | 600 | .mmap = sock_no_mmap, |
593 | .sendpage = sock_no_sendpage, | 601 | .sendpage = sock_no_sendpage, |
602 | .set_peek_off = unix_set_peek_off, | ||
594 | }; | 603 | }; |
595 | 604 | ||
596 | static struct proto unix_proto = { | 605 | static struct proto unix_proto = { |
@@ -628,8 +637,8 @@ static struct sock *unix_create1(struct net *net, struct socket *sock) | |||
628 | sk->sk_max_ack_backlog = net->unx.sysctl_max_dgram_qlen; | 637 | sk->sk_max_ack_backlog = net->unx.sysctl_max_dgram_qlen; |
629 | sk->sk_destruct = unix_sock_destructor; | 638 | sk->sk_destruct = unix_sock_destructor; |
630 | u = unix_sk(sk); | 639 | u = unix_sk(sk); |
631 | u->dentry = NULL; | 640 | u->path.dentry = NULL; |
632 | u->mnt = NULL; | 641 | u->path.mnt = NULL; |
633 | spin_lock_init(&u->lock); | 642 | spin_lock_init(&u->lock); |
634 | atomic_long_set(&u->inflight, 0); | 643 | atomic_long_set(&u->inflight, 0); |
635 | INIT_LIST_HEAD(&u->link); | 644 | INIT_LIST_HEAD(&u->link); |
@@ -775,7 +784,7 @@ static struct sock *unix_find_other(struct net *net, | |||
775 | goto put_fail; | 784 | goto put_fail; |
776 | 785 | ||
777 | if (u->sk_type == type) | 786 | if (u->sk_type == type) |
778 | touch_atime(path.mnt, path.dentry); | 787 | touch_atime(&path); |
779 | 788 | ||
780 | path_put(&path); | 789 | path_put(&path); |
781 | 790 | ||
@@ -789,9 +798,9 @@ static struct sock *unix_find_other(struct net *net, | |||
789 | u = unix_find_socket_byname(net, sunname, len, type, hash); | 798 | u = unix_find_socket_byname(net, sunname, len, type, hash); |
790 | if (u) { | 799 | if (u) { |
791 | struct dentry *dentry; | 800 | struct dentry *dentry; |
792 | dentry = unix_sk(u)->dentry; | 801 | dentry = unix_sk(u)->path.dentry; |
793 | if (dentry) | 802 | if (dentry) |
794 | touch_atime(unix_sk(u)->mnt, dentry); | 803 | touch_atime(&unix_sk(u)->path); |
795 | } else | 804 | } else |
796 | goto fail; | 805 | goto fail; |
797 | } | 806 | } |
@@ -897,8 +906,7 @@ out_mknod_drop_write: | |||
897 | list = &unix_socket_table[addr->hash]; | 906 | list = &unix_socket_table[addr->hash]; |
898 | } else { | 907 | } else { |
899 | list = &unix_socket_table[dentry->d_inode->i_ino & (UNIX_HASH_SIZE-1)]; | 908 | list = &unix_socket_table[dentry->d_inode->i_ino & (UNIX_HASH_SIZE-1)]; |
900 | u->dentry = path.dentry; | 909 | u->path = path; |
901 | u->mnt = path.mnt; | ||
902 | } | 910 | } |
903 | 911 | ||
904 | err = 0; | 912 | err = 0; |
@@ -1180,9 +1188,9 @@ restart: | |||
1180 | atomic_inc(&otheru->addr->refcnt); | 1188 | atomic_inc(&otheru->addr->refcnt); |
1181 | newu->addr = otheru->addr; | 1189 | newu->addr = otheru->addr; |
1182 | } | 1190 | } |
1183 | if (otheru->dentry) { | 1191 | if (otheru->path.dentry) { |
1184 | newu->dentry = dget(otheru->dentry); | 1192 | path_get(&otheru->path); |
1185 | newu->mnt = mntget(otheru->mnt); | 1193 | newu->path = otheru->path; |
1186 | } | 1194 | } |
1187 | 1195 | ||
1188 | /* Set credentials */ | 1196 | /* Set credentials */ |
@@ -1756,6 +1764,7 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1756 | int noblock = flags & MSG_DONTWAIT; | 1764 | int noblock = flags & MSG_DONTWAIT; |
1757 | struct sk_buff *skb; | 1765 | struct sk_buff *skb; |
1758 | int err; | 1766 | int err; |
1767 | int peeked, skip; | ||
1759 | 1768 | ||
1760 | err = -EOPNOTSUPP; | 1769 | err = -EOPNOTSUPP; |
1761 | if (flags&MSG_OOB) | 1770 | if (flags&MSG_OOB) |
@@ -1769,7 +1778,9 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1769 | goto out; | 1778 | goto out; |
1770 | } | 1779 | } |
1771 | 1780 | ||
1772 | skb = skb_recv_datagram(sk, flags, noblock, &err); | 1781 | skip = sk_peek_offset(sk, flags); |
1782 | |||
1783 | skb = __skb_recv_datagram(sk, flags, &peeked, &skip, &err); | ||
1773 | if (!skb) { | 1784 | if (!skb) { |
1774 | unix_state_lock(sk); | 1785 | unix_state_lock(sk); |
1775 | /* Signal EOF on disconnected non-blocking SEQPACKET socket. */ | 1786 | /* Signal EOF on disconnected non-blocking SEQPACKET socket. */ |
@@ -1786,12 +1797,12 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1786 | if (msg->msg_name) | 1797 | if (msg->msg_name) |
1787 | unix_copy_addr(msg, skb->sk); | 1798 | unix_copy_addr(msg, skb->sk); |
1788 | 1799 | ||
1789 | if (size > skb->len) | 1800 | if (size > skb->len - skip) |
1790 | size = skb->len; | 1801 | size = skb->len - skip; |
1791 | else if (size < skb->len) | 1802 | else if (size < skb->len - skip) |
1792 | msg->msg_flags |= MSG_TRUNC; | 1803 | msg->msg_flags |= MSG_TRUNC; |
1793 | 1804 | ||
1794 | err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, size); | 1805 | err = skb_copy_datagram_iovec(skb, skip, msg->msg_iov, size); |
1795 | if (err) | 1806 | if (err) |
1796 | goto out_free; | 1807 | goto out_free; |
1797 | 1808 | ||
@@ -1808,6 +1819,8 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1808 | if (!(flags & MSG_PEEK)) { | 1819 | if (!(flags & MSG_PEEK)) { |
1809 | if (UNIXCB(skb).fp) | 1820 | if (UNIXCB(skb).fp) |
1810 | unix_detach_fds(siocb->scm, skb); | 1821 | unix_detach_fds(siocb->scm, skb); |
1822 | |||
1823 | sk_peek_offset_bwd(sk, skb->len); | ||
1811 | } else { | 1824 | } else { |
1812 | /* It is questionable: on PEEK we could: | 1825 | /* It is questionable: on PEEK we could: |
1813 | - do not return fds - good, but too simple 8) | 1826 | - do not return fds - good, but too simple 8) |
@@ -1821,10 +1834,13 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1821 | clearly however! | 1834 | clearly however! |
1822 | 1835 | ||
1823 | */ | 1836 | */ |
1837 | |||
1838 | sk_peek_offset_fwd(sk, size); | ||
1839 | |||
1824 | if (UNIXCB(skb).fp) | 1840 | if (UNIXCB(skb).fp) |
1825 | siocb->scm->fp = scm_fp_dup(UNIXCB(skb).fp); | 1841 | siocb->scm->fp = scm_fp_dup(UNIXCB(skb).fp); |
1826 | } | 1842 | } |
1827 | err = size; | 1843 | err = (flags & MSG_TRUNC) ? skb->len - skip : size; |
1828 | 1844 | ||
1829 | scm_recv(sock, msg, siocb->scm, flags); | 1845 | scm_recv(sock, msg, siocb->scm, flags); |
1830 | 1846 | ||
@@ -1884,6 +1900,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1884 | int target; | 1900 | int target; |
1885 | int err = 0; | 1901 | int err = 0; |
1886 | long timeo; | 1902 | long timeo; |
1903 | int skip; | ||
1887 | 1904 | ||
1888 | err = -EINVAL; | 1905 | err = -EINVAL; |
1889 | if (sk->sk_state != TCP_ESTABLISHED) | 1906 | if (sk->sk_state != TCP_ESTABLISHED) |
@@ -1913,12 +1930,15 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1913 | goto out; | 1930 | goto out; |
1914 | } | 1931 | } |
1915 | 1932 | ||
1933 | skip = sk_peek_offset(sk, flags); | ||
1934 | |||
1916 | do { | 1935 | do { |
1917 | int chunk; | 1936 | int chunk; |
1918 | struct sk_buff *skb; | 1937 | struct sk_buff *skb; |
1919 | 1938 | ||
1920 | unix_state_lock(sk); | 1939 | unix_state_lock(sk); |
1921 | skb = skb_peek(&sk->sk_receive_queue); | 1940 | skb = skb_peek(&sk->sk_receive_queue); |
1941 | again: | ||
1922 | if (skb == NULL) { | 1942 | if (skb == NULL) { |
1923 | unix_sk(sk)->recursion_level = 0; | 1943 | unix_sk(sk)->recursion_level = 0; |
1924 | if (copied >= target) | 1944 | if (copied >= target) |
@@ -1953,6 +1973,13 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1953 | unix_state_unlock(sk); | 1973 | unix_state_unlock(sk); |
1954 | break; | 1974 | break; |
1955 | } | 1975 | } |
1976 | |||
1977 | if (skip >= skb->len) { | ||
1978 | skip -= skb->len; | ||
1979 | skb = skb_peek_next(skb, &sk->sk_receive_queue); | ||
1980 | goto again; | ||
1981 | } | ||
1982 | |||
1956 | unix_state_unlock(sk); | 1983 | unix_state_unlock(sk); |
1957 | 1984 | ||
1958 | if (check_creds) { | 1985 | if (check_creds) { |
@@ -1972,8 +1999,8 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1972 | sunaddr = NULL; | 1999 | sunaddr = NULL; |
1973 | } | 2000 | } |
1974 | 2001 | ||
1975 | chunk = min_t(unsigned int, skb->len, size); | 2002 | chunk = min_t(unsigned int, skb->len - skip, size); |
1976 | if (memcpy_toiovec(msg->msg_iov, skb->data, chunk)) { | 2003 | if (memcpy_toiovec(msg->msg_iov, skb->data + skip, chunk)) { |
1977 | if (copied == 0) | 2004 | if (copied == 0) |
1978 | copied = -EFAULT; | 2005 | copied = -EFAULT; |
1979 | break; | 2006 | break; |
@@ -1985,6 +2012,8 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1985 | if (!(flags & MSG_PEEK)) { | 2012 | if (!(flags & MSG_PEEK)) { |
1986 | skb_pull(skb, chunk); | 2013 | skb_pull(skb, chunk); |
1987 | 2014 | ||
2015 | sk_peek_offset_bwd(sk, chunk); | ||
2016 | |||
1988 | if (UNIXCB(skb).fp) | 2017 | if (UNIXCB(skb).fp) |
1989 | unix_detach_fds(siocb->scm, skb); | 2018 | unix_detach_fds(siocb->scm, skb); |
1990 | 2019 | ||
@@ -2002,6 +2031,8 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
2002 | if (UNIXCB(skb).fp) | 2031 | if (UNIXCB(skb).fp) |
2003 | siocb->scm->fp = scm_fp_dup(UNIXCB(skb).fp); | 2032 | siocb->scm->fp = scm_fp_dup(UNIXCB(skb).fp); |
2004 | 2033 | ||
2034 | sk_peek_offset_fwd(sk, chunk); | ||
2035 | |||
2005 | break; | 2036 | break; |
2006 | } | 2037 | } |
2007 | } while (size); | 2038 | } while (size); |
@@ -2175,7 +2206,7 @@ static unsigned int unix_dgram_poll(struct file *file, struct socket *sock, | |||
2175 | } | 2206 | } |
2176 | 2207 | ||
2177 | /* No write status requested, avoid expensive OUT tests. */ | 2208 | /* No write status requested, avoid expensive OUT tests. */ |
2178 | if (wait && !(wait->key & (POLLWRBAND | POLLWRNORM | POLLOUT))) | 2209 | if (!(poll_requested_events(wait) & (POLLWRBAND|POLLWRNORM|POLLOUT))) |
2179 | return mask; | 2210 | return mask; |
2180 | 2211 | ||
2181 | writable = unix_writable(sk); | 2212 | writable = unix_writable(sk); |
diff --git a/net/unix/diag.c b/net/unix/diag.c index 6b7697fd911b..f0486ae9ebe6 100644 --- a/net/unix/diag.c +++ b/net/unix/diag.c | |||
@@ -29,7 +29,7 @@ rtattr_failure: | |||
29 | 29 | ||
30 | static int sk_diag_dump_vfs(struct sock *sk, struct sk_buff *nlskb) | 30 | static int sk_diag_dump_vfs(struct sock *sk, struct sk_buff *nlskb) |
31 | { | 31 | { |
32 | struct dentry *dentry = unix_sk(sk)->dentry; | 32 | struct dentry *dentry = unix_sk(sk)->path.dentry; |
33 | struct unix_diag_vfs *uv; | 33 | struct unix_diag_vfs *uv; |
34 | 34 | ||
35 | if (dentry) { | 35 | if (dentry) { |
@@ -301,10 +301,12 @@ static int unix_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h) | |||
301 | if (nlmsg_len(h) < hdrlen) | 301 | if (nlmsg_len(h) < hdrlen) |
302 | return -EINVAL; | 302 | return -EINVAL; |
303 | 303 | ||
304 | if (h->nlmsg_flags & NLM_F_DUMP) | 304 | if (h->nlmsg_flags & NLM_F_DUMP) { |
305 | return netlink_dump_start(sock_diag_nlsk, skb, h, | 305 | struct netlink_dump_control c = { |
306 | unix_diag_dump, NULL, 0); | 306 | .dump = unix_diag_dump, |
307 | else | 307 | }; |
308 | return netlink_dump_start(sock_diag_nlsk, skb, h, &c); | ||
309 | } else | ||
308 | return unix_diag_get_exact(skb, h, (struct unix_diag_req *)NLMSG_DATA(h)); | 310 | return unix_diag_get_exact(skb, h, (struct unix_diag_req *)NLMSG_DATA(h)); |
309 | } | 311 | } |
310 | 312 | ||