netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net-next v2 0/2] unix: Show number of scm files in fdinfo
@ 2019-12-09 10:03 Kirill Tkhai
  2019-12-09 10:03 ` [PATCH net-next v2 1/2] net: Allow to show socket-specific information in /proc/[pid]/fdinfo/[fd] Kirill Tkhai
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Kirill Tkhai @ 2019-12-09 10:03 UTC (permalink / raw)
  To: netdev
  Cc: davem, axboe, pankaj.laxminarayan.bharadiya, keescook, viro,
	hare, tglx, edumazet, arnd, ktkhai

v2: Pass correct argument to locked in patch [2/2].

Unix sockets like a block box. You never know what is pending there:
there may be a file descriptor holding a mount or a block device,
or there may be whole universes with namespaces, sockets with receive
queues full of sockets etc.

The patchset makes number of pending scm files be visible in fdinfo.
This may be useful to determine, that socket should be investigated
or which task should be killed to put a reference counter on a resourse.

$cat /proc/[pid]/fdinfo/[unix_sk_fd] | grep scm_fds
scm_fds: 1

---

Kirill Tkhai (2):
      net: Allow to show socket-specific information in /proc/[pid]/fdinfo/[fd]
      unix: Show number of pending scm files of receive queue in fdinfo


 include/linux/net.h   |    1 +
 include/net/af_unix.h |    5 ++++
 net/socket.c          |   12 +++++++++++
 net/unix/af_unix.c    |   56 +++++++++++++++++++++++++++++++++++++++++++++----
 4 files changed, 69 insertions(+), 5 deletions(-)

--
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH net-next v2 1/2] net: Allow to show socket-specific information in /proc/[pid]/fdinfo/[fd]
  2019-12-09 10:03 [PATCH net-next v2 0/2] unix: Show number of scm files in fdinfo Kirill Tkhai
@ 2019-12-09 10:03 ` Kirill Tkhai
  2019-12-09 10:03 ` [PATCH net-next v2 2/2] unix: Show number of pending scm files of receive queue in fdinfo Kirill Tkhai
  2019-12-13  1:05 ` [PATCH net-next v2 0/2] unix: Show number of scm files " David Miller
  2 siblings, 0 replies; 5+ messages in thread
From: Kirill Tkhai @ 2019-12-09 10:03 UTC (permalink / raw)
  To: netdev
  Cc: davem, axboe, pankaj.laxminarayan.bharadiya, keescook, viro,
	hare, tglx, edumazet, arnd, ktkhai

This adds .show_fdinfo to socket_file_ops, so protocols will be able
to print their specific data in fdinfo.

Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
---
 include/linux/net.h |    1 +
 net/socket.c        |   12 ++++++++++++
 2 files changed, 13 insertions(+)

diff --git a/include/linux/net.h b/include/linux/net.h
index 9cafb5f353a9..6451425e828f 100644
--- a/include/linux/net.h
+++ b/include/linux/net.h
@@ -171,6 +171,7 @@ struct proto_ops {
 	int		(*compat_getsockopt)(struct socket *sock, int level,
 				      int optname, char __user *optval, int __user *optlen);
 #endif
+	void		(*show_fdinfo)(struct seq_file *m, struct socket *sock);
 	int		(*sendmsg)   (struct socket *sock, struct msghdr *m,
 				      size_t total_len);
 	/* Notes for implementing recvmsg:
diff --git a/net/socket.c b/net/socket.c
index 4d38d49d6ad9..532f123e0459 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -128,6 +128,7 @@ static ssize_t sock_sendpage(struct file *file, struct page *page,
 static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
 				struct pipe_inode_info *pipe, size_t len,
 				unsigned int flags);
+static void sock_show_fdinfo(struct seq_file *m, struct file *f);
 
 /*
  *	Socket files have a set of 'special' operations as well as the generic file ones. These don't appear
@@ -150,6 +151,9 @@ static const struct file_operations socket_file_ops = {
 	.sendpage =	sock_sendpage,
 	.splice_write = generic_splice_sendpage,
 	.splice_read =	sock_splice_read,
+#ifdef CONFIG_PROC_FS
+	.show_fdinfo =	sock_show_fdinfo,
+#endif
 };
 
 /*
@@ -993,6 +997,14 @@ static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from)
 	return res;
 }
 
+static void sock_show_fdinfo(struct seq_file *m, struct file *f)
+{
+	struct socket *sock = f->private_data;
+
+	if (sock->ops->show_fdinfo)
+		sock->ops->show_fdinfo(m, sock);
+}
+
 /*
  * Atomic setting of ioctl hooks to avoid race
  * with module unload.



^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH net-next v2 2/2] unix: Show number of pending scm files of receive queue in fdinfo
  2019-12-09 10:03 [PATCH net-next v2 0/2] unix: Show number of scm files in fdinfo Kirill Tkhai
  2019-12-09 10:03 ` [PATCH net-next v2 1/2] net: Allow to show socket-specific information in /proc/[pid]/fdinfo/[fd] Kirill Tkhai
@ 2019-12-09 10:03 ` Kirill Tkhai
  2019-12-13  1:05 ` [PATCH net-next v2 0/2] unix: Show number of scm files " David Miller
  2 siblings, 0 replies; 5+ messages in thread
From: Kirill Tkhai @ 2019-12-09 10:03 UTC (permalink / raw)
  To: netdev
  Cc: davem, axboe, pankaj.laxminarayan.bharadiya, keescook, viro,
	hare, tglx, edumazet, arnd, ktkhai

Unix sockets like a block box. You never know what is stored there:
there may be a file descriptor holding a mount or a block device,
or there may be whole universes with namespaces, sockets with receive
queues full of sockets etc.

The patch adds a little debug and accounts number of files (not recursive),
which is in receive queue of a unix socket. Sometimes this is useful
to determine, that socket should be investigated or which task should
be killed to put reference counter on a resourse.

v2: Pass correct argument to lockdep

Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
---
 include/net/af_unix.h |    5 ++++
 net/unix/af_unix.c    |   56 +++++++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 56 insertions(+), 5 deletions(-)

diff --git a/include/net/af_unix.h b/include/net/af_unix.h
index 3426d6dacc45..17e10fba2152 100644
--- a/include/net/af_unix.h
+++ b/include/net/af_unix.h
@@ -41,6 +41,10 @@ struct unix_skb_parms {
 	u32			consumed;
 } __randomize_layout;
 
+struct scm_stat {
+	u32 nr_fds;
+};
+
 #define UNIXCB(skb)	(*(struct unix_skb_parms *)&((skb)->cb))
 
 #define unix_state_lock(s)	spin_lock(&unix_sk(s)->lock)
@@ -65,6 +69,7 @@ struct unix_sock {
 #define UNIX_GC_MAYBE_CYCLE	1
 	struct socket_wq	peer_wq;
 	wait_queue_entry_t	peer_wake;
+	struct scm_stat		scm_stat;
 };
 
 static inline struct unix_sock *unix_sk(const struct sock *sk)
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index f0a074356012..71d2aa83911a 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -676,6 +676,16 @@ static int unix_set_peek_off(struct sock *sk, int val)
 	return 0;
 }
 
+static void unix_show_fdinfo(struct seq_file *m, struct socket *sock)
+{
+	struct sock *sk = sock->sk;
+	struct unix_sock *u;
+
+	if (sk) {
+		u = unix_sk(sock->sk);
+		seq_printf(m, "scm_fds: %u\n", READ_ONCE(u->scm_stat.nr_fds));
+	}
+}
 
 static const struct proto_ops unix_stream_ops = {
 	.family =	PF_UNIX,
@@ -701,6 +711,7 @@ static const struct proto_ops unix_stream_ops = {
 	.sendpage =	unix_stream_sendpage,
 	.splice_read =	unix_stream_splice_read,
 	.set_peek_off =	unix_set_peek_off,
+	.show_fdinfo =	unix_show_fdinfo,
 };
 
 static const struct proto_ops unix_dgram_ops = {
@@ -726,6 +737,7 @@ static const struct proto_ops unix_dgram_ops = {
 	.mmap =		sock_no_mmap,
 	.sendpage =	sock_no_sendpage,
 	.set_peek_off =	unix_set_peek_off,
+	.show_fdinfo =	unix_show_fdinfo,
 };
 
 static const struct proto_ops unix_seqpacket_ops = {
@@ -751,6 +763,7 @@ static const struct proto_ops unix_seqpacket_ops = {
 	.mmap =		sock_no_mmap,
 	.sendpage =	sock_no_sendpage,
 	.set_peek_off =	unix_set_peek_off,
+	.show_fdinfo =	unix_show_fdinfo,
 };
 
 static struct proto unix_proto = {
@@ -788,6 +801,7 @@ static struct sock *unix_create1(struct net *net, struct socket *sock, int kern)
 	mutex_init(&u->bindlock); /* single task binding lock */
 	init_waitqueue_head(&u->peer_wait);
 	init_waitqueue_func_entry(&u->peer_wake, unix_dgram_peer_wake_relay);
+	memset(&u->scm_stat, 0, sizeof(struct scm_stat));
 	unix_insert_socket(unix_sockets_unbound(sk), sk);
 out:
 	if (sk == NULL)
@@ -1572,6 +1586,28 @@ static bool unix_skb_scm_eq(struct sk_buff *skb,
 	       unix_secdata_eq(scm, skb);
 }
 
+static void scm_stat_add(struct sock *sk, struct sk_buff *skb)
+{
+	struct scm_fp_list *fp = UNIXCB(skb).fp;
+	struct unix_sock *u = unix_sk(sk);
+
+	lockdep_assert_held(&sk->sk_receive_queue.lock);
+
+	if (unlikely(fp && fp->count))
+		u->scm_stat.nr_fds += fp->count;
+}
+
+static void scm_stat_del(struct sock *sk, struct sk_buff *skb)
+{
+	struct scm_fp_list *fp = UNIXCB(skb).fp;
+	struct unix_sock *u = unix_sk(sk);
+
+	lockdep_assert_held(&sk->sk_receive_queue.lock);
+
+	if (unlikely(fp && fp->count))
+		u->scm_stat.nr_fds -= fp->count;
+}
+
 /*
  *	Send AF_UNIX data.
  */
@@ -1757,7 +1793,10 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg,
 	if (sock_flag(other, SOCK_RCVTSTAMP))
 		__net_timestamp(skb);
 	maybe_add_creds(skb, sock, other);
-	skb_queue_tail(&other->sk_receive_queue, skb);
+	spin_lock(&other->sk_receive_queue.lock);
+	scm_stat_add(other, skb);
+	__skb_queue_tail(&other->sk_receive_queue, skb);
+	spin_unlock(&other->sk_receive_queue.lock);
 	unix_state_unlock(other);
 	other->sk_data_ready(other);
 	sock_put(other);
@@ -1859,7 +1898,10 @@ static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg,
 			goto pipe_err_free;
 
 		maybe_add_creds(skb, sock, other);
-		skb_queue_tail(&other->sk_receive_queue, skb);
+		spin_lock(&other->sk_receive_queue.lock);
+		scm_stat_add(other, skb);
+		__skb_queue_tail(&other->sk_receive_queue, skb);
+		spin_unlock(&other->sk_receive_queue.lock);
 		unix_state_unlock(other);
 		other->sk_data_ready(other);
 		sent += size;
@@ -2058,8 +2100,8 @@ static int unix_dgram_recvmsg(struct socket *sock, struct msghdr *msg,
 		mutex_lock(&u->iolock);
 
 		skip = sk_peek_offset(sk, flags);
-		skb = __skb_try_recv_datagram(sk, flags, NULL, &skip, &err,
-					      &last);
+		skb = __skb_try_recv_datagram(sk, flags, scm_stat_del,
+					      &skip, &err, &last);
 		if (skb)
 			break;
 
@@ -2353,8 +2395,12 @@ static int unix_stream_read_generic(struct unix_stream_read_state *state,
 
 			sk_peek_offset_bwd(sk, chunk);
 
-			if (UNIXCB(skb).fp)
+			if (UNIXCB(skb).fp) {
+				spin_lock(&sk->sk_receive_queue.lock);
+				scm_stat_del(sk, skb);
+				spin_unlock(&sk->sk_receive_queue.lock);
 				unix_detach_fds(&scm, skb);
+			}
 
 			if (unix_skb_len(skb))
 				break;



^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH net-next v2 0/2] unix: Show number of scm files in fdinfo
  2019-12-09 10:03 [PATCH net-next v2 0/2] unix: Show number of scm files in fdinfo Kirill Tkhai
  2019-12-09 10:03 ` [PATCH net-next v2 1/2] net: Allow to show socket-specific information in /proc/[pid]/fdinfo/[fd] Kirill Tkhai
  2019-12-09 10:03 ` [PATCH net-next v2 2/2] unix: Show number of pending scm files of receive queue in fdinfo Kirill Tkhai
@ 2019-12-13  1:05 ` David Miller
  2019-12-13  7:37   ` Kirill Tkhai
  2 siblings, 1 reply; 5+ messages in thread
From: David Miller @ 2019-12-13  1:05 UTC (permalink / raw)
  To: ktkhai
  Cc: netdev, axboe, pankaj.laxminarayan.bharadiya, keescook, viro,
	hare, tglx, edumazet, arnd

From: Kirill Tkhai <ktkhai@virtuozzo.com>
Date: Mon, 09 Dec 2019 13:03:34 +0300

> v2: Pass correct argument to locked in patch [2/2].
> 
> Unix sockets like a block box. You never know what is pending there:
> there may be a file descriptor holding a mount or a block device,
> or there may be whole universes with namespaces, sockets with receive
> queues full of sockets etc.
> 
> The patchset makes number of pending scm files be visible in fdinfo.
> This may be useful to determine, that socket should be investigated
> or which task should be killed to put a reference counter on a resourse.
> 
> $cat /proc/[pid]/fdinfo/[unix_sk_fd] | grep scm_fds
> scm_fds: 1

Series applied.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH net-next v2 0/2] unix: Show number of scm files in fdinfo
  2019-12-13  1:05 ` [PATCH net-next v2 0/2] unix: Show number of scm files " David Miller
@ 2019-12-13  7:37   ` Kirill Tkhai
  0 siblings, 0 replies; 5+ messages in thread
From: Kirill Tkhai @ 2019-12-13  7:37 UTC (permalink / raw)
  To: David Miller
  Cc: netdev, axboe, pankaj.laxminarayan.bharadiya, keescook, viro,
	hare, tglx, edumazet, arnd

On 13.12.2019 04:05, David Miller wrote:
> From: Kirill Tkhai <ktkhai@virtuozzo.com>
> Date: Mon, 09 Dec 2019 13:03:34 +0300
> 
>> v2: Pass correct argument to locked in patch [2/2].
>>
>> Unix sockets like a block box. You never know what is pending there:
>> there may be a file descriptor holding a mount or a block device,
>> or there may be whole universes with namespaces, sockets with receive
>> queues full of sockets etc.
>>
>> The patchset makes number of pending scm files be visible in fdinfo.
>> This may be useful to determine, that socket should be investigated
>> or which task should be killed to put a reference counter on a resourse.
>>
>> $cat /proc/[pid]/fdinfo/[unix_sk_fd] | grep scm_fds
>> scm_fds: 1
> 
> Series applied.

Thanks, David.


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2019-12-13  7:38 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-12-09 10:03 [PATCH net-next v2 0/2] unix: Show number of scm files in fdinfo Kirill Tkhai
2019-12-09 10:03 ` [PATCH net-next v2 1/2] net: Allow to show socket-specific information in /proc/[pid]/fdinfo/[fd] Kirill Tkhai
2019-12-09 10:03 ` [PATCH net-next v2 2/2] unix: Show number of pending scm files of receive queue in fdinfo Kirill Tkhai
2019-12-13  1:05 ` [PATCH net-next v2 0/2] unix: Show number of scm files " David Miller
2019-12-13  7:37   ` Kirill Tkhai

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).