summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/eventpoll.c35
-rw-r--r--fs/proc/base.c9
-rw-r--r--fs/select.c5
-rw-r--r--include/linux/eventpoll.h5
-rw-r--r--include/linux/poll.h5
-rw-r--r--include/linux/sched.h25
-rw-r--r--include/net/sock.h4
-rw-r--r--net/core/sock.c131
-rw-r--r--net/ipv4/tcp_ipv4.c19
-rw-r--r--net/ipv4/udp.c15
-rw-r--r--net/ipv6/tcp_ipv6.c13
-rw-r--r--net/ipv6/udp.c13
-rw-r--r--net/socket.c5
13 files changed, 266 insertions, 18 deletions
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index 0cff4434880d..e92a15091d80 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -9,6 +9,8 @@
*
* Davide Libenzi <davidel@xmailserver.org>
*
+ * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
+ *
*/
#include <linux/init.h>
@@ -967,7 +969,7 @@ static struct epitem *ep_find(struct eventpoll *ep, struct file *file, int fd)
* mechanism. It is called by the stored file descriptors when they
* have events to report.
*/
-static int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync, void *key)
+int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync, void *key)
{
int pwake = 0;
unsigned long flags;
@@ -1064,6 +1066,7 @@ static void ep_ptable_queue_proc(struct file *file, wait_queue_head_t *whead,
if (epi->nwait >= 0 && (pwq = kmem_cache_alloc(pwq_cache, GFP_KERNEL))) {
init_waitqueue_func_entry(&pwq->wait, ep_poll_callback);
+ pwq->wait.private = get_thread_process(current);
pwq->whead = whead;
pwq->base = epi;
add_wait_queue(whead, &pwq->wait);
@@ -1287,6 +1290,7 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event,
spin_lock(&tfile->f_lock);
list_add_tail(&epi->fllink, &tfile->f_ep_links);
spin_unlock(&tfile->f_lock);
+ tfile->f_path.dentry->d_inode->i_private = get_thread_process(current);
/*
* Add the current item to the RB tree. All RB tree operations are
@@ -1728,6 +1732,35 @@ static void clear_tfile_check_list(void)
INIT_LIST_HEAD(&tfile_check_list);
}
+struct task_struct *get_epoll_file_task(struct file *file)
+{
+ struct list_head *lh;
+ struct epitem *epi = NULL;
+ struct eppoll_entry *pwq = NULL;
+ struct task_struct *task = NULL;
+ wait_queue_head_t *whead = NULL;
+ wait_queue_t *wq = NULL;
+
+ lh = &file->f_ep_links;
+ if (!list_empty(lh)) {
+ lh = lh->next;
+ epi = list_entry(lh, struct epitem, fllink);
+ lh = &epi->pwqlist;
+ if (!list_empty(lh)) {
+ lh = lh->next;
+ pwq = list_entry(lh, struct eppoll_entry, llink);
+ lh = &pwq->whead->task_list;
+ if (!list_empty(lh)) {
+ lh = lh->next;
+ wq = list_entry(lh, wait_queue_t, task_list);
+ task = wq->private;
+ }
+ }
+ }
+
+ return task;
+}
+
/*
* Open an eventpoll file descriptor.
*/
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 2d00fdde9345..77377014887c 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -45,6 +45,8 @@
*
* Paul Mundt <paul.mundt@nokia.com>:
* Overall revision about smaps.
+ *
+ * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
*/
#include <asm/uaccess.h>
@@ -206,7 +208,12 @@ static int proc_root_link(struct dentry *dentry, struct path *path)
return result;
}
-static int proc_pid_cmdline(struct task_struct *task, char * buffer)
+struct mm_struct *mm_for_maps(struct task_struct *task)
+{
+ return mm_access(task, PTRACE_MODE_READ);
+}
+
+static int proc_pid_cmdline(struct task_struct *task, char *buffer)
{
int res = 0;
unsigned int len;
diff --git a/fs/select.c b/fs/select.c
index 6b14dc7df3a4..0595305eeb0a 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -12,6 +12,8 @@
* 24 January 2000
* Changed sys_poll()/do_poll() to use PAGE_SIZE chunk-based allocation
* of fds to overcome nfds < 16390 descriptors limit (Tigran Aivazian).
+ *
+ * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
*/
#include <linux/kernel.h>
@@ -204,7 +206,7 @@ static int __pollwake(wait_queue_t *wait, unsigned mode, int sync, void *key)
return default_wake_function(&dummy_wait, mode, sync, key);
}
-static int pollwake(wait_queue_t *wait, unsigned mode, int sync, void *key)
+int pollwake(wait_queue_t *wait, unsigned mode, int sync, void *key)
{
struct poll_table_entry *entry;
@@ -213,6 +215,7 @@ static int pollwake(wait_queue_t *wait, unsigned mode, int sync, void *key)
return 0;
return __pollwake(wait, mode, sync, key);
}
+EXPORT_SYMBOL(pollwake);
/* Add a new entry */
static void __pollwait(struct file *filp, wait_queue_head_t *wait_address,
diff --git a/include/linux/eventpoll.h b/include/linux/eventpoll.h
index 6daf6d4971f6..226cbda5c435 100644
--- a/include/linux/eventpoll.h
+++ b/include/linux/eventpoll.h
@@ -9,6 +9,8 @@
*
* Davide Libenzi <davidel@xmailserver.org>
*
+ * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
+ *
*/
#ifndef _LINUX_EVENTPOLL_H
#define _LINUX_EVENTPOLL_H
@@ -61,6 +63,9 @@ static inline void eventpoll_release(struct file *file)
eventpoll_release_file(file);
}
+int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync, void *key);
+struct task_struct *get_epoll_file_task(struct file *file);
+
#else
static inline void eventpoll_init_file(struct file *file) {}
diff --git a/include/linux/poll.h b/include/linux/poll.h
index c08386fb3e08..d52bb3f34bc6 100644
--- a/include/linux/poll.h
+++ b/include/linux/poll.h
@@ -1,3 +1,7 @@
+/*
+ * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
+ */
+
#ifndef _LINUX_POLL_H
#define _LINUX_POLL_H
@@ -94,6 +98,7 @@ struct poll_wqueues {
extern void poll_initwait(struct poll_wqueues *pwq);
extern void poll_freewait(struct poll_wqueues *pwq);
+extern int pollwake(wait_queue_t *wait, unsigned mode, int sync, void *key);
extern int poll_schedule_timeout(struct poll_wqueues *pwq, int state,
ktime_t *expires, unsigned long slack);
extern long select_estimate_accuracy(struct timespec *tv);
diff --git a/include/linux/sched.h b/include/linux/sched.h
index d14b99d6e480..0c6ca85ff151 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1,3 +1,19 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
+ */
+
#ifndef _LINUX_SCHED_H
#define _LINUX_SCHED_H
@@ -1459,6 +1475,15 @@ static inline struct pid *task_session(struct task_struct *task)
return task->group_leader->pids[PIDTYPE_SID].pid;
}
+static inline struct task_struct *get_thread_process(struct task_struct *thread)
+{
+ struct task_struct *task = thread;
+ while (task->pid != task->tgid)
+ task = task->group_leader;
+
+ return task;
+}
+
struct pid_namespace;
/*
diff --git a/include/net/sock.h b/include/net/sock.h
index 66772cf8c3c5..0a98c459f2ba 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -36,6 +36,8 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
+ *
+ * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
*/
#ifndef _SOCK_H
#define _SOCK_H
@@ -1580,6 +1582,8 @@ extern int compat_sock_common_setsockopt(struct socket *sock, int level,
extern void sk_common_release(struct sock *sk);
+extern char *sk_get_waiting_task_cmdline(struct sock *sk, char *cmdline);
+
/*
* Default socket callbacks and setup code
*/
diff --git a/net/core/sock.c b/net/core/sock.c
index d6d024cfaaaf..7ba763cbf099 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -87,6 +87,8 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
+ *
+ * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -139,6 +141,8 @@
#include <net/tcp.h>
#endif
+#include <linux/eventpoll.h>
+
static DEFINE_MUTEX(proto_list_mutex);
static LIST_HEAD(proto_list);
@@ -2512,6 +2516,133 @@ void sk_common_release(struct sock *sk)
}
EXPORT_SYMBOL(sk_common_release);
+char *sk_get_waiting_task_cmdline(struct sock *sk, char *cmdline)
+{
+ bool softirq_enabled = false;
+ int res = 0;
+ unsigned int len;
+ char *program_name = cmdline;
+ struct task_struct *task = NULL;
+ struct mm_struct *mm = NULL;
+ static char *apk_path_prefix = "/data/data";
+ wait_queue_t *wq = NULL;
+ struct list_head *lh = NULL;
+ struct socket_wq *sk_wq = NULL;
+ wait_queue_func_t wait_func;
+ enum pid_type type;
+ struct pid *pid = NULL;
+ struct fown_struct *fown = NULL;
+ struct file *file;
+
+ *program_name = '\0';
+
+ if (!sk || !sk->sk_wq)
+ goto out;
+ lh = sk->sk_wq->wait.task_list.next;
+ if (!wq_has_sleeper(sk->sk_wq)) {
+ sk_wq = sk->sk_wq;
+ if (sk_wq->fasync_list && sk_wq->fasync_list->fa_file) {
+ fown = &sk_wq->fasync_list->fa_file->f_owner;
+ pid = fown->pid;
+ type = fown->pid_type;
+ do_each_pid_task(pid, type, task) {
+ if (task)
+ break;
+ } while_each_pid_task(pid, type, task);
+ }
+ } else {
+ lh = sk->sk_wq->wait.task_list.next;
+ wq = list_entry(lh, wait_queue_t, task_list);
+
+ wait_func = wq->func;
+ if (wait_func == pollwake)
+ task = ((struct poll_wqueues *)
+ (wq->private))->polling_task;
+ else if (wait_func == default_wake_function)
+ task = (struct task_struct *)(wq->private);
+ else if (wait_func == ep_poll_callback)
+ task = (struct task_struct *)(wq->private);
+ else if (wait_func == autoremove_wake_function)
+ task = (struct task_struct *)(wq->private);
+ else
+ pr_warning("Unknown wakeup:%p.\n", wait_func);
+
+ if (task)
+ task = get_thread_process(task);
+ }
+
+#ifdef CONFIG_EPOLL
+ if (!task) {
+ file = sk->sk_socket->file;
+ if (file)
+ task = get_epoll_file_task(file);
+ }
+#endif
+
+ if (!task && sk && sk->sk_socket)
+ task = SOCK_INODE(sk->sk_socket)->i_private;
+
+ if (!task) {
+ pr_err("Can't find a process for this sock.\n");
+ goto out;
+ }
+
+ mm = get_task_mm(task);
+ if (mm && mm->arg_end) {
+ len = mm->arg_end - mm->arg_start;
+
+ if (len > PAGE_SIZE)
+ len = PAGE_SIZE;
+
+ if (softirq_count()) {
+ softirq_enabled = true;
+ local_bh_enable();
+ }
+ res = access_process_vm(task, mm->arg_start, cmdline, len, 0);
+
+ if (res > 0 && cmdline[res-1] != '\0' && len < PAGE_SIZE) {
+ len = strnlen(cmdline, res);
+ if (len < res) {
+ res = len;
+ } else {
+ len = mm->env_end - mm->env_start;
+ if (len > PAGE_SIZE - res)
+ len = PAGE_SIZE - res;
+ res += access_process_vm(task,
+ mm->env_start, cmdline+res, len, 0);
+ res = strnlen(cmdline, res);
+ }
+ }
+ if (softirq_enabled)
+ local_bh_disable();
+
+ if (res > PAGE_SIZE)
+ cmdline[PAGE_SIZE-1] = '\0';
+
+ len = strlen(apk_path_prefix);
+ if (!strncmp(apk_path_prefix, program_name, len))
+ program_name += len;
+ else
+ program_name = strrchr(cmdline, '/');
+
+ if (program_name == NULL)
+ program_name = cmdline;
+ else
+ program_name++;
+ }
+
+ if (mm)
+ mmput(mm);
+
+ len = strlen(program_name);
+ snprintf(program_name + len, PAGE_SIZE-(program_name-cmdline)-len,
+ " %d %s", task->pid, task->comm);
+out:
+ return program_name;
+}
+EXPORT_SYMBOL(sk_get_waiting_task_cmdline);
+
+
#ifdef CONFIG_PROC_FS
#define PROTO_INUSE_NR 64 /* should be enough for the first time */
struct prot_inuse {
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 7999fc55c83b..1fb157f0957d 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -48,6 +48,8 @@
* YOSHIFUJI Hideaki @USAGI and: Support IPV6_V6ONLY socket option, which
* Alexey Kuznetsov allow both IPv4 and IPv6 sockets to bind
* a single port at the same time.
+ *
+ * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
*/
#define pr_fmt(fmt) "TCP: " fmt
@@ -2661,6 +2663,9 @@ static void get_tcp4_sock(struct sock *sk, struct seq_file *f, int i, int *len)
__u16 destp = ntohs(inet->inet_dport);
__u16 srcp = ntohs(inet->inet_sport);
int rx_queue;
+ unsigned long cmdline = __get_free_page(GFP_TEMPORARY);
+ if (cmdline == NULL)
+ return;
if (icsk->icsk_pending == ICSK_TIME_RETRANS ||
icsk->icsk_pending == ICSK_TIME_EARLY_RETRANS ||
@@ -2687,7 +2692,7 @@ static void get_tcp4_sock(struct sock *sk, struct seq_file *f, int i, int *len)
rx_queue = max_t(int, tp->rcv_nxt - tp->copied_seq, 0);
seq_printf(f, "%4d: %08X:%04X %08X:%04X %02X %08X:%08X %02X:%08lX "
- "%08X %5d %8d %lu %d %pK %lu %lu %u %u %d%n",
+ "%08X %5d %8d %lu %d %pK %lu %lu %u %u %d %s%n",
i, src, srcp, dest, destp, sk->sk_state,
tp->write_seq - tp->snd_una,
rx_queue,
@@ -2705,7 +2710,10 @@ static void get_tcp4_sock(struct sock *sk, struct seq_file *f, int i, int *len)
sk->sk_state == TCP_LISTEN ?
(fastopenq ? fastopenq->max_qlen : 0) :
(tcp_in_initial_slowstart(tp) ? -1 : tp->snd_ssthresh),
+ sk_get_waiting_task_cmdline(sk, cmdline),
len);
+
+ free_page(cmdline);
}
static void get_timewait4_sock(const struct inet_timewait_sock *tw,
@@ -2736,9 +2744,10 @@ static int tcp4_seq_show(struct seq_file *seq, void *v)
if (v == SEQ_START_TOKEN) {
seq_printf(seq, "%-*s\n", TMPSZ - 1,
- " sl local_address rem_address st tx_queue "
- "rx_queue tr tm->when retrnsmt uid timeout "
- "inode");
+ " sl local_address rem_address st tx_queue "
+ "rx_queue tr tm->when retrnsmt uid timeout "
+ "inode "
+ "cmdline");
goto out;
}
st = seq->private;
@@ -2755,7 +2764,7 @@ static int tcp4_seq_show(struct seq_file *seq, void *v)
get_timewait4_sock(v, seq, st->num, &len);
break;
}
- seq_printf(seq, "%*s\n", TMPSZ - 1 - len, "");
+ seq_printf(seq, "\n");
out:
return 0;
}
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 93b731d53221..6c9ab80efb52 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -75,6 +75,8 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
+ *
+ * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
*/
#define pr_fmt(fmt) "UDP: " fmt
@@ -2150,9 +2152,12 @@ static void udp4_format_sock(struct sock *sp, struct seq_file *f,
__be32 src = inet->inet_rcv_saddr;
__u16 destp = ntohs(inet->inet_dport);
__u16 srcp = ntohs(inet->inet_sport);
+ unsigned long cmdline = __get_free_page(GFP_TEMPORARY);
+ if (cmdline == NULL)
+ return;
seq_printf(f, "%5d: %08X:%04X %08X:%04X"
- " %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %pK %d%n",
+ " %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %pK %d %s%n",
bucket, src, srcp, dest, destp, sp->sk_state,
sk_wmem_alloc_get(sp),
sk_rmem_alloc_get(sp),
@@ -2160,7 +2165,9 @@ static void udp4_format_sock(struct sock *sp, struct seq_file *f,
from_kuid_munged(seq_user_ns(f), sock_i_uid(sp)),
0, sock_i_ino(sp),
atomic_read(&sp->sk_refcnt), sp,
- atomic_read(&sp->sk_drops), len);
+ atomic_read(&sp->sk_drops),
+ sk_get_waiting_task_cmdline(sp, cmdline), len);
+ free_page(cmdline);
}
int udp4_seq_show(struct seq_file *seq, void *v)
@@ -2169,13 +2176,13 @@ int udp4_seq_show(struct seq_file *seq, void *v)
seq_printf(seq, "%-127s\n",
" sl local_address rem_address st tx_queue "
"rx_queue tr tm->when retrnsmt uid timeout "
- "inode ref pointer drops");
+ "inode ref pointer drops cmdline");
else {
struct udp_iter_state *state = seq->private;
int len;
udp4_format_sock(v, seq, state->bucket, &len);
- seq_printf(seq, "%*s\n", 127 - len, "");
+ seq_printf(seq, "\n");
}
return 0;
}
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 0a17ed9eaf39..28f791ed6bb8 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -21,6 +21,8 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
+ *
+ * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
*/
#include <linux/bottom_half.h>
@@ -1759,6 +1761,9 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i)
const struct tcp_sock *tp = tcp_sk(sp);
const struct inet_connection_sock *icsk = inet_csk(sp);
const struct ipv6_pinfo *np = inet6_sk(sp);
+ unsigned long cmdline = __get_free_page(GFP_TEMPORARY);
+ if (cmdline == NULL)
+ return;
dest = &np->daddr;
src = &np->rcv_saddr;
@@ -1781,7 +1786,7 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i)
seq_printf(seq,
"%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
- "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %pK %lu %lu %u %u %d\n",
+ "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %pK %lu %lu %u %u %d %s\n",
i,
src->s6_addr32[0], src->s6_addr32[1],
src->s6_addr32[2], src->s6_addr32[3], srcp,
@@ -1801,8 +1806,10 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i)
jiffies_to_clock_t(icsk->icsk_ack.ato),
(icsk->icsk_ack.quick << 1 ) | icsk->icsk_ack.pingpong,
tp->snd_cwnd,
- tcp_in_initial_slowstart(tp) ? -1 : tp->snd_ssthresh
+ tcp_in_initial_slowstart(tp) ? -1 : tp->snd_ssthresh,
+ sk_get_waiting_task_cmdline(sp, cmdline)
);
+ free_page(cmdline);
}
static void get_timewait6_sock(struct seq_file *seq,
@@ -1841,7 +1848,7 @@ static int tcp6_seq_show(struct seq_file *seq, void *v)
"local_address "
"remote_address "
"st tx_queue rx_queue tr tm->when retrnsmt"
- " uid timeout inode\n");
+ " uid timeout inode cmdline\n");
goto out;
}
st = seq->private;
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index e7b28f9bb02b..51330d91c825 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -19,6 +19,8 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
+ *
+ * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
*/
#include <linux/errno.h>
@@ -1371,6 +1373,9 @@ static void udp6_sock_seq_show(struct seq_file *seq, struct sock *sp, int bucket
struct ipv6_pinfo *np = inet6_sk(sp);
const struct in6_addr *dest, *src;
__u16 destp, srcp;
+ unsigned long cmdline = __get_free_page(GFP_TEMPORARY);
+ if (cmdline == NULL)
+ return;
dest = &np->daddr;
src = &np->rcv_saddr;
@@ -1378,7 +1383,7 @@ static void udp6_sock_seq_show(struct seq_file *seq, struct sock *sp, int bucket
srcp = ntohs(inet->inet_sport);
seq_printf(seq,
"%5d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
- "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %pK %d\n",
+ "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %pK %d %s\n",
bucket,
src->s6_addr32[0], src->s6_addr32[1],
src->s6_addr32[2], src->s6_addr32[3], srcp,
@@ -1392,7 +1397,9 @@ static void udp6_sock_seq_show(struct seq_file *seq, struct sock *sp, int bucket
0,
sock_i_ino(sp),
atomic_read(&sp->sk_refcnt), sp,
- atomic_read(&sp->sk_drops));
+ atomic_read(&sp->sk_drops),
+ sk_get_waiting_task_cmdline(sp, cmdline));
+ free_page(cmdline);
}
int udp6_seq_show(struct seq_file *seq, void *v)
@@ -1403,7 +1410,7 @@ int udp6_seq_show(struct seq_file *seq, void *v)
"local_address "
"remote_address "
"st tx_queue rx_queue tr tm->when retrnsmt"
- " uid timeout inode ref pointer drops\n");
+ " uid timeout inode ref pointer drops cmdline\n");
else
udp6_sock_seq_show(seq, v, ((struct udp_iter_state *)seq->private)->bucket);
return 0;
diff --git a/net/socket.c b/net/socket.c
index 4ca1526db756..30d6ec51b620 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -56,6 +56,8 @@
* paradigm.
*
* Based upon Swansea University Computer Society NET3.039
+ *
+ * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
*/
#include <linux/mm.h>
@@ -913,6 +915,7 @@ static ssize_t do_sock_read(struct msghdr *msg, struct kiocb *iocb,
msg->msg_iov = (struct iovec *)iov;
msg->msg_iovlen = nr_segs;
msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
+ SOCK_INODE(sock)->i_private = get_thread_process(current);
return __sock_recvmsg(iocb, sock, msg, size, msg->msg_flags);
}
@@ -1148,6 +1151,7 @@ static unsigned int sock_poll(struct file *file, poll_table *wait)
* We can't return errors to poll, so it's either yes or no.
*/
sock = file->private_data;
+ SOCK_INODE(sock)->i_private = get_thread_process(current);
return sock->ops->poll(file, sock, wait);
}
@@ -1384,6 +1388,7 @@ SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
retval = sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK));
if (retval < 0)
goto out_release;
+ SOCK_INODE(sock)->i_private = get_thread_process(current);
out:
/* It may be already another descriptor 8) Not kernel problem. */