hc
2024-05-10 ee930fffee469d076998274a2ca55e13dc1efb67
kernel/drivers/misc/uid_sys_stats.c
....@@ -14,7 +14,6 @@
1414 */
1515
1616 #include <linux/atomic.h>
17
-#include <linux/cpufreq_times.h>
1817 #include <linux/err.h>
1918 #include <linux/hashtable.h>
2019 #include <linux/init.h>
....@@ -78,12 +77,12 @@
7877 #endif
7978 };
8079
81
-static u64 compute_write_bytes(struct task_struct *task)
80
+static u64 compute_write_bytes(struct task_io_accounting *ioac)
8281 {
83
- if (task->ioac.write_bytes <= task->ioac.cancelled_write_bytes)
82
+ if (ioac->write_bytes <= ioac->cancelled_write_bytes)
8483 return 0;
8584
86
- return task->ioac.write_bytes - task->ioac.cancelled_write_bytes;
85
+ return ioac->write_bytes - ioac->cancelled_write_bytes;
8786 }
8887
8988 static void compute_io_bucket_stats(struct io_stats *io_bucket,
....@@ -137,7 +136,7 @@
137136
138137 /* next the executable file name */
139138 if (mm) {
140
- down_read(&mm->mmap_sem);
139
+ mmap_write_lock(mm);
141140 if (mm->exe_file) {
142141 char *pathname = d_path(&mm->exe_file->f_path, buf,
143142 unused_len);
....@@ -150,7 +149,7 @@
150149 unused_len--;
151150 }
152151 }
153
- up_read(&mm->mmap_sem);
152
+ mmap_write_unlock(mm);
154153 }
155154 unused_len -= len;
156155
....@@ -240,17 +239,16 @@
240239 }
241240 }
242241
243
-static void add_uid_tasks_io_stats(struct uid_entry *uid_entry,
244
- struct task_struct *task, int slot)
242
+static void add_uid_tasks_io_stats(struct task_entry *task_entry,
243
+ struct task_io_accounting *ioac, int slot)
245244 {
246
- struct task_entry *task_entry = find_or_register_task(uid_entry, task);
247245 struct io_stats *task_io_slot = &task_entry->io[slot];
248246
249
- task_io_slot->read_bytes += task->ioac.read_bytes;
250
- task_io_slot->write_bytes += compute_write_bytes(task);
251
- task_io_slot->rchar += task->ioac.rchar;
252
- task_io_slot->wchar += task->ioac.wchar;
253
- task_io_slot->fsync += task->ioac.syscfs;
247
+ task_io_slot->read_bytes += ioac->read_bytes;
248
+ task_io_slot->write_bytes += compute_write_bytes(ioac);
249
+ task_io_slot->rchar += ioac->rchar;
250
+ task_io_slot->wchar += ioac->wchar;
251
+ task_io_slot->fsync += ioac->syscfs;
254252 }
255253
256254 static void compute_io_uid_tasks(struct uid_entry *uid_entry)
....@@ -291,8 +289,6 @@
291289 #else
292290 static void remove_uid_tasks(struct uid_entry *uid_entry) {};
293291 static void set_io_uid_tasks_zero(struct uid_entry *uid_entry) {};
294
-static void add_uid_tasks_io_stats(struct uid_entry *uid_entry,
295
- struct task_struct *task, int slot) {};
296292 static void compute_io_uid_tasks(struct uid_entry *uid_entry) {};
297293 static void show_io_uid_tasks(struct seq_file *m,
298294 struct uid_entry *uid_entry) {}
....@@ -385,11 +381,11 @@
385381 return single_open(file, uid_cputime_show, PDE_DATA(inode));
386382 }
387383
388
-static const struct file_operations uid_cputime_fops = {
389
- .open = uid_cputime_open,
390
- .read = seq_read,
391
- .llseek = seq_lseek,
392
- .release = single_release,
384
+static const struct proc_ops uid_cputime_fops = {
385
+ .proc_open = uid_cputime_open,
386
+ .proc_read = seq_read,
387
+ .proc_lseek = seq_lseek,
388
+ .proc_release = single_release,
393389 };
394390
395391 static int uid_remove_open(struct inode *inode, struct file *file)
....@@ -404,8 +400,7 @@
404400 struct hlist_node *tmp;
405401 char uids[128];
406402 char *start_uid, *end_uid = NULL;
407
- uid_t uid_start = 0, uid_end = 0;
408
- u64 uid;
403
+ long int uid_start = 0, uid_end = 0;
409404
410405 if (count >= sizeof(uids))
411406 count = sizeof(uids) - 1;
....@@ -420,20 +415,17 @@
420415 if (!start_uid || !end_uid)
421416 return -EINVAL;
422417
423
- if (kstrtouint(start_uid, 10, &uid_start) != 0 ||
424
- kstrtouint(end_uid, 10, &uid_end) != 0) {
418
+ if (kstrtol(start_uid, 10, &uid_start) != 0 ||
419
+ kstrtol(end_uid, 10, &uid_end) != 0) {
425420 return -EINVAL;
426421 }
427422
428
- /* Also remove uids from /proc/uid_time_in_state */
429
- cpufreq_task_times_remove_uids(uid_start, uid_end);
430
-
431423 rt_mutex_lock(&uid_lock);
432424
433
- for (uid = uid_start; uid <= uid_end; uid++) {
425
+ for (; uid_start <= uid_end; uid_start++) {
434426 hash_for_each_possible_safe(hash_table, uid_entry, tmp,
435
- hash, uid) {
436
- if (uid == uid_entry->uid) {
427
+ hash, (uid_t)uid_start) {
428
+ if (uid_start == uid_entry->uid) {
437429 remove_uid_tasks(uid_entry);
438430 hash_del(&uid_entry->hash);
439431 kfree(uid_entry);
....@@ -445,29 +437,38 @@
445437 return count;
446438 }
447439
448
-static const struct file_operations uid_remove_fops = {
449
- .open = uid_remove_open,
450
- .release = single_release,
451
- .write = uid_remove_write,
440
+static const struct proc_ops uid_remove_fops = {
441
+ .proc_open = uid_remove_open,
442
+ .proc_release = single_release,
443
+ .proc_write = uid_remove_write,
452444 };
453445
446
+static void __add_uid_io_stats(struct uid_entry *uid_entry,
447
+ struct task_io_accounting *ioac, int slot)
448
+{
449
+ struct io_stats *io_slot = &uid_entry->io[slot];
450
+
451
+ io_slot->read_bytes += ioac->read_bytes;
452
+ io_slot->write_bytes += compute_write_bytes(ioac);
453
+ io_slot->rchar += ioac->rchar;
454
+ io_slot->wchar += ioac->wchar;
455
+ io_slot->fsync += ioac->syscfs;
456
+}
454457
455458 static void add_uid_io_stats(struct uid_entry *uid_entry,
456459 struct task_struct *task, int slot)
457460 {
458
- struct io_stats *io_slot = &uid_entry->io[slot];
461
+ struct task_entry *task_entry __maybe_unused;
459462
460463 /* avoid double accounting of dying threads */
461464 if (slot != UID_STATE_DEAD_TASKS && (task->flags & PF_EXITING))
462465 return;
463466
464
- io_slot->read_bytes += task->ioac.read_bytes;
465
- io_slot->write_bytes += compute_write_bytes(task);
466
- io_slot->rchar += task->ioac.rchar;
467
- io_slot->wchar += task->ioac.wchar;
468
- io_slot->fsync += task->ioac.syscfs;
469
-
470
- add_uid_tasks_io_stats(uid_entry, task, slot);
467
+#ifdef CONFIG_UID_SYS_STATS_DEBUG
468
+ task_entry = find_or_register_task(uid_entry, task);
469
+ add_uid_tasks_io_stats(task_entry, &task->ioac, slot);
470
+#endif
471
+ __add_uid_io_stats(uid_entry, &task->ioac, slot);
471472 }
472473
473474 static void update_io_stats_all_locked(void)
....@@ -564,11 +565,11 @@
564565 return single_open(file, uid_io_show, PDE_DATA(inode));
565566 }
566567
567
-static const struct file_operations uid_io_fops = {
568
- .open = uid_io_open,
569
- .read = seq_read,
570
- .llseek = seq_lseek,
571
- .release = single_release,
568
+static const struct proc_ops uid_io_fops = {
569
+ .proc_open = uid_io_open,
570
+ .proc_read = seq_read,
571
+ .proc_lseek = seq_lseek,
572
+ .proc_release = single_release,
572573 };
573574
574575 static int uid_procstat_open(struct inode *inode, struct file *file)
....@@ -621,11 +622,53 @@
621622 return count;
622623 }
623624
624
-static const struct file_operations uid_procstat_fops = {
625
- .open = uid_procstat_open,
626
- .release = single_release,
627
- .write = uid_procstat_write,
625
+static const struct proc_ops uid_procstat_fops = {
626
+ .proc_open = uid_procstat_open,
627
+ .proc_release = single_release,
628
+ .proc_write = uid_procstat_write,
628629 };
630
+
631
+struct update_stats_work {
632
+ struct work_struct work;
633
+ uid_t uid;
634
+#ifdef CONFIG_UID_SYS_STATS_DEBUG
635
+ struct task_struct *task;
636
+#endif
637
+ struct task_io_accounting ioac;
638
+ u64 utime;
639
+ u64 stime;
640
+};
641
+
642
+static void update_stats_workfn(struct work_struct *work)
643
+{
644
+ struct update_stats_work *usw =
645
+ container_of(work, struct update_stats_work, work);
646
+ struct uid_entry *uid_entry;
647
+ struct task_entry *task_entry __maybe_unused;
648
+
649
+ rt_mutex_lock(&uid_lock);
650
+ uid_entry = find_uid_entry(usw->uid);
651
+ if (!uid_entry)
652
+ goto exit;
653
+
654
+ uid_entry->utime += usw->utime;
655
+ uid_entry->stime += usw->stime;
656
+
657
+#ifdef CONFIG_UID_SYS_STATS_DEBUG
658
+ task_entry = find_task_entry(uid_entry, usw->task);
659
+ if (!task_entry)
660
+ goto exit;
661
+ add_uid_tasks_io_stats(task_entry, &usw->ioac,
662
+ UID_STATE_DEAD_TASKS);
663
+#endif
664
+ __add_uid_io_stats(uid_entry, &usw->ioac, UID_STATE_DEAD_TASKS);
665
+exit:
666
+ rt_mutex_unlock(&uid_lock);
667
+#ifdef CONFIG_UID_SYS_STATS_DEBUG
668
+ put_task_struct(usw->task);
669
+#endif
670
+ kfree(usw);
671
+}
629672
630673 static int process_notifier(struct notifier_block *self,
631674 unsigned long cmd, void *v)
....@@ -638,8 +681,28 @@
638681 if (!task)
639682 return NOTIFY_OK;
640683
641
- rt_mutex_lock(&uid_lock);
642684 uid = from_kuid_munged(current_user_ns(), task_uid(task));
685
+ if (!rt_mutex_trylock(&uid_lock)) {
686
+ struct update_stats_work *usw;
687
+
688
+ usw = kmalloc(sizeof(struct update_stats_work), GFP_KERNEL);
689
+ if (usw) {
690
+ INIT_WORK(&usw->work, update_stats_workfn);
691
+ usw->uid = uid;
692
+#ifdef CONFIG_UID_SYS_STATS_DEBUG
693
+ usw->task = get_task_struct(task);
694
+#endif
695
+ /*
696
+ * Copy task->ioac since task might be destroyed before
697
+ * the work is later performed.
698
+ */
699
+ usw->ioac = task->ioac;
700
+ task_cputime_adjusted(task, &usw->utime, &usw->stime);
701
+ schedule_work(&usw->work);
702
+ }
703
+ return NOTIFY_OK;
704
+ }
705
+
643706 uid_entry = find_or_register_uid(uid);
644707 if (!uid_entry) {
645708 pr_err("%s: failed to find uid %d\n", __func__, uid);