}
 
 #ifdef CONFIG_TASK_IO_ACCOUNTING
-static int proc_pid_io_accounting(struct task_struct *task, char *buffer)
-{
+static int do_io_accounting(struct task_struct *task, char *buffer, int whole)
+{
+       u64 rchar, wchar, syscr, syscw;
+       struct task_io_accounting ioac;
+
+       if (!whole) {
+               rchar = task->rchar;
+               wchar = task->wchar;
+               syscr = task->syscr;
+               syscw = task->syscw;
+               memcpy(&ioac, &task->ioac, sizeof(ioac));
+       } else {
+               unsigned long flags;
+               struct task_struct *t = task;
+               rchar = wchar = syscr = syscw = 0;
+               memset(&ioac, 0, sizeof(ioac));
+
+               rcu_read_lock();
+               do {
+                       rchar += t->rchar;
+                       wchar += t->wchar;
+                       syscr += t->syscr;
+                       syscw += t->syscw;
+
+                       ioac.read_bytes += t->ioac.read_bytes;
+                       ioac.write_bytes += t->ioac.write_bytes;
+                       ioac.cancelled_write_bytes +=
+                                       t->ioac.cancelled_write_bytes;
+                       t = next_thread(t);
+               } while (t != task);
+               rcu_read_unlock();
+
+               if (lock_task_sighand(task, &flags)) {
+                       struct signal_struct *sig = task->signal;
+
+                       rchar += sig->rchar;
+                       wchar += sig->wchar;
+                       syscr += sig->syscr;
+                       syscw += sig->syscw;
+
+                       ioac.read_bytes += sig->ioac.read_bytes;
+                       ioac.write_bytes += sig->ioac.write_bytes;
+                       ioac.cancelled_write_bytes +=
+                                       sig->ioac.cancelled_write_bytes;
+
+                       unlock_task_sighand(task, &flags);
+               }
+       }
+
        return sprintf(buffer,
-#ifdef CONFIG_TASK_XACCT
                        "rchar: %llu\n"
                        "wchar: %llu\n"
                        "syscr: %llu\n"
                        "syscw: %llu\n"
-#endif
                        "read_bytes: %llu\n"
                        "write_bytes: %llu\n"
                        "cancelled_write_bytes: %llu\n",
-#ifdef CONFIG_TASK_XACCT
-                       (unsigned long long)task->rchar,
-                       (unsigned long long)task->wchar,
-                       (unsigned long long)task->syscr,
-                       (unsigned long long)task->syscw,
-#endif
-                       (unsigned long long)task->ioac.read_bytes,
-                       (unsigned long long)task->ioac.write_bytes,
-                       (unsigned long long)task->ioac.cancelled_write_bytes);
+                       (unsigned long long)rchar,
+                       (unsigned long long)wchar,
+                       (unsigned long long)syscr,
+                       (unsigned long long)syscw,
+                       (unsigned long long)ioac.read_bytes,
+                       (unsigned long long)ioac.write_bytes,
+                       (unsigned long long)ioac.cancelled_write_bytes);
+}
+
+static int proc_tid_io_accounting(struct task_struct *task, char *buffer)
+{
+       return do_io_accounting(task, buffer, 0);
 }
-#endif
+
+static int proc_tgid_io_accounting(struct task_struct *task, char *buffer)
+{
+       return do_io_accounting(task, buffer, 1);
+}
+#endif /* CONFIG_TASK_IO_ACCOUNTING */
 
 /*
  * Thread groups
        REG("coredump_filter", S_IRUGO|S_IWUSR, coredump_filter),
 #endif
 #ifdef CONFIG_TASK_IO_ACCOUNTING
-       INF("io",       S_IRUGO, pid_io_accounting),
+       INF("io",       S_IRUGO, tgid_io_accounting),
 #endif
 };
 
 #ifdef CONFIG_FAULT_INJECTION
        REG("make-it-fail", S_IRUGO|S_IWUSR, fault_inject),
 #endif
+#ifdef CONFIG_TASK_IO_ACCOUNTING
+       INF("io",       S_IRUGO, tid_io_accounting),
+#endif
 };
 
 static int proc_tid_base_readdir(struct file * filp,
 
                sig->nivcsw += tsk->nivcsw;
                sig->inblock += task_io_get_inblock(tsk);
                sig->oublock += task_io_get_oublock(tsk);
+#ifdef CONFIG_TASK_XACCT
+               sig->rchar += tsk->rchar;
+               sig->wchar += tsk->wchar;
+               sig->syscr += tsk->syscr;
+               sig->syscw += tsk->syscw;
+#endif /* CONFIG_TASK_XACCT */
+#ifdef CONFIG_TASK_IO_ACCOUNTING
+               sig->ioac.read_bytes += tsk->ioac.read_bytes;
+               sig->ioac.write_bytes += tsk->ioac.write_bytes;
+               sig->ioac.cancelled_write_bytes +=
+                                       tsk->ioac.cancelled_write_bytes;
+#endif /* CONFIG_TASK_IO_ACCOUNTING */
                sig->sum_sched_runtime += tsk->se.sum_exec_runtime;
                sig = NULL; /* Marker for below. */
        }
                psig->coublock +=
                        task_io_get_oublock(p) +
                        sig->oublock + sig->coublock;
+#ifdef CONFIG_TASK_XACCT
+               psig->rchar += p->rchar + sig->rchar;
+               psig->wchar += p->wchar + sig->wchar;
+               psig->syscr += p->syscr + sig->syscr;
+               psig->syscw += p->syscw + sig->syscw;
+#endif /* CONFIG_TASK_XACCT */
+#ifdef CONFIG_TASK_IO_ACCOUNTING
+               psig->ioac.read_bytes +=
+                       p->ioac.read_bytes + sig->ioac.read_bytes;
+               psig->ioac.write_bytes +=
+                       p->ioac.write_bytes + sig->ioac.write_bytes;
+               psig->ioac.cancelled_write_bytes +=
+                               p->ioac.cancelled_write_bytes +
+                               sig->ioac.cancelled_write_bytes;
+#endif /* CONFIG_TASK_IO_ACCOUNTING */
                spin_unlock_irq(&p->parent->sighand->siglock);
        }