Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1376336 > unrolled thread
| Started by | Andrey Vagin <avagin@openvz.org> |
|---|---|
| First post | 2016-04-12 01:40 +0200 |
| Last post | 2016-04-13 05:30 +0200 |
| Articles | 5 — 4 participants |
Back to article view | Back to linux.kernel
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
[PATCH 04/15] task_diag: add a new interface to get information about tasks (v4) Andrey Vagin <avagin@openvz.org> - 2016-04-12 01:40 +0200
Re: [PATCH 04/15] task_diag: add a new interface to get information about tasks (v4) Cyrill Gorcunov <gorcunov@gmail.com> - 2016-04-12 09:10 +0200
Re: [PATCH 04/15] task_diag: add a new interface to get information about tasks (v4) Andrew Vagin <avagin@gmail.com> - 2016-04-13 02:40 +0200
Re: [PATCH 04/15] task_diag: add a new interface to get information about tasks (v4) Cyrill Gorcunov <gorcunov@gmail.com> - 2016-04-13 07:30 +0200
Re: [PATCH 04/15] task_diag: add a new interface to get information about tasks (v4) Andrew Vagin <avagin@virtuozzo.com> - 2016-04-13 05:30 +0200
| From | Andrey Vagin <avagin@openvz.org> |
|---|---|
| Date | 2016-04-12 01:40 +0200 |
| Subject | [PATCH 04/15] task_diag: add a new interface to get information about tasks (v4) |
| Message-ID | <rmTB0-5Gv-19@gated-at.bofh.it> |
The task-diag interface allows to get information about running
processes (roughly same info that is now available from /proc/PID/*
files). Compared to /proc/PID/*, it is faster, more flexible and
provides data in a binary format.
Task-diag was created using the basic idea of socket_diag.
Here is the /proc/task-diag file, which operates based on the following
principles:
* Transactional: write request, read response
* Netlink message format (same as used by sock_diag; binary and extendable)
A request messages is described by the task_diag_pid structure:
struct task_diag_pid {
__u64 show_flags;
__u64 dump_strategy;
__u32 pid;
};
A respone is a set of netlink messages. Each message describes one task.
All task properties are divided on groups. A message contains the
TASK_DIAG_PID group, and other groups if they have been requested in
show_flags. For example, if show_flags contains TASK_DIAG_SHOW_BASE, a
response will contain the TASK_DIAG_CRED group which is described by the
task_diag_creds structure.
struct task_diag_base {
__u32 tgid;
__u32 pid;
__u32 ppid;
__u32 tpid;
__u32 sid;
__u32 pgid;
__u8 state;
char comm[TASK_DIAG_COMM_LEN];
};
The dump_strategy field will be used in following patches to request
information for a group of processes.
v2: A few changes from David Ahern
Use a consistent name
Add max attr enum
task diag: Send pid as u32
Change _MSG/msg references to base
Fix 8-byte alignment
v3: take pid namespace from scm credentials. There is a pid of a process
which sent an request. If we need to get information from another
namespace, we can set pid in scm of a process from this namespaces.
v4: use a transaction file instead of netlink
Cc: David Ahern <dsahern@gmail.com>
Signed-off-by: Andrey Vagin <avagin@openvz.org>
---
fs/proc/Kconfig | 13 ++
fs/proc/Makefile | 3 +
fs/proc/task_diag.c | 424 +++++++++++++++++++++++++++++++++++++++++
include/uapi/linux/task_diag.h | 66 +++++++
4 files changed, 506 insertions(+)
create mode 100644 fs/proc/task_diag.c
create mode 100644 include/uapi/linux/task_diag.h
diff --git a/fs/proc/Kconfig b/fs/proc/Kconfig
index 1ade120..ca223f5 100644
--- a/fs/proc/Kconfig
+++ b/fs/proc/Kconfig
@@ -81,3 +81,16 @@ config PROC_CHILDREN
Say Y if you are running any user-space software which takes benefit from
this interface. For example, rkt is such a piece of software.
+
+config TASK_DIAG
+ bool "Task-diag support (/proc/task-diag)"
+ depends on NET
+ default n
+ help
+ Export selected properties for tasks/processes through the /proc/task-diag
+ transaction file. Unlike the proc file system, task_diag returns
+ information in a binary format (netlink) and allows to specify which
+ properties are required.
+
+ Say N if unsure.
+
diff --git a/fs/proc/Makefile b/fs/proc/Makefile
index 7151ea4..94965b9 100644
--- a/fs/proc/Makefile
+++ b/fs/proc/Makefile
@@ -30,3 +30,6 @@ proc-$(CONFIG_PROC_KCORE) += kcore.o
proc-$(CONFIG_PROC_VMCORE) += vmcore.o
proc-$(CONFIG_PRINTK) += kmsg.o
proc-$(CONFIG_PROC_PAGE_MONITOR) += page.o
+
+obj-$(CONFIG_TASK_DIAG) += task_diag.o
+
diff --git a/fs/proc/task_diag.c b/fs/proc/task_diag.c
new file mode 100644
index 0000000..3c2127e
--- /dev/null
+++ b/fs/proc/task_diag.c
@@ -0,0 +1,424 @@
+#include <linux/kernel.h>
+#include <linux/task_diag.h>
+#include <linux/pid_namespace.h>
+#include <linux/ptrace.h>
+#include <linux/proc_fs.h>
+#include <linux/sched.h>
+#include <linux/taskstats.h>
+#include <net/sock.h>
+
+struct task_diag_cb {
+ struct sk_buff *req;
+ struct sk_buff *resp;
+ const struct nlmsghdr *nlh;
+ pid_t pid;
+ int pos;
+ int attr;
+};
+
+/*
+ * The task state array is a strange "bitmap" of
+ * reasons to sleep. Thus "running" is zero, and
+ * you can test for combinations of others with
+ * simple bit tests.
+ */
+static const __u8 task_state_array[] = {
+ TASK_DIAG_RUNNING,
+ TASK_DIAG_INTERRUPTIBLE,
+ TASK_DIAG_UNINTERRUPTIBLE,
+ TASK_DIAG_STOPPED,
+ TASK_DIAG_TRACE_STOP,
+ TASK_DIAG_DEAD,
+ TASK_DIAG_ZOMBIE,
+};
+
+static inline const __u8 get_task_state(struct task_struct *tsk)
+{
+ unsigned int state = (tsk->state | tsk->exit_state) & TASK_REPORT;
+
+ BUILD_BUG_ON(1 + ilog2(TASK_REPORT) != ARRAY_SIZE(task_state_array)-1);
+
+ return task_state_array[fls(state)];
+}
+
+static int fill_task_base(struct task_struct *p,
+ struct sk_buff *skb, struct pid_namespace *ns)
+{
+ struct task_diag_base *base;
+ struct nlattr *attr;
+ char tcomm[sizeof(p->comm)];
+ struct task_struct *tracer;
+
+ attr = nla_reserve(skb, TASK_DIAG_BASE, sizeof(struct task_diag_base));
+ if (!attr)
+ return -EMSGSIZE;
+
+ base = nla_data(attr);
+
+ rcu_read_lock();
+ base->ppid = pid_alive(p) ?
+ task_tgid_nr_ns(rcu_dereference(p->real_parent), ns) : 0;
+
+ base->tpid = 0;
+ tracer = ptrace_parent(p);
+ if (tracer)
+ base->tpid = task_pid_nr_ns(tracer, ns);
+
+ base->tgid = task_tgid_nr_ns(p, ns);
+ base->pid = task_pid_nr_ns(p, ns);
+ base->sid = task_session_nr_ns(p, ns);
+ base->pgid = task_pgrp_nr_ns(p, ns);
+
+ rcu_read_unlock();
+
+ get_task_comm(tcomm, p);
+ memset(base->comm, 0, TASK_DIAG_COMM_LEN);
+ strncpy(base->comm, tcomm, TASK_DIAG_COMM_LEN);
+
+ base->state = get_task_state(p);
+
+ return 0;
+}
+
+static int task_diag_fill(struct task_struct *tsk, struct sk_buff *skb,
+ struct task_diag_pid *req,
+ struct task_diag_cb *cb, struct pid_namespace *pidns,
+ struct user_namespace *userns)
+{
+ u64 show_flags = req->show_flags;
+ struct nlmsghdr *nlh;
+ struct task_diag_msg *msg;
+ int err = 0, i = 0, n = 0;
+ int flags = 0;
+
+ if (cb) {
+ n = cb->attr;
+ flags |= NLM_F_MULTI;
+ }
+
+ nlh = nlmsg_put(skb, 0, cb->nlh->nlmsg_seq,
+ TASK_DIAG_CMD_GET, sizeof(*msg), flags);
+ if (nlh == NULL)
+ return -EMSGSIZE;
+
+ msg = nlmsg_data(nlh);
+ msg->pid = task_pid_nr_ns(tsk, pidns);
+ msg->tgid = task_tgid_nr_ns(tsk, pidns);
+
+ if (show_flags & TASK_DIAG_SHOW_BASE) {
+ if (i >= n)
+ err = fill_task_base(tsk, skb, pidns);
+ if (err)
+ goto err;
+ i++;
+ }
+
+ nlmsg_end(skb, nlh);
+ if (cb)
+ cb->attr = 0;
+
+ return 0;
+err:
+ if (err == -EMSGSIZE && (i > n)) {
+ if (cb)
+ cb->attr = i;
+ nlmsg_end(skb, nlh);
+ } else
+ nlmsg_cancel(skb, nlh);
+
+ return err;
+}
+
+struct task_iter {
+ struct task_diag_pid req;
+ struct pid_namespace *ns;
+ struct task_struct *parent;
+
+ struct task_diag_cb *cb;
+
+ struct tgid_iter tgid;
+ unsigned int pos;
+ struct task_struct *task;
+};
+
+static void iter_stop(struct task_iter *iter)
+{
+ struct task_struct *task;
+
+ if (iter->parent)
+ put_task_struct(iter->parent);
+
+ switch (iter->req.dump_strategy) {
+ case TASK_DIAG_DUMP_ALL:
+ task = iter->tgid.task;
+ break;
+ default:
+ task = iter->task;
+ }
+ if (task)
+ put_task_struct(task);
+}
+
+static struct task_struct *iter_start(struct task_iter *iter)
+{
+ if (iter->req.pid > 0) {
+ rcu_read_lock();
+ iter->parent = find_task_by_pid_ns(iter->req.pid, iter->ns);
+ if (iter->parent)
+ get_task_struct(iter->parent);
+ rcu_read_unlock();
+ }
+
+ switch (iter->req.dump_strategy) {
+ case TASK_DIAG_DUMP_ONE:
+ if (iter->parent == NULL)
+ return ERR_PTR(-ESRCH);
+ iter->pos = iter->cb->pos;
+ if (iter->pos == 0) {
+ iter->task = iter->parent;
+ iter->parent = NULL;
+ } else
+ iter->task = NULL;
+ return iter->task;
+
+ case TASK_DIAG_DUMP_ALL:
+ iter->tgid.tgid = iter->cb->pid;
+ iter->tgid.task = NULL;
+ iter->tgid = next_tgid(iter->ns, iter->tgid);
+ return iter->tgid.task;
+ }
+
+ return ERR_PTR(-EINVAL);
+}
+
+static struct task_struct *iter_next(struct task_iter *iter)
+{
+ switch (iter->req.dump_strategy) {
+ case TASK_DIAG_DUMP_ONE:
+ iter->pos++;
+ iter->cb->pos = iter->pos;
+ if (iter->task)
+ put_task_struct(iter->task);
+ iter->task = NULL;
+ return NULL;
+
+ case TASK_DIAG_DUMP_ALL:
+ iter->tgid.tgid += 1;
+ iter->tgid = next_tgid(iter->ns, iter->tgid);
+ iter->cb->pid = iter->tgid.tgid;
+ return iter->tgid.task;
+ }
+
+ return NULL;
+}
+
+static int __taskdiag_dumpit(struct task_iter *iter,
+ struct task_diag_cb *cb, struct task_struct **start)
+{
+ struct user_namespace *userns = current_user_ns();
+ struct task_struct *task = *start;
+ int rc;
+
+ for (; task; task = iter_next(iter)) {
+ if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS))
+ continue;
+
+ rc = task_diag_fill(task, cb->resp, &iter->req,
+ cb, iter->ns, userns);
+ if (rc < 0) {
+ if (rc != -EMSGSIZE)
+ return rc;
+ break;
+ }
+ }
+ *start = task;
+
+ return 0;
+}
+
+static int taskdiag_dumpit(struct task_diag_cb *cb,
+ struct pid_namespace *pidns,
+ struct msghdr *msg, size_t len)
+{
+ struct sk_buff *skb = cb->resp;
+ struct task_struct *task;
+ struct task_iter iter;
+ struct nlattr *na;
+ size_t copied;
+ int err;
+
+ if (nlmsg_len(cb->nlh) < sizeof(iter.req))
+ return -EINVAL;
+
+ na = nlmsg_data(cb->nlh);
+ if (na->nla_type < 0)
+ return -EINVAL;
+
+ memcpy(&iter.req, na, sizeof(iter.req));
+
+ iter.ns = pidns;
+ iter.cb = cb;
+ iter.parent = NULL;
+ iter.pos = 0;
+ iter.task = NULL;
+
+ task = iter_start(&iter);
+ if (IS_ERR(task))
+ return PTR_ERR(task);
+
+ copied = 0;
+ while (1) {
+ err = __taskdiag_dumpit(&iter, cb, &task);
+ if (err < 0)
+ goto err;
+ if (skb->len == 0)
+ break;
+
+ err = skb_copy_datagram_msg(skb, 0, msg, skb->len);
+ if (err < 0)
+ goto err;
+
+ copied += skb->len;
+
+ skb_trim(skb, 0);
+ if (skb_tailroom(skb) + copied > len)
+ break;
+
+ if (signal_pending(current))
+ break;
+ }
+
+ iter_stop(&iter);
+ return copied;
+err:
+ iter_stop(&iter);
+ return err;
+}
+
+static ssize_t task_diag_write(struct file *f, const char __user *buf,
+ size_t len, loff_t *off)
+{
+ struct task_diag_cb *cb = f->private_data;
+ struct sk_buff *skb;
+ struct msghdr msg;
+ struct iovec iov;
+ int err;
+
+ if (cb->req)
+ return -EBUSY;
+ if (len < nlmsg_total_size(0))
+ return -EINVAL;
+
+ err = import_single_range(WRITE, (void __user *) buf, len,
+ &iov, &msg.msg_iter);
+ if (unlikely(err))
+ return err;
+
+ msg.msg_name = NULL;
+ msg.msg_control = NULL;
+ msg.msg_controllen = 0;
+ msg.msg_namelen = 0;
+ msg.msg_flags = 0;
+
+ skb = nlmsg_new(len, GFP_KERNEL);
+ if (skb == NULL)
+ return -ENOMEM;
+
+ if (memcpy_from_msg(skb_put(skb, len), &msg, len)) {
+ kfree_skb(skb);
+ return -EFAULT;
+ }
+
+ memset(cb, 0, sizeof(*cb));
+ cb->req = skb;
+ cb->nlh = nlmsg_hdr(skb);
+
+ return len;
+}
+
+static ssize_t task_diag_read(struct file *file, char __user *ubuf,
+ size_t len, loff_t *off)
+{
+ struct pid_namespace *ns = file_inode(file)->i_sb->s_fs_info;
+ struct task_diag_cb *cb = file->private_data;
+ struct iovec iov;
+ struct msghdr msg;
+ int size, err;
+
+ if (cb->req == NULL)
+ return 0;
+
+ err = import_single_range(READ, ubuf, len, &iov, &msg.msg_iter);
+ if (unlikely(err))
+ goto err;
+ msg.msg_control = NULL;
+ msg.msg_controllen = 0;
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+
+ if (!cb->resp) {
+ size = min_t(size_t, len, 16384);
+ cb->resp = alloc_skb(size, GFP_KERNEL);
+ if (cb->resp == NULL) {
+ err = -ENOMEM;
+ goto err;
+ }
+ /* Trim skb to allocated size. */
+ skb_reserve(cb->resp, skb_tailroom(cb->resp) - size);
+ }
+
+ err = taskdiag_dumpit(cb, ns, &msg, len);
+
+err:
+ skb_trim(cb->resp, 0);
+ if (err <= 0) {
+ kfree_skb(cb->req);
+ cb->req = NULL;
+ }
+
+ return err;
+}
+
+static int task_diag_open (struct inode *inode, struct file *f)
+{
+ f->private_data = kzalloc(sizeof(struct task_diag_cb), GFP_KERNEL);
+ if (f->private_data == NULL)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static int task_diag_release(struct inode *inode, struct file *f)
+{
+ struct task_diag_cb *cb = f->private_data;
+
+ kfree_skb(cb->req);
+ kfree_skb(cb->resp);
+
+ kfree(f->private_data);
+ return 0;
+}
+
+static const struct file_operations task_diag_fops = {
+ .owner = THIS_MODULE,
+ .open = task_diag_open,
+ .release = task_diag_release,
+ .write = task_diag_write,
+ .read = task_diag_read,
+};
+
+static __init int task_diag_init(void)
+{
+ if (!proc_create("task-diag", S_IRUGO | S_IWUGO, NULL, &task_diag_fops))
+ return -ENOMEM;
+
+ return 0;
+}
+
+static __exit void task_diag_exit(void)
+{
+ remove_proc_entry("task-diag", NULL);
+}
+
+module_init(task_diag_init);
+module_exit(task_diag_exit);
diff --git a/include/uapi/linux/task_diag.h b/include/uapi/linux/task_diag.h
new file mode 100644
index 0000000..ba0f71a
--- /dev/null
+++ b/include/uapi/linux/task_diag.h
@@ -0,0 +1,66 @@
+#ifndef _LINUX_TASK_DIAG_H
+#define _LINUX_TASK_DIAG_H
+
+#include <linux/types.h>
+#include <linux/netlink.h>
+#include <linux/capability.h>
+
+#define TASK_DIAG_CMD_GET 0xd101U
+
+struct task_diag_msg {
+ __u32 pid;
+ __u32 tgid;
+ __u32 flags;
+};
+
+enum {
+ TASK_DIAG_BASE = 0,
+
+ __TASK_DIAG_ATTR_MAX
+#define TASK_DIAG_ATTR_MAX (__TASK_DIAG_ATTR_MAX - 1)
+};
+
+#define TASK_DIAG_SHOW_BASE (1ULL << TASK_DIAG_BASE)
+
+enum {
+ TASK_DIAG_RUNNING,
+ TASK_DIAG_INTERRUPTIBLE,
+ TASK_DIAG_UNINTERRUPTIBLE,
+ TASK_DIAG_STOPPED,
+ TASK_DIAG_TRACE_STOP,
+ TASK_DIAG_DEAD,
+ TASK_DIAG_ZOMBIE,
+};
+
+#define TASK_DIAG_COMM_LEN 16
+
+struct task_diag_base {
+ __u32 tgid;
+ __u32 pid;
+ __u32 ppid;
+ __u32 tpid;
+ __u32 sid;
+ __u32 pgid;
+ __u8 state;
+ char comm[TASK_DIAG_COMM_LEN];
+};
+
+#define TASK_DIAG_DUMP_ALL 0
+#define TASK_DIAG_DUMP_ONE 1
+
+struct task_diag_pid {
+ __u64 show_flags;
+ __u64 dump_strategy;
+
+ __u32 pid;
+};
+
+enum {
+ TASK_DIAG_CMD_ATTR_UNSPEC = 0,
+ TASK_DIAG_CMD_ATTR_GET,
+ __TASK_DIAG_CMD_ATTR_MAX,
+};
+
+#define TASK_DIAG_CMD_ATTR_MAX (__TASK_DIAG_CMD_ATTR_MAX - 1)
+
+#endif /* _LINUX_TASK_DIAG_H */
--
2.5.5
[toc] | [next] | [standalone]
| From | Cyrill Gorcunov <gorcunov@gmail.com> |
|---|---|
| Date | 2016-04-12 09:10 +0200 |
| Subject | Re: [PATCH 04/15] task_diag: add a new interface to get information about tasks (v4) |
| Message-ID | <rn0Ct-3dN-3@gated-at.bofh.it> |
| In reply to | #1376336 |
On Mon, Apr 11, 2016 at 04:35:44PM -0700, Andrey Vagin wrote:
...
> +static int __taskdiag_dumpit(struct task_iter *iter,
> + struct task_diag_cb *cb, struct task_struct **start)
> +{
> + struct user_namespace *userns = current_user_ns();
> + struct task_struct *task = *start;
> + int rc;
> +
> + for (; task; task = iter_next(iter)) {
> + if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS))
> + continue;
> +
> + rc = task_diag_fill(task, cb->resp, &iter->req,
> + cb, iter->ns, userns);
> + if (rc < 0) {
> + if (rc != -EMSGSIZE)
> + return rc;
> + break;
> + }
> + }
> + *start = task;
task = NULL always here?
> +
> + return 0;
> +}
Cyrill
[toc] | [prev] | [next] | [standalone]
| From | Andrew Vagin <avagin@gmail.com> |
|---|---|
| Date | 2016-04-13 02:40 +0200 |
| Subject | Re: [PATCH 04/15] task_diag: add a new interface to get information about tasks (v4) |
| Message-ID | <rnh0C-8oX-11@gated-at.bofh.it> |
| In reply to | #1376517 |
On Tue, Apr 12, 2016 at 10:08:57AM +0300, Cyrill Gorcunov wrote:
> On Mon, Apr 11, 2016 at 04:35:44PM -0700, Andrey Vagin wrote:
> ...
> > +static int __taskdiag_dumpit(struct task_iter *iter,
> > + struct task_diag_cb *cb, struct task_struct **start)
> > +{
> > + struct user_namespace *userns = current_user_ns();
> > + struct task_struct *task = *start;
> > + int rc;
> > +
> > + for (; task; task = iter_next(iter)) {
> > + if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS))
> > + continue;
> > +
> > + rc = task_diag_fill(task, cb->resp, &iter->req,
> > + cb, iter->ns, userns);
> > + if (rc < 0) {
> > + if (rc != -EMSGSIZE)
> > + return rc;
> > + break;
task isn't NULL here
> > + }
> > + }
> > + *start = task;
>
> task = NULL always here?
No, it isn't if the loop is interrupted by break.
Thanks,
Andrew
[toc] | [prev] | [next] | [standalone]
| From | Cyrill Gorcunov <gorcunov@gmail.com> |
|---|---|
| Date | 2016-04-13 07:30 +0200 |
| Subject | Re: [PATCH 04/15] task_diag: add a new interface to get information about tasks (v4) |
| Message-ID | <rnlxg-49c-9@gated-at.bofh.it> |
| In reply to | #1377447 |
On Tue, Apr 12, 2016 at 05:39:14PM -0700, Andrew Vagin wrote: > > > > task = NULL always here? > > No, it isn't if the loop is interrupted by break. Yeah, managed to miss break, thanks!
[toc] | [prev] | [next] | [standalone]
| From | Andrew Vagin <avagin@virtuozzo.com> |
|---|---|
| Date | 2016-04-13 05:30 +0200 |
| Subject | Re: [PATCH 04/15] task_diag: add a new interface to get information about tasks (v4) |
| Message-ID | <rnjF7-2ok-1@gated-at.bofh.it> |
| In reply to | #1376336 |
On Tue, Apr 12, 2016 at 09:03:39AM +0800, kbuild test robot wrote: > Hi Andrey, > > [auto build test ERROR on v4.6-rc3] > [also build test ERROR on next-20160411] > [if your patch is applied to the wrong git tree, please drop us a note to help improving the system] > > url: https://github.com/0day-ci/linux/commits/Andrey-Vagin/task_diag-add-a-new-interface-to-get-information-about-processes-v3/20160412-074109 > config: microblaze-allmodconfig (attached as .config) > reproduce: > wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross > chmod +x ~/bin/make.cross > # save the attached .config to linux build tree > make.cross ARCH=microblaze > > Note: the linux-review/Andrey-Vagin/task_diag-add-a-new-interface-to-get-information-about-processes-v3/20160412-074109 HEAD 2e0f174ce7e6fddc8fdd89f3dbb8d990626358a0 builds fine. > It only hurts bisectibility. > > All errors (new ones prefixed by >>): > > >> fs/proc/task_diag.c:139:19: error: field 'tgid' has incomplete type > struct tgid_iter tgid; > ^ > fs/proc/task_diag.c: In function 'iter_start': > >> fs/proc/task_diag.c:187:3: error: implicit declaration of function 'next_tgid' [-Werror=implicit-function-declaration] > iter->tgid = next_tgid(iter->ns, iter->tgid); > ^ > cc1: some warnings being treated as errors > Unfortunately I forgot to include fs/proc/internal.h here. It will be included in the 6-th patch. I will fix this issue in a final version. Thanks, Andrew
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web