import PAGE_BOOST from N10 Lite

This commit is contained in:
renoxtv 2022-02-20 22:17:57 +03:00 committed by xxmustafacooTR
parent 77597e5802
commit 5a3fbbb8a4
No known key found for this signature in database
GPG key ID: 520B6FE385CBF5C9
9 changed files with 332 additions and 0 deletions

View file

@ -2079,6 +2079,10 @@ static inline bool may_mandlock(void)
* unixes. Our API is identical to OSF/1 to avoid making a mess of AMD * unixes. Our API is identical to OSF/1 to avoid making a mess of AMD
*/ */
#ifdef CONFIG_PAGE_BOOST_RECORDING
#include <linux/io_record.h>
#endif
SYSCALL_DEFINE2(umount, char __user *, name, int, flags) SYSCALL_DEFINE2(umount, char __user *, name, int, flags)
{ {
struct path path; struct path path;
@ -2092,6 +2096,9 @@ SYSCALL_DEFINE2(umount, char __user *, name, int, flags)
if (!may_mount()) if (!may_mount())
return -EPERM; return -EPERM;
#ifdef CONFIG_PAGE_BOOST_RECORDING
forced_init_record();
#endif
if (!(flags & UMOUNT_NOFOLLOW)) if (!(flags & UMOUNT_NOFOLLOW))
lookup_flags |= LOOKUP_FOLLOW; lookup_flags |= LOOKUP_FOLLOW;

View file

@ -99,6 +99,10 @@
#include "../../lib/kstrtox.h" #include "../../lib/kstrtox.h"
#ifdef CONFIG_PAGE_BOOST
#include <linux/delayacct.h>
#endif
/* NOTE: /* NOTE:
* Implementing inode permission operations in /proc is almost * Implementing inode permission operations in /proc is almost
* certainly an error. Permission checks need to happen during * certainly an error. Permission checks need to happen during
@ -496,6 +500,57 @@ static int proc_pid_stack(struct seq_file *m, struct pid_namespace *ns,
} }
#endif #endif
#ifdef CONFIG_PAGE_BOOST
static int proc_pid_ioinfo(struct seq_file *m, struct pid_namespace *ns,
struct pid *pid, struct task_struct *task)
{
struct task_io_accounting acct = task->ioac;
unsigned long flags;
int result;
result = mutex_lock_killable(&task->signal->cred_guard_mutex);
if (result)
return result;
if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)) {
result = -EACCES;
goto out_unlock;
}
if (lock_task_sighand(task, &flags)) {
struct task_struct *t = task;
task_io_accounting_add(&acct, &task->signal->ioac);
while_each_thread(task, t)
task_io_accounting_add(&acct, &t->ioac);
unlock_task_sighand(task, &flags);
}
seq_printf(m,
"%llu\n"
"%llu\n"
"%llu\n",
#ifdef CONFIG_TASK_XACCT
(unsigned long long)acct.rchar,
#else
(unsigned long long)0,
#endif
#ifdef CONFIG_TASK_IO_ACCOUNTING
(unsigned long long)acct.read_bytes,
#else
(unsigned long long)0,
#endif
(unsigned long long)delayacct_blkio_nsecs(task));
result = 0;
out_unlock:
mutex_unlock(&task->signal->cred_guard_mutex);
return result;
}
#endif
#ifdef CONFIG_SCHED_INFO #ifdef CONFIG_SCHED_INFO
/* /*
* Provides /proc/PID/schedstat * Provides /proc/PID/schedstat
@ -3175,6 +3230,13 @@ static const struct pid_entry tgid_base_stuff[] = {
ONE("statm", S_IRUGO, proc_pid_statm), ONE("statm", S_IRUGO, proc_pid_statm),
ONE("statlmkd", S_IRUGO, proc_pid_statlmkd), ONE("statlmkd", S_IRUGO, proc_pid_statlmkd),
REG("maps", S_IRUGO, proc_pid_maps_operations), REG("maps", S_IRUGO, proc_pid_maps_operations),
#ifdef CONFIG_PAGE_BOOST
REG("filemap_list", S_IRUGO, proc_pid_filemap_list_operations),
ONE("ioinfo", S_IRUGO, proc_pid_ioinfo),
#ifdef CONFIG_PAGE_BOOST_RECORDING
REG("io_record_control", S_IRUGO|S_IWUGO, proc_pid_io_record_operations),
#endif
#endif
#ifdef CONFIG_NUMA #ifdef CONFIG_NUMA
REG("numa_maps", S_IRUGO, proc_pid_numa_maps_operations), REG("numa_maps", S_IRUGO, proc_pid_numa_maps_operations),
#endif #endif

View file

@ -323,3 +323,19 @@ extern unsigned long task_statm(struct mm_struct *,
extern void task_statlmkd(struct mm_struct *, unsigned long *, extern void task_statlmkd(struct mm_struct *, unsigned long *,
unsigned long *, unsigned long *); unsigned long *, unsigned long *);
extern void task_mem(struct seq_file *, struct mm_struct *); extern void task_mem(struct seq_file *, struct mm_struct *);
#ifdef CONFIG_PAGE_BOOST
#include <linux/pagevec.h>
#define MAX_PAGE_BOOST_FILEPATH_LEN 256
struct proc_filemap_private {
struct proc_maps_private maps_private;
struct file *target_file;
char target_file_name[MAX_PAGE_BOOST_FILEPATH_LEN + 1];
bool show_list; /* true : filemap_list, false : filemap_info */
};
extern const struct file_operations proc_pid_filemap_list_operations;
extern const struct file_operations proc_pid_io_record_operations;
#endif

View file

@ -2017,3 +2017,183 @@ const struct file_operations proc_tid_numa_maps_operations = {
.release = proc_map_release, .release = proc_map_release,
}; };
#endif /* CONFIG_NUMA */ #endif /* CONFIG_NUMA */
#ifdef CONFIG_PAGE_BOOST
/*
* Currently, target_file_name is shared by all filemap_info nodes
* as we do not access this node in parallel. (do not need synchronization also)
*/
#include <linux/io_record.h>
#include <linux/atomic.h>
static atomic_t filemap_fd_opened = ATOMIC_INIT(0);
char target_file_name[MAX_PAGE_BOOST_FILEPATH_LEN + 1] = "";
static inline bool try_to_get_filemap_fd(void)
{
/* only 1 context is allowed at a time */
if (atomic_inc_return(&filemap_fd_opened) == 1)
return true;
else {
atomic_dec(&filemap_fd_opened);
return false;
}
}
static inline void put_filemap_fd(void)
{
atomic_dec(&filemap_fd_opened);
}
static void
show_filemap_vma(struct seq_file *m, struct vm_area_struct *vma)
{
struct file *file = vma->vm_file;
struct proc_filemap_private *priv = m->private;
char strbuf[MAX_PAGE_BOOST_FILEPATH_LEN];
char *pathname;
if (!file)
return;
pathname = d_path(&file->f_path, strbuf, MAX_PAGE_BOOST_FILEPATH_LEN);
if (IS_ERR(pathname))
return;
if (priv->show_list) {
if (!strncmp(pathname, "/data", 5) ||
!strncmp(pathname, "/system", 7)) {
seq_puts(m, pathname);
seq_putc(m, '\n');
}
}
}
static int show_filemap(struct seq_file *m, void *v)
{
show_filemap_vma(m, v);
m_cache_vma(m, v);
return 0;
}
static const struct seq_operations proc_pid_filemap_op = {
.start = m_start,
.next = m_next,
.stop = m_stop,
.show = show_filemap,
};
static int pid_filemap_list_open(struct inode *inode, struct file *file)
{
int psize = sizeof(struct proc_filemap_private);
const struct seq_operations *ops = &proc_pid_filemap_op;
struct proc_filemap_private *priv = __seq_open_private(file, ops,
psize);
if (!priv)
return -ENOMEM;
if (!try_to_get_filemap_fd())
return -EINVAL;
priv->maps_private.inode = inode;
priv->maps_private.mm = proc_mem_open(inode, PTRACE_MODE_READ);
priv->show_list = true;
if (IS_ERR(priv->maps_private.mm)) {
int err = PTR_ERR(priv->maps_private.mm);
put_filemap_fd();
seq_release_private(inode, file);
return err;
}
return 0;
}
/* common release for filemap_list and filemap_info */
static int proc_filemap_release(struct inode *inode, struct file *file)
{
struct seq_file *seq = file->private_data;
struct proc_filemap_private *priv = seq->private;
if (priv->maps_private.mm)
mmdrop(priv->maps_private.mm);
put_filemap_fd();
return seq_release_private(inode, file);
}
/* List mapped files for this process */
const struct file_operations proc_pid_filemap_list_operations = {
.open = pid_filemap_list_open,
.read = seq_read,
.llseek = seq_lseek,
.release = proc_filemap_release,
};
#ifdef CONFIG_PAGE_BOOST_RECORDING
static ssize_t pid_io_record_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
return read_record(buf, count, ppos);
}
static ssize_t pid_io_record_write(struct file *file,
const char __user *buf,
size_t count, loff_t *ppos)
{
char buffer[PROC_NUMBUF];
int itype;
enum io_record_cmd_types type;
int rv;
struct task_struct *task;
bool ret = true;
memset(buffer, 0, sizeof(buffer));
if (count > sizeof(buffer) - 1)
count = sizeof(buffer) - 1;
if (copy_from_user(buffer, buf, count))
return -EFAULT;
rv = kstrtoint(strstrip(buffer), 10, &itype);
if (rv < 0)
return rv;
task = get_proc_task(file_inode(file));
if (!task)
return -EFAULT;
type = (enum io_record_cmd_types)itype;
if (type < IO_RECORD_INIT || type > IO_RECORD_POST_PROCESSING) {
put_task_struct(task);
return -EINVAL;
}
switch (type) {
case IO_RECORD_INIT:
ret = init_record();
break;
case IO_RECORD_START:
ret = start_record((int)task_pid_nr(task));
break;
case IO_RECORD_STOP:
ret = stop_record();
break;
case IO_RECORD_POST_PROCESSING:
ret = post_processing_records();
break;
default:
break;
}
put_task_struct(task);
if (!ret)
count = -EINVAL;
return count;
}
const struct file_operations proc_pid_io_record_operations = {
.read = pid_io_record_read,
.write = pid_io_record_write,
.llseek = noop_llseek,
};
#endif
#endif

View file

@ -80,6 +80,9 @@ extern void __delayacct_blkio_start(void);
extern void __delayacct_blkio_end(void); extern void __delayacct_blkio_end(void);
extern int __delayacct_add_tsk(struct taskstats *, struct task_struct *); extern int __delayacct_add_tsk(struct taskstats *, struct task_struct *);
extern __u64 __delayacct_blkio_ticks(struct task_struct *); extern __u64 __delayacct_blkio_ticks(struct task_struct *);
#ifdef CONFIG_PAGE_BOOST
extern __u64 __delayacct_blkio_nsecs(struct task_struct *);
#endif
extern void __delayacct_freepages_start(void); extern void __delayacct_freepages_start(void);
extern void __delayacct_freepages_end(void); extern void __delayacct_freepages_end(void);
extern void __delayacct_thrashing_start(void); extern void __delayacct_thrashing_start(void);
@ -152,6 +155,15 @@ static inline __u64 delayacct_blkio_ticks(struct task_struct *tsk)
return 0; return 0;
} }
#ifdef CONFIG_PAGE_BOOST
static inline __u64 delayacct_blkio_nsecs(struct task_struct *tsk)
{
if (tsk->delays)
return __delayacct_blkio_nsecs(tsk);
return 0;
}
#endif
static inline void delayacct_freepages_start(void) static inline void delayacct_freepages_start(void)
{ {
if (current->delays) if (current->delays)
@ -196,6 +208,10 @@ static inline int delayacct_add_tsk(struct taskstats *d,
{ return 0; } { return 0; }
static inline __u64 delayacct_blkio_ticks(struct task_struct *tsk) static inline __u64 delayacct_blkio_ticks(struct task_struct *tsk)
{ return 0; } { return 0; }
#ifdef CONFIG_PAGE_BOOST
static inline __u64 delayacct_blkio_nsecs(struct task_struct *tsk)
{ return 0; }
#endif
static inline int delayacct_is_task_waiting_on_io(struct task_struct *p) static inline int delayacct_is_task_waiting_on_io(struct task_struct *p)
{ return 0; } { return 0; }
static inline void delayacct_freepages_start(void) static inline void delayacct_freepages_start(void)

23
include/linux/io_record.h Normal file
View file

@ -0,0 +1,23 @@
#ifndef _LINUX_IO_RECORD_H
#define _LINUX_IO_RECORD_H
enum io_record_cmd_types {
IO_RECORD_INIT = 1,
IO_RECORD_START = 2,
IO_RECORD_STOP = 3,
IO_RECORD_POST_PROCESSING = 4,
IO_RECORD_POST_PROCESSING_DONE = 5,
};
bool start_record(int pid);
bool stop_record(void);
bool post_processing_records(void);
bool init_record(void);
bool forced_init_record(void);
ssize_t read_record(char __user *buf, size_t count, loff_t *ppos);
void record_io_info(struct file *file, pgoff_t offset,
unsigned long req_size);
#endif /* _LINUX_IO_RECORD_H */

View file

@ -147,6 +147,19 @@ __u64 __delayacct_blkio_ticks(struct task_struct *tsk)
return ret; return ret;
} }
#ifdef CONFIG_PAGE_BOOST
__u64 __delayacct_blkio_nsecs(struct task_struct *tsk)
{
__u64 ret;
unsigned long flags;
spin_lock_irqsave(&tsk->delays->lock, flags);
ret = tsk->delays->blkio_delay + tsk->delays->swapin_delay;
spin_unlock_irqrestore(&tsk->delays->lock, flags);
return ret;
}
#endif
void __delayacct_freepages_start(void) void __delayacct_freepages_start(void)
{ {
current->delays->freepages_start = ktime_get_ns(); current->delays->freepages_start = ktime_get_ns();

View file

@ -101,3 +101,4 @@ obj-$(CONFIG_IDLE_PAGE_TRACKING) += page_idle.o
obj-$(CONFIG_FRAME_VECTOR) += frame_vector.o obj-$(CONFIG_FRAME_VECTOR) += frame_vector.o
obj-$(CONFIG_DEBUG_PAGE_REF) += debug_page_ref.o obj-$(CONFIG_DEBUG_PAGE_REF) += debug_page_ref.o
obj-$(CONFIG_HARDENED_USERCOPY) += usercopy.o obj-$(CONFIG_HARDENED_USERCOPY) += usercopy.o
obj-$(CONFIG_PAGE_BOOST_RECORDING) += io_record.o

View file

@ -45,6 +45,12 @@
#ifdef CONFIG_FSCRYPT_SDP #ifdef CONFIG_FSCRYPT_SDP
#include <linux/fscrypto_sdp_cache.h> #include <linux/fscrypto_sdp_cache.h>
#endif #endif
#ifdef CONFIG_PAGE_BOOST_RECORDING
#include <linux/io_record.h>
#endif
#define CREATE_TRACE_POINTS #define CREATE_TRACE_POINTS
#include <trace/events/filemap.h> #include <trace/events/filemap.h>
@ -1863,6 +1869,9 @@ static ssize_t do_generic_file_read(struct file *filp, loff_t *ppos,
prev_offset = ra->prev_pos & (PAGE_SIZE-1); prev_offset = ra->prev_pos & (PAGE_SIZE-1);
last_index = (*ppos + iter->count + PAGE_SIZE-1) >> PAGE_SHIFT; last_index = (*ppos + iter->count + PAGE_SIZE-1) >> PAGE_SHIFT;
offset = *ppos & ~PAGE_MASK; offset = *ppos & ~PAGE_MASK;
#ifdef CONFIG_PAGE_BOOST_RECORDING
record_io_info(filp, index, last_index - index);
#endif
for (;;) { for (;;) {
struct page *page; struct page *page;
@ -2536,6 +2545,11 @@ next:
break; break;
} }
rcu_read_unlock(); rcu_read_unlock();
#ifdef CONFIG_PAGE_BOOST_RECORDING
/* end_pgoff is inclusive */
record_io_info(file, start_pgoff, last_pgoff - start_pgoff + 1);
#endif
} }
EXPORT_SYMBOL(filemap_map_pages); EXPORT_SYMBOL(filemap_map_pages);