diff options
author | Eric Dumazet <dada1@cosmosbay.com> | 2007-03-18 20:33:16 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-04-26 01:24:04 -0400 |
commit | ae40eb1ef30ab4120bd3c8b7e3da99ee53d27a23 (patch) | |
tree | b5ae288b3c27d13bde9648c41d7db3cfe1884bc2 /net | |
parent | cb69cc52364690d7789940c480b3a9490784b680 (diff) |
[NET]: Introduce SIOCGSTAMPNS ioctl to get timestamps with nanosec resolution
Now network timestamps use ktime_t infrastructure, we can add a new
ioctl() SIOCGSTAMPNS command to get timestamps in 'struct timespec'.
User programs can thus access to nanosecond resolution.
Signed-off-by: Eric Dumazet <dada1@cosmosbay.com>
CC: Stephen Hemminger <shemminger@linux-foundation.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/appletalk/ddp.c | 3 | ||||
-rw-r--r-- | net/atm/ioctl.c | 3 | ||||
-rw-r--r-- | net/ax25/af_ax25.c | 4 | ||||
-rw-r--r-- | net/compat.c | 24 | ||||
-rw-r--r-- | net/core/sock.c | 16 | ||||
-rw-r--r-- | net/econet/af_econet.c | 3 | ||||
-rw-r--r-- | net/ipv4/af_inet.c | 3 | ||||
-rw-r--r-- | net/ipv6/af_inet6.c | 3 | ||||
-rw-r--r-- | net/netrom/af_netrom.c | 6 | ||||
-rw-r--r-- | net/packet/af_packet.c | 2 | ||||
-rw-r--r-- | net/rose/af_rose.c | 3 | ||||
-rw-r--r-- | net/x25/af_x25.c | 12 |
12 files changed, 82 insertions, 0 deletions
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index c8b7dc2c3257..32b82705b685 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c | |||
@@ -1771,6 +1771,9 @@ static int atalk_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1771 | case SIOCGSTAMP: | 1771 | case SIOCGSTAMP: |
1772 | rc = sock_get_timestamp(sk, argp); | 1772 | rc = sock_get_timestamp(sk, argp); |
1773 | break; | 1773 | break; |
1774 | case SIOCGSTAMPNS: | ||
1775 | rc = sock_get_timestampns(sk, argp); | ||
1776 | break; | ||
1774 | /* Routing */ | 1777 | /* Routing */ |
1775 | case SIOCADDRT: | 1778 | case SIOCADDRT: |
1776 | case SIOCDELRT: | 1779 | case SIOCDELRT: |
diff --git a/net/atm/ioctl.c b/net/atm/ioctl.c index 8ccee4591f65..7afd8e7754fd 100644 --- a/net/atm/ioctl.c +++ b/net/atm/ioctl.c | |||
@@ -82,6 +82,9 @@ int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
82 | case SIOCGSTAMP: /* borrowed from IP */ | 82 | case SIOCGSTAMP: /* borrowed from IP */ |
83 | error = sock_get_timestamp(sk, argp); | 83 | error = sock_get_timestamp(sk, argp); |
84 | goto done; | 84 | goto done; |
85 | case SIOCGSTAMPNS: /* borrowed from IP */ | ||
86 | error = sock_get_timestampns(sk, argp); | ||
87 | goto done; | ||
85 | case ATM_SETSC: | 88 | case ATM_SETSC: |
86 | printk(KERN_WARNING "ATM_SETSC is obsolete\n"); | 89 | printk(KERN_WARNING "ATM_SETSC is obsolete\n"); |
87 | error = 0; | 90 | error = 0; |
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index 1c07c6a50eb8..62605dc5a2c8 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c | |||
@@ -1711,6 +1711,10 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1711 | res = sock_get_timestamp(sk, argp); | 1711 | res = sock_get_timestamp(sk, argp); |
1712 | break; | 1712 | break; |
1713 | 1713 | ||
1714 | case SIOCGSTAMPNS: | ||
1715 | res = sock_get_timestampns(sk, argp); | ||
1716 | break; | ||
1717 | |||
1714 | case SIOCAX25ADDUID: /* Add a uid to the uid/call map table */ | 1718 | case SIOCAX25ADDUID: /* Add a uid to the uid/call map table */ |
1715 | case SIOCAX25DELUID: /* Delete a uid from the uid/call map table */ | 1719 | case SIOCAX25DELUID: /* Delete a uid from the uid/call map table */ |
1716 | case SIOCAX25GETUID: { | 1720 | case SIOCAX25GETUID: { |
diff --git a/net/compat.c b/net/compat.c index 17c2710b2b93..2fc6d9bb622b 100644 --- a/net/compat.c +++ b/net/compat.c | |||
@@ -564,6 +564,30 @@ int compat_sock_get_timestamp(struct sock *sk, struct timeval __user *userstamp) | |||
564 | } | 564 | } |
565 | EXPORT_SYMBOL(compat_sock_get_timestamp); | 565 | EXPORT_SYMBOL(compat_sock_get_timestamp); |
566 | 566 | ||
567 | int compat_sock_get_timestampns(struct sock *sk, struct timespec __user *userstamp) | ||
568 | { | ||
569 | struct compat_timespec __user *ctv = | ||
570 | (struct compat_timespec __user*) userstamp; | ||
571 | int err = -ENOENT; | ||
572 | struct timespec ts; | ||
573 | |||
574 | if (!sock_flag(sk, SOCK_TIMESTAMP)) | ||
575 | sock_enable_timestamp(sk); | ||
576 | ts = ktime_to_timespec(sk->sk_stamp); | ||
577 | if (ts.tv_sec == -1) | ||
578 | return err; | ||
579 | if (ts.tv_sec == 0) { | ||
580 | sk->sk_stamp = ktime_get_real(); | ||
581 | ts = ktime_to_timespec(sk->sk_stamp); | ||
582 | } | ||
583 | err = 0; | ||
584 | if (put_user(ts.tv_sec, &ctv->tv_sec) || | ||
585 | put_user(ts.tv_nsec, &ctv->tv_nsec)) | ||
586 | err = -EFAULT; | ||
587 | return err; | ||
588 | } | ||
589 | EXPORT_SYMBOL(compat_sock_get_timestampns); | ||
590 | |||
567 | asmlinkage long compat_sys_getsockopt(int fd, int level, int optname, | 591 | asmlinkage long compat_sys_getsockopt(int fd, int level, int optname, |
568 | char __user *optval, int __user *optlen) | 592 | char __user *optval, int __user *optlen) |
569 | { | 593 | { |
diff --git a/net/core/sock.c b/net/core/sock.c index 6ddb3664b993..cb48fa0e1249 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -1567,6 +1567,22 @@ int sock_get_timestamp(struct sock *sk, struct timeval __user *userstamp) | |||
1567 | } | 1567 | } |
1568 | EXPORT_SYMBOL(sock_get_timestamp); | 1568 | EXPORT_SYMBOL(sock_get_timestamp); |
1569 | 1569 | ||
1570 | int sock_get_timestampns(struct sock *sk, struct timespec __user *userstamp) | ||
1571 | { | ||
1572 | struct timespec ts; | ||
1573 | if (!sock_flag(sk, SOCK_TIMESTAMP)) | ||
1574 | sock_enable_timestamp(sk); | ||
1575 | ts = ktime_to_timespec(sk->sk_stamp); | ||
1576 | if (ts.tv_sec == -1) | ||
1577 | return -ENOENT; | ||
1578 | if (ts.tv_sec == 0) { | ||
1579 | sk->sk_stamp = ktime_get_real(); | ||
1580 | ts = ktime_to_timespec(sk->sk_stamp); | ||
1581 | } | ||
1582 | return copy_to_user(userstamp, &ts, sizeof(ts)) ? -EFAULT : 0; | ||
1583 | } | ||
1584 | EXPORT_SYMBOL(sock_get_timestampns); | ||
1585 | |||
1570 | void sock_enable_timestamp(struct sock *sk) | 1586 | void sock_enable_timestamp(struct sock *sk) |
1571 | { | 1587 | { |
1572 | if (!sock_flag(sk, SOCK_TIMESTAMP)) { | 1588 | if (!sock_flag(sk, SOCK_TIMESTAMP)) { |
diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c index f573eddc6034..487f879f5a19 100644 --- a/net/econet/af_econet.c +++ b/net/econet/af_econet.c | |||
@@ -727,6 +727,9 @@ static int econet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg | |||
727 | case SIOCGSTAMP: | 727 | case SIOCGSTAMP: |
728 | return sock_get_timestamp(sk, argp); | 728 | return sock_get_timestamp(sk, argp); |
729 | 729 | ||
730 | case SIOCGSTAMPNS: | ||
731 | return sock_get_timestampns(sk, argp); | ||
732 | |||
730 | case SIOCSIFADDR: | 733 | case SIOCSIFADDR: |
731 | case SIOCGIFADDR: | 734 | case SIOCGIFADDR: |
732 | return ec_dev_ioctl(sock, cmd, argp); | 735 | return ec_dev_ioctl(sock, cmd, argp); |
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index cf358c84c440..df41856fc603 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c | |||
@@ -755,6 +755,9 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
755 | case SIOCGSTAMP: | 755 | case SIOCGSTAMP: |
756 | err = sock_get_timestamp(sk, (struct timeval __user *)arg); | 756 | err = sock_get_timestamp(sk, (struct timeval __user *)arg); |
757 | break; | 757 | break; |
758 | case SIOCGSTAMPNS: | ||
759 | err = sock_get_timestampns(sk, (struct timespec __user *)arg); | ||
760 | break; | ||
758 | case SIOCADDRT: | 761 | case SIOCADDRT: |
759 | case SIOCDELRT: | 762 | case SIOCDELRT: |
760 | case SIOCRTMSG: | 763 | case SIOCRTMSG: |
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index fed3758181e1..2ff070417955 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -443,6 +443,9 @@ int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
443 | case SIOCGSTAMP: | 443 | case SIOCGSTAMP: |
444 | return sock_get_timestamp(sk, (struct timeval __user *)arg); | 444 | return sock_get_timestamp(sk, (struct timeval __user *)arg); |
445 | 445 | ||
446 | case SIOCGSTAMPNS: | ||
447 | return sock_get_timestampns(sk, (struct timespec __user *)arg); | ||
448 | |||
446 | case SIOCADDRT: | 449 | case SIOCADDRT: |
447 | case SIOCDELRT: | 450 | case SIOCDELRT: |
448 | 451 | ||
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index bf9837dd95c4..a54e7ef2568a 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c | |||
@@ -1209,6 +1209,12 @@ static int nr_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1209 | release_sock(sk); | 1209 | release_sock(sk); |
1210 | return ret; | 1210 | return ret; |
1211 | 1211 | ||
1212 | case SIOCGSTAMPNS: | ||
1213 | lock_sock(sk); | ||
1214 | ret = sock_get_timestampns(sk, argp); | ||
1215 | release_sock(sk); | ||
1216 | return ret; | ||
1217 | |||
1212 | case SIOCGIFADDR: | 1218 | case SIOCGIFADDR: |
1213 | case SIOCSIFADDR: | 1219 | case SIOCSIFADDR: |
1214 | case SIOCGIFDSTADDR: | 1220 | case SIOCGIFDSTADDR: |
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index f9866a8456a1..6f8c72d2413b 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -1545,6 +1545,8 @@ static int packet_ioctl(struct socket *sock, unsigned int cmd, | |||
1545 | } | 1545 | } |
1546 | case SIOCGSTAMP: | 1546 | case SIOCGSTAMP: |
1547 | return sock_get_timestamp(sk, (struct timeval __user *)arg); | 1547 | return sock_get_timestamp(sk, (struct timeval __user *)arg); |
1548 | case SIOCGSTAMPNS: | ||
1549 | return sock_get_timestampns(sk, (struct timespec __user *)arg); | ||
1548 | 1550 | ||
1549 | #ifdef CONFIG_INET | 1551 | #ifdef CONFIG_INET |
1550 | case SIOCADDRT: | 1552 | case SIOCADDRT: |
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index f92d5310847b..f64be9369ef7 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c | |||
@@ -1296,6 +1296,9 @@ static int rose_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1296 | case SIOCGSTAMP: | 1296 | case SIOCGSTAMP: |
1297 | return sock_get_timestamp(sk, (struct timeval __user *) argp); | 1297 | return sock_get_timestamp(sk, (struct timeval __user *) argp); |
1298 | 1298 | ||
1299 | case SIOCGSTAMPNS: | ||
1300 | return sock_get_timestampns(sk, (struct timespec __user *) argp); | ||
1301 | |||
1299 | case SIOCGIFADDR: | 1302 | case SIOCGIFADDR: |
1300 | case SIOCSIFADDR: | 1303 | case SIOCSIFADDR: |
1301 | case SIOCGIFDSTADDR: | 1304 | case SIOCGIFDSTADDR: |
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index e62ba41b05c5..a19884315622 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c | |||
@@ -1280,6 +1280,12 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1280 | rc = sock_get_timestamp(sk, | 1280 | rc = sock_get_timestamp(sk, |
1281 | (struct timeval __user *)argp); | 1281 | (struct timeval __user *)argp); |
1282 | break; | 1282 | break; |
1283 | case SIOCGSTAMPNS: | ||
1284 | rc = -EINVAL; | ||
1285 | if (sk) | ||
1286 | rc = sock_get_timestampns(sk, | ||
1287 | (struct timespec __user *)argp); | ||
1288 | break; | ||
1283 | case SIOCGIFADDR: | 1289 | case SIOCGIFADDR: |
1284 | case SIOCSIFADDR: | 1290 | case SIOCSIFADDR: |
1285 | case SIOCGIFDSTADDR: | 1291 | case SIOCGIFDSTADDR: |
@@ -1521,6 +1527,12 @@ static int compat_x25_ioctl(struct socket *sock, unsigned int cmd, | |||
1521 | rc = compat_sock_get_timestamp(sk, | 1527 | rc = compat_sock_get_timestamp(sk, |
1522 | (struct timeval __user*)argp); | 1528 | (struct timeval __user*)argp); |
1523 | break; | 1529 | break; |
1530 | case SIOCGSTAMPNS: | ||
1531 | rc = -EINVAL; | ||
1532 | if (sk) | ||
1533 | rc = compat_sock_get_timestampns(sk, | ||
1534 | (struct timespec __user*)argp); | ||
1535 | break; | ||
1524 | case SIOCGIFADDR: | 1536 | case SIOCGIFADDR: |
1525 | case SIOCSIFADDR: | 1537 | case SIOCSIFADDR: |
1526 | case SIOCGIFDSTADDR: | 1538 | case SIOCGIFDSTADDR: |