diff options
Diffstat (limited to 'net/socket.c')
-rw-r--r-- | net/socket.c | 101 |
1 files changed, 74 insertions, 27 deletions
diff --git a/net/socket.c b/net/socket.c index 35dd7371752a..791d71a36a93 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -328,7 +328,7 @@ static char *sockfs_dname(struct dentry *dentry, char *buffer, int buflen) | |||
328 | dentry->d_inode->i_ino); | 328 | dentry->d_inode->i_ino); |
329 | } | 329 | } |
330 | 330 | ||
331 | static struct dentry_operations sockfs_dentry_operations = { | 331 | static const struct dentry_operations sockfs_dentry_operations = { |
332 | .d_delete = sockfs_delete_dentry, | 332 | .d_delete = sockfs_delete_dentry, |
333 | .d_dname = sockfs_dname, | 333 | .d_dname = sockfs_dname, |
334 | }; | 334 | }; |
@@ -493,8 +493,7 @@ static struct socket *sock_alloc(void) | |||
493 | inode->i_uid = current_fsuid(); | 493 | inode->i_uid = current_fsuid(); |
494 | inode->i_gid = current_fsgid(); | 494 | inode->i_gid = current_fsgid(); |
495 | 495 | ||
496 | get_cpu_var(sockets_in_use)++; | 496 | percpu_add(sockets_in_use, 1); |
497 | put_cpu_var(sockets_in_use); | ||
498 | return sock; | 497 | return sock; |
499 | } | 498 | } |
500 | 499 | ||
@@ -536,8 +535,7 @@ void sock_release(struct socket *sock) | |||
536 | if (sock->fasync_list) | 535 | if (sock->fasync_list) |
537 | printk(KERN_ERR "sock_release: fasync list not empty!\n"); | 536 | printk(KERN_ERR "sock_release: fasync list not empty!\n"); |
538 | 537 | ||
539 | get_cpu_var(sockets_in_use)--; | 538 | percpu_sub(sockets_in_use, 1); |
540 | put_cpu_var(sockets_in_use); | ||
541 | if (!sock->file) { | 539 | if (!sock->file) { |
542 | iput(SOCK_INODE(sock)); | 540 | iput(SOCK_INODE(sock)); |
543 | return; | 541 | return; |
@@ -545,6 +543,18 @@ void sock_release(struct socket *sock) | |||
545 | sock->file = NULL; | 543 | sock->file = NULL; |
546 | } | 544 | } |
547 | 545 | ||
546 | int sock_tx_timestamp(struct msghdr *msg, struct sock *sk, | ||
547 | union skb_shared_tx *shtx) | ||
548 | { | ||
549 | shtx->flags = 0; | ||
550 | if (sock_flag(sk, SOCK_TIMESTAMPING_TX_HARDWARE)) | ||
551 | shtx->hardware = 1; | ||
552 | if (sock_flag(sk, SOCK_TIMESTAMPING_TX_SOFTWARE)) | ||
553 | shtx->software = 1; | ||
554 | return 0; | ||
555 | } | ||
556 | EXPORT_SYMBOL(sock_tx_timestamp); | ||
557 | |||
548 | static inline int __sock_sendmsg(struct kiocb *iocb, struct socket *sock, | 558 | static inline int __sock_sendmsg(struct kiocb *iocb, struct socket *sock, |
549 | struct msghdr *msg, size_t size) | 559 | struct msghdr *msg, size_t size) |
550 | { | 560 | { |
@@ -595,33 +605,65 @@ int kernel_sendmsg(struct socket *sock, struct msghdr *msg, | |||
595 | return result; | 605 | return result; |
596 | } | 606 | } |
597 | 607 | ||
608 | static int ktime2ts(ktime_t kt, struct timespec *ts) | ||
609 | { | ||
610 | if (kt.tv64) { | ||
611 | *ts = ktime_to_timespec(kt); | ||
612 | return 1; | ||
613 | } else { | ||
614 | return 0; | ||
615 | } | ||
616 | } | ||
617 | |||
598 | /* | 618 | /* |
599 | * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP) | 619 | * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP) |
600 | */ | 620 | */ |
601 | void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk, | 621 | void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk, |
602 | struct sk_buff *skb) | 622 | struct sk_buff *skb) |
603 | { | 623 | { |
604 | ktime_t kt = skb->tstamp; | 624 | int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP); |
605 | 625 | struct timespec ts[3]; | |
606 | if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) { | 626 | int empty = 1; |
607 | struct timeval tv; | 627 | struct skb_shared_hwtstamps *shhwtstamps = |
608 | /* Race occurred between timestamp enabling and packet | 628 | skb_hwtstamps(skb); |
609 | receiving. Fill in the current time for now. */ | 629 | |
610 | if (kt.tv64 == 0) | 630 | /* Race occurred between timestamp enabling and packet |
611 | kt = ktime_get_real(); | 631 | receiving. Fill in the current time for now. */ |
612 | skb->tstamp = kt; | 632 | if (need_software_tstamp && skb->tstamp.tv64 == 0) |
613 | tv = ktime_to_timeval(kt); | 633 | __net_timestamp(skb); |
614 | put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP, sizeof(tv), &tv); | 634 | |
615 | } else { | 635 | if (need_software_tstamp) { |
616 | struct timespec ts; | 636 | if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) { |
617 | /* Race occurred between timestamp enabling and packet | 637 | struct timeval tv; |
618 | receiving. Fill in the current time for now. */ | 638 | skb_get_timestamp(skb, &tv); |
619 | if (kt.tv64 == 0) | 639 | put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP, |
620 | kt = ktime_get_real(); | 640 | sizeof(tv), &tv); |
621 | skb->tstamp = kt; | 641 | } else { |
622 | ts = ktime_to_timespec(kt); | 642 | struct timespec ts; |
623 | put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS, sizeof(ts), &ts); | 643 | skb_get_timestampns(skb, &ts); |
644 | put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS, | ||
645 | sizeof(ts), &ts); | ||
646 | } | ||
647 | } | ||
648 | |||
649 | |||
650 | memset(ts, 0, sizeof(ts)); | ||
651 | if (skb->tstamp.tv64 && | ||
652 | sock_flag(sk, SOCK_TIMESTAMPING_SOFTWARE)) { | ||
653 | skb_get_timestampns(skb, ts + 0); | ||
654 | empty = 0; | ||
624 | } | 655 | } |
656 | if (shhwtstamps) { | ||
657 | if (sock_flag(sk, SOCK_TIMESTAMPING_SYS_HARDWARE) && | ||
658 | ktime2ts(shhwtstamps->syststamp, ts + 1)) | ||
659 | empty = 0; | ||
660 | if (sock_flag(sk, SOCK_TIMESTAMPING_RAW_HARDWARE) && | ||
661 | ktime2ts(shhwtstamps->hwtstamp, ts + 2)) | ||
662 | empty = 0; | ||
663 | } | ||
664 | if (!empty) | ||
665 | put_cmsg(msg, SOL_SOCKET, | ||
666 | SCM_TIMESTAMPING, sizeof(ts), &ts); | ||
625 | } | 667 | } |
626 | 668 | ||
627 | EXPORT_SYMBOL_GPL(__sock_recv_timestamp); | 669 | EXPORT_SYMBOL_GPL(__sock_recv_timestamp); |
@@ -1030,6 +1072,13 @@ static int sock_fasync(int fd, struct file *filp, int on) | |||
1030 | 1072 | ||
1031 | lock_sock(sk); | 1073 | lock_sock(sk); |
1032 | 1074 | ||
1075 | spin_lock(&filp->f_lock); | ||
1076 | if (on) | ||
1077 | filp->f_flags |= FASYNC; | ||
1078 | else | ||
1079 | filp->f_flags &= ~FASYNC; | ||
1080 | spin_unlock(&filp->f_lock); | ||
1081 | |||
1033 | prev = &(sock->fasync_list); | 1082 | prev = &(sock->fasync_list); |
1034 | 1083 | ||
1035 | for (fa = *prev; fa != NULL; prev = &fa->fa_next, fa = *prev) | 1084 | for (fa = *prev; fa != NULL; prev = &fa->fa_next, fa = *prev) |
@@ -1485,8 +1534,6 @@ SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr, | |||
1485 | fd_install(newfd, newfile); | 1534 | fd_install(newfd, newfile); |
1486 | err = newfd; | 1535 | err = newfd; |
1487 | 1536 | ||
1488 | security_socket_post_accept(sock, newsock); | ||
1489 | |||
1490 | out_put: | 1537 | out_put: |
1491 | fput_light(sock->file, fput_needed); | 1538 | fput_light(sock->file, fput_needed); |
1492 | out: | 1539 | out: |