blob: 8c6dba9b2fba0daf423edb40ffa2a1c5d2246526 [file] [log] [blame]
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright 2019 Google, Inc.
*
* Support for setting tasks as latency sensitive
* using /proc/pid/tasks/tid/latency_sensitive interface.
*/
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/ptrace.h>
#include <linux/sched/task.h>
#include <linux/sched/latsense.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/fs_struct.h>
#include "internal.h"
/*
* Print out latsense related information:
*/
static int sched_latsense_show(struct seq_file *m, void *v)
{
struct inode *inode = m->private;
struct task_struct *p;
p = get_proc_task(inode);
if (!p)
return -ESRCH;
seq_printf(m, "%d\n", !!proc_sched_get_latency_sensitive(p));
put_task_struct(p);
return 0;
}
static ssize_t
sched_latsense_write(struct file *file, const char __user *buf,
size_t count, loff_t *offset)
{
struct inode *inode = file_inode(file);
struct task_struct *p;
char buffer[PROC_NUMBUF];
int val;
int err;
memset(buffer, 0, sizeof(buffer));
if (count > sizeof(buffer) - 1)
count = sizeof(buffer) - 1;
if (copy_from_user(buffer, buf, count))
return -EFAULT;
err = kstrtoint(strstrip(buffer), 0, &val);
if (err < 0)
return err;
if (val != 0 && val != 1)
return -EINVAL;
p = get_proc_task(inode);
if (!p)
return -ESRCH;
err = proc_sched_set_latency_sensitive(p, val);
if (err)
count = err;
put_task_struct(p);
return count;
}
static int sched_latsense_access(struct inode *inode, fmode_t mode)
{
struct task_struct *p;
int ret = -EACCES;
if (!(mode & FMODE_WRITE))
return 0;
p = get_proc_task(inode);
if (!p)
return -ESRCH;
if (ptrace_may_access(p, PTRACE_MODE_ATTACH_REALCREDS) ||
capable(CAP_SYS_NICE)) {
ret = 0;
}
put_task_struct(p);
return ret;
}
static int sched_latsense_open(struct inode *inode, struct file *filp)
{
int ret;
ret = sched_latsense_access(inode, filp->f_mode);
if (ret < 0)
return ret;
ret = single_open(filp, sched_latsense_show, NULL);
if (!ret) {
struct seq_file *m = filp->private_data;
m->private = inode;
}
return ret;
}
const struct file_operations proc_tid_latsense_operations = {
.open = sched_latsense_open,
.read = seq_read,
.write = sched_latsense_write,
.llseek = seq_lseek,
.release = single_release,
};