import PAGE_BOOST from N10 Lite
This commit is contained in:
parent
77597e5802
commit
5a3fbbb8a4
9 changed files with 332 additions and 0 deletions
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
23
include/linux/io_record.h
Normal 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 */
|
|
@ -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();
|
||||||
|
|
|
@ -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
|
||||||
|
|
14
mm/filemap.c
14
mm/filemap.c
|
@ -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);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue