This commit is contained in:
zy
2023-11-16 14:07:37 +08:00
parent 1e9c7be927
commit bd277b53c5
5 changed files with 834 additions and 0 deletions

189
source/buffer/internal.h Normal file
View File

@@ -0,0 +1,189 @@
// /*
// * Linux内核诊断工具--杂项定义头文件
// *
// * Copyright (C) 2020 Alibaba Ltd.
// *
// * 作者: Baoyou Xie <baoyou.xie@linux.alibaba.com>
// *
// * License terms: GNU General Public License (GPL) version 3
// *
// */
// #include <string>
// #include <set>
// #include "uapi/ali_diagnose.h"
// #include "json/json.h"
// #include <fcntl.h>
// #include <sys/ioctl.h>
// #include <unistd.h>
// #include "debug.h"
// extern std::set<int> g_proc_map;
// int run_trace_main(int argc, char **argv);
// int sys_delay_main(int argc, char **argv);
// int sched_delay_main(int argc, char **argv);
// int throttle_delay_main(int argc, char **argv);
// int load_monitor_main(int argc, char **argv);
// int exit_monitor_main(int argc, char **argv);
// int utilization_main(int argc, char **argv);
// int perf_main(int argc, char **argv);
// int tcp_retrans_main(int argc, char **argv);
// int tcp_connect_main(int argc, char **argv);
// int rw_top_main(int argc, char **argv);
// int irq_delay_main(int argc, char **argv);
// int mutex_monitor_main(int argc, char **argv);
// int alloc_top_main(int argc, char **argv);
// int alloc_load_main(int argc, char **argv);
// int drop_packet_main(int argc, char **argv);
// int fs_orphan_main(int argc, char **argv);
// int df_du_main(int argc, char **argv);
// int exec_monitor_main(int argc, char **argv);
// int fs_shm_main(int argc, char **argv);
// int irq_stats_main(int argc, char **argv);
// int irq_trace_main(int argc, char **argv);
// int kprobe_main(int argc, char **argv);
// int mm_leak_main(int argc, char **argv);
// int proc_monitor_main(int argc, char **argv);
// int runq_info_main(int argc, char **argv);
// int reboot_main(int argc, char **argv);
// int pi_main(int argc, char *argv[]);
// int memcpy_main(int argc, char* argv[]);
// int md5_main(int argc, char *argv[]);
// int net_bandwidth_main(int argc, char *argv[]);
// int sig_info_main(int argc, char *argv[]);
// int task_monitor_main(int argc, char **argv);
// int rw_sem_main(int argc, char **argv);
// int rss_monitor_main(int argc, char **argv);
// void usage_run_trace(void);
// void usage_sys_delay(void);
// void usage_load_monitor(void);
// void usage_exit_monitor(void);
// void usage_utilization(void);
// void usage_perf();
// void usage_tcp_retrans();
// void usage_rw_top();
// void usage_irq_delay();
// void usage_mutex_monitor();
// void usage_alloc_top();
// void usage_drop_packet();
// void usage_fs_orphan();
// void usage_exec_monitor();
// void usage_fs_shm();
// void usage_irq_stats();
// void usage_irq_trace();
// void usage_kprobe();
// void usage_mm_leak();
// void usage_testcase(void);
// void usage_pupil(void);
// void usage_sched_delay(void);
// void usage_reboot(void);
// void usage_test_memcpy(void);
// void usage_test_pi(void);
// void usage_test_md5(void);
// void usage_net_bandwidth(void);
// void usage_sig_info(void);
// void usage_task_monitor(void);
// void usage_rw_sem(void);
// void usage_rss_monitor(void);
// void usage_throttle_delay(void);
// int uprobe_main(int argc, char **argv);
// void usage_uprobe();
// int ping_delay_main(int argc, char *argv[]);
// void usage_ping_delay(void);
// int ping_delay6_main(int argc, char *argv[]);
// void usage_ping_delay6(void);
// int test_run_trace_main(int argc, char *argv[]);
// void usage_test_run_trace(void);
// int memcg_stats_main(int argc, char *argv[]);
// void usage_memcg_stats(void);
// int diag_activate(const char func[]);
// int diag_deactivate(const char func[]);
// void diag_printf_inode(struct diag_inode_detail *inode);
// void diag_printf_time(struct diag_timespec *tv);
// void diag_printf_task(struct diag_task_detail *task);
// void diag_printf_proc_chains(struct diag_proc_chains_detail *proc_chains);
// void diag_printf_proc_chains(struct diag_proc_chains_detail *proc_chains, int reverse);
// void diag_printf_proc_chains(struct diag_proc_chains_detail *proc_chains, int reverse, int detail);
// void diag_printf_kern_stack(struct diag_kern_stack_detail *kern_stack);
// void diag_printf_kern_stack(struct diag_kern_stack_detail *kern_stack, int reverse);
// void diag_printf_user_stack(int pid, int ns_pid, const char *comm,
// struct diag_user_stack_detail *user_stack);
// void diag_printf_user_stack(int pid, int ns_pid, const char *comm,
// struct diag_user_stack_detail *user_stack, int attach);
// void diag_printf_user_stack(int pid, int ns_pid, const char *comm,
// struct diag_user_stack_detail *user_stack, int attach, int reverse);
// void diag_printf_raw_stack(int pid, int ns_pid, const char *comm,
// struct diag_raw_stack_detail *raw_stack);
// void diag_printf_raw_stack(int pid, int ns_pid, const char *comm,
// struct diag_raw_stack_detail *raw_stack, int attach);
// void init_java_env(const char *agent, int pid, int ns_pid, const char *comm, std::set<int> &);
// void diag_unwind_raw_stack(int pid, int ns_pid,
// struct diag_raw_stack_detail *raw_stack, unsigned long stack[BACKTRACE_DEPTH]);
// void diag_sls_time(struct diag_timespec *tv, Json::Value &owner);
// void diag_sls_task(struct diag_task_detail *tsk_info, Json::Value &task);
// void diag_sls_proc_chains(struct diag_proc_chains_detail *proc_chains, Json::Value &task);
// void diag_sls_kern_stack(struct diag_kern_stack_detail *kern_stack, Json::Value &task);
// void diag_sls_user_stack(pid_t pid, pid_t ns_pid, const char *comm,
// struct diag_user_stack_detail *user_stack, Json::Value &task);
// void diag_sls_user_stack(pid_t pid, pid_t ns_pid, const char *comm,
// struct diag_user_stack_detail *user_stack, Json::Value &task, int attach);
// void diag_sls_inode(struct diag_inode_detail *inode, Json::Value &root);
// int log_config(char *arg, char *sls_file, int *p_syslog_enabled);
// void write_syslog(int enabled, const char mod[], struct diag_timespec *tv, unsigned long id, int seq, Json::Value &root);
// void write_file(char *sls_file, const char mod[], struct diag_timespec *tv, unsigned long id, int seq, Json::Value &root);
// void diag_ip_addr_to_str(unsigned char *ip_addr,const char type[], Json::Value &root);
// #define ULONG_MAX (~0UL)
// #define STACK_IS_END(v) ((v) == 0 || (v) == ULONG_MAX)
// class pid_cmdline {
// private:
// std::map<int, std::string> cmdlines;
// public:
// void clear(void);
// std::string & get_pid_cmdline(int pid);
// };
// int jmaps_main(int argc, char **argv);
// void restore_global_env();
// int attach_ns_env(int pid);
// int java_attach_once(int flag_no_attach = 0);
// extern class pid_cmdline pid_cmdline;
// extern void clear_symbol_info(class pid_cmdline &pid_cmdline, std::set<int> &procs, int dist);
// extern unsigned int ipstr2int(const char *ipstr);
// extern char *int2ipstr(const unsigned int ip, char *ipstr, const unsigned int ip_str_len);
// extern int is_linux_2_6_x(void);
// extern int linux_2_6_x;
// int sys_cost_main(int argc, char **argv);
// void usage_sys_cost();
// int fs_cache_main(int argc, char *argv[]);
// void usage_fs_cache(void);
// int high_order_main(int argc, char *argv[]);
// void usage_high_order(void);
// int pmu_main(int argc, char **argv);
// void usage_pmu(void);
// int testcase_main(int argc, char *argv[]);
// struct timeval;
// struct timezone;
// extern "C" {
// void diag_gettimeofday(struct diag_timespec *tv, struct timezone *tz);
// }

View File

@@ -0,0 +1,215 @@
/*
* diagnose-tools 工具通用调试缓冲区模块
* 这是为了解决procfs/trace的问题而编写
*
* Copyright (C) 20 Alibaba Ltd.
*
* 作者: Baoyou Xie <baoyou.xie@linux.alibaba.com>
*
* License terms: GNU General Public License (GPL) version 3
*
*/
#include <linux/vmalloc.h>
// #include "internal.h"
#include "trace_buffer.h"
int init_diag_trace_buffer(struct diag_trace_buffer *buffer,
unsigned int buf_size)
{
int ret = -ENOMEM;
char *buf1 = NULL, *buf2 = NULL;
ret = -EINVAL;
if (buf_size < 10 * DIAG_TRACE_BUF_SIZE)
return ret;
buf1 = vmalloc(buf_size);
if (!buf1)
goto out_nomem;
buf2 = vmalloc(buf_size);
if (!buf2)
goto out_nomem;
memset(buf1, 0, buf_size);
memset(buf2, 0, buf_size);
memset(buffer, 0, sizeof(struct diag_trace_buffer));
buffer->buf_size = buf_size;
buffer->buffer.data = buf1;
spin_lock_init(&buffer->buffer.lock);
mutex_init(&buffer->buffer.mutex);
buffer->product.data = buf2;
ret = 0;
return ret;
out_nomem:
if (buf1)
vfree(buf1);
if (buf2)
vfree(buf2);
return ret;
}
void destroy_diag_trace_buffer(struct diag_trace_buffer *buffer)
{
if (buffer->buffer.data)
vfree(buffer->buffer.data);
if (buffer->product.data)
vfree(buffer->product.data);
memset(buffer, 0, sizeof(struct diag_trace_buffer));
}
void discard_diag_trace_buffer(struct diag_trace_buffer *buffer)
{
unsigned long flags;
diag_trace_buffer_mutex_lock(buffer);
diag_trace_buffer_spin_lock(buffer, flags);
buffer->buffer.circle = buffer->buffer.pos = buffer->buffer.tail = 0;
diag_trace_buffer_spin_unlock(buffer, flags);
diag_trace_buffer_mutex_unlock(buffer);
}
void backup_diag_trace_buffer(struct diag_trace_buffer *buffer)
{
unsigned long flags;
if (!buffer->buffer.data || !buffer->product.data)
return;
diag_trace_buffer_mutex_lock(buffer);
diag_trace_buffer_spin_lock(buffer, flags);
buffer->product.len = 0;
if (buffer->buffer.pos < buffer->buf_size) {
if (buffer->buffer.circle) {
int tail_len = 0;
if (buffer->buffer.tail > buffer->buffer.pos) {
tail_len = buffer->buffer.tail - buffer->buffer.pos;
memcpy(buffer->product.data,
buffer->buffer.data + buffer->buffer.pos,
tail_len);
}
memcpy(buffer->product.data + tail_len,
buffer->buffer.data,
buffer->buffer.pos);
buffer->product.len = buffer->buffer.pos + tail_len;
} else {
memcpy(buffer->product.data, buffer->buffer.data, buffer->buffer.pos);
buffer->product.len = buffer->buffer.pos;
}
}
buffer->buffer.circle = buffer->buffer.pos = buffer->buffer.tail = 0;
diag_trace_buffer_spin_unlock(buffer, flags);
diag_trace_buffer_mutex_unlock(buffer);
}
asmlinkage int
diag_trace_buffer_write_nolock(struct diag_trace_buffer *buffer,
const void *data, size_t len)
{
unsigned int left;
left = buffer->buf_size - buffer->buffer.pos;
if (len < left) {
memcpy(buffer->buffer.data + buffer->buffer.pos,
data, len);
buffer->buffer.pos += len;
} else {
buffer->buffer.tail = buffer->buffer.pos;
memcpy(buffer->buffer.data, data, len);
buffer->buffer.pos = len;
buffer->buffer.circle = 1;
}
return len;
}
asmlinkage int
diag_trace_buffer_write(struct diag_trace_buffer *buffer,
const void *data, size_t len)
{
int ret;
unsigned long flags;
spin_lock_irqsave(&buffer->buffer.lock, flags);
ret = diag_trace_buffer_write_nolock(buffer, data, len);
spin_unlock_irqrestore(&buffer->buffer.lock, flags);
return ret;
}
static asmlinkage int
__diag_trace_buffer_printk_nolock(struct diag_trace_buffer *buffer,
const char *fmt, va_list ap)
{
unsigned int len = 0;
unsigned int left;
len = vsnprintf(buffer->fmt_buffer, DIAG_TRACE_BUF_SIZE, fmt, ap);
if (len > DIAG_TRACE_BUF_SIZE)
return len;
left = buffer->buf_size - buffer->buffer.pos;
if (len < left) {
memcpy(buffer->buffer.data + buffer->buffer.pos,
buffer->fmt_buffer, len);
buffer->buffer.pos += len;
} else {
buffer->buffer.tail = buffer->buffer.pos;
memcpy(buffer->buffer.data, buffer->fmt_buffer, len);
buffer->buffer.pos = len;
buffer->buffer.circle = 1;
}
return len;
}
asmlinkage int
diag_trace_buffer_printk_nolock(struct diag_trace_buffer *buffer,
const char *fmt, ...)
{
va_list ap;
int ret;
va_start(ap, fmt);
ret = __diag_trace_buffer_printk_nolock(buffer, fmt, ap);
va_end(ap);
return ret;
}
asmlinkage int
diag_trace_buffer_printk(struct diag_trace_buffer *buffer,
const char *fmt, ...)
{
int ret;
unsigned long flags;
va_list ap;
spin_lock_irqsave(&buffer->buffer.lock, flags);
va_start(ap, fmt);
ret = __diag_trace_buffer_printk_nolock(buffer, fmt, ap);
va_end(ap);
spin_unlock_irqrestore(&buffer->buffer.lock, flags);
return ret;
}
void diag_trace_buffer_mutex_lock(struct diag_trace_buffer *buffer)
{
mutex_lock(&buffer->buffer.mutex);
}
void diag_trace_buffer_mutex_unlock(struct diag_trace_buffer *buffer)
{
mutex_unlock(&buffer->buffer.mutex);
}

View File

@@ -0,0 +1,106 @@
/*
* diagnose-tools 工具通用调试缓冲区模块
* 这是为了解决procfs/trace的问题而编写
*
* Copyright (C) 20 Alibaba Ltd.
*
* 作者: Baoyou Xie <baoyou.xie@linux.alibaba.com>
*
* License terms: GNU General Public License (GPL) version 3
*
*/
#include <linux/spinlock.h>
#include <linux/mutex.h>
#include <linux/stddef.h>
/**
* 调试缓冲区描述符
* buffer: 当前正在接受调用者输出的缓冲区
* data: 数据起始指针
* pos: 当前写入位置
* circle: 是否已经产生了回绕
* tail: 有效位置的尾部
* product: 将buffer中数据临时保存到此避免影响记录速度
* data: 数据起始指针
* len: 数据有效长度
* buf_size: buffer/product的大小
*/
#define DIAG_TRACE_BUF_SIZE 1024
struct diag_trace_buffer {
struct {
char *data;
unsigned int pos;
int circle;
unsigned int tail;
spinlock_t lock;
struct mutex mutex;
} buffer;
struct {
char *data;
unsigned int len;
} product;
char fmt_buffer[DIAG_TRACE_BUF_SIZE];
unsigned int buf_size;
};
int init_diag_trace_buffer(struct diag_trace_buffer *buffer,
unsigned int buf_size);
void destroy_diag_trace_buffer(struct diag_trace_buffer *buffer);
void discard_diag_trace_buffer(struct diag_trace_buffer *buffer);
void backup_diag_trace_buffer(struct diag_trace_buffer *buffer);
asmlinkage int
diag_trace_buffer_printk_nolock(struct diag_trace_buffer *buffer,
const char *fmt, ...);
asmlinkage int
diag_trace_buffer_printk(struct diag_trace_buffer *buffer,
const char *fmt, ...);
asmlinkage int
diag_trace_buffer_write_nolock(struct diag_trace_buffer *buffer,
const void *data, size_t len);
asmlinkage int
diag_trace_buffer_write(struct diag_trace_buffer *buffer,
const void *data, size_t len);
#define diag_trace_buffer_spin_lock(__buffer, flags) \
spin_lock_irqsave(&((__buffer)->buffer.lock), flags)
#define diag_trace_buffer_spin_unlock(__buffer, flags) \
spin_unlock_irqrestore(&((__buffer)->buffer.lock), flags)
void diag_trace_buffer_mutex_lock(struct diag_trace_buffer *buffer);
void diag_trace_buffer_mutex_unlock(struct diag_trace_buffer *buffer);
void diagnose_trace_buffer_stack_trace(int pre, struct diag_trace_buffer *buffer,
struct task_struct *p, unsigned long *backtrace);
void diagnose_trace_buffer_nolock_stack_trace(int pre, struct diag_trace_buffer *buffer,
struct task_struct *p, unsigned long *backtrace);
void diagnose_trace_buffer_nolock_stack_trace_user(int pre, struct diag_trace_buffer *buffer,
unsigned long *backtrace);
void diagnose_trace_buffer_stack_trace_user(int pre, struct diag_trace_buffer *buffer,
unsigned long *backtrace);
void diagnose_trace_buffer_nolock_stack_trace_user_tsk(int pre, struct diag_trace_buffer *buffer,
struct task_struct *tsk, unsigned long *backtrace);
void diagnose_trace_buffer_stack_trace_user_tsk(int pre, struct diag_trace_buffer *buffer,
struct task_struct *tsk, unsigned long *backtrace);
void diag_trace_buffer_process_chain(int pre, struct diag_trace_buffer *buffer, struct task_struct *tsk);
void diag_trace_buffer_nolock_process_chain(int pre, struct diag_trace_buffer *buffer, struct task_struct *tsk);
void diag_trace_buffer_process_chain_cmdline(int pre, struct diag_trace_buffer *buffer, struct task_struct *tsk);
void diag_trace_buffer_nolock_process_chain_cmdline(int pre, struct diag_trace_buffer *buffer, struct task_struct *tsk);
void trace_buffer_cgroups_tsk(int pre, struct diag_trace_buffer *buffer, struct task_struct *tsk);
void trace_buffer_nolock_cgroups_tsk(int pre, struct diag_trace_buffer *buffer, struct task_struct *tsk);
void trace_buffer_cgroups(int pre, struct diag_trace_buffer *buffer);
void trace_buffer_nolock_cgroups(int pre, struct diag_trace_buffer *buffer);
void diag_trace_buffer_all_task_stack(int pre, struct diag_trace_buffer *buffer);
void diag_trace_buffer_nolock_all_task_stack(int pre,
struct diag_trace_buffer *buffer);
void diagnose_trace_buffer_nolock_stack_trace_unfold(int pre, struct diag_trace_buffer *buffer,
struct task_struct *p, unsigned long *backtrace);
void diagnose_trace_buffer_nolock_stack_trace_unfold_user(int pre, struct diag_trace_buffer *buffer,
unsigned long *backtrace);
void diagnose_print_stack_trace_unfold_user_tsk(int pre, int might_sleep, struct task_struct *tsk, unsigned long *backtrace);
void diagnose_trace_buffer_nolock_stack_trace_unfold_user_tsk(int pre, int might_sleep, struct diag_trace_buffer *buffer,
struct task_struct *tsk, unsigned long *backtrace);
void diagnose_trace_buffer_stack_trace_unfold_user_tsk(int pre, int might_sleep, struct diag_trace_buffer *buffer,
struct task_struct *tsk, unsigned long *backtrace);

View File

@@ -0,0 +1,260 @@
/*
* Linux内核诊断工具--工具通用调试缓冲区模块
* 这是为了解决procfs/trace的问题而编写
*
* Copyright (C) 2020 Alibaba Ltd.
*
* 作者: Baoyou Xie <baoyou.xie@linux.alibaba.com>
*
* License terms: GNU General Public License (GPL) version 3
*/
#include <linux/uaccess.h>
#include <linux/vmalloc.h>
#include "trace_buffer.h"
// #include "internal.h"
#include "variant_buffer.h"
int init_diag_variant_buffer(struct diag_variant_buffer *buffer,
unsigned int buf_size) {
int ret = 0;
ret = -EINVAL;
if (buf_size < 10 * DIAG_TRACE_BUF_SIZE)
return ret;
memset(buffer, 0, sizeof(struct diag_variant_buffer));
buffer->buf_size = buf_size;
spin_lock_init(&buffer->lock);
mutex_init(&buffer->mutex);
ret = 0;
return ret;
}
int alloc_diag_variant_buffer(struct diag_variant_buffer *buffer) {
int ret = -ENOMEM;
char *buf1 = NULL, *buf2 = NULL, *buf3 = NULL;
unsigned int buf_size;
buf_size = buffer->buf_size;
if (buffer->alloced)
return 0;
ret = -EINVAL;
if (buf_size < 10 * DIAG_TRACE_BUF_SIZE)
return ret;
ret = -ENOMEM;
buf1 = vmalloc(buf_size);
if (!buf1)
goto out_nomem;
buf2 = vmalloc(buf_size);
if (!buf2)
goto out_nomem;
buf3 = vmalloc(buf_size * 2);
if (!buf3)
goto out_nomem;
memset(buf1, 0, buf_size);
memset(buf2, 0, buf_size);
memset(buf3, 0, buf_size * 2);
buffer->buffers[0].data = buf1;
buffer->buffers[1].data = buf2;
buffer->product.data = buf3;
buffer->alloced = 1;
ret = 0;
return ret;
out_nomem:
if (buf1)
vfree(buf1);
if (buf2)
vfree(buf2);
if (buf3)
vfree(buf3);
return ret;
}
void destroy_diag_variant_buffer(struct diag_variant_buffer *buffer) {
if (buffer->buffers[0].data)
vfree(buffer->buffers[0].data);
if (buffer->buffers[1].data)
vfree(buffer->buffers[1].data);
if (buffer->product.data)
vfree(buffer->product.data);
memset(buffer, 0, sizeof(struct diag_variant_buffer));
}
void discard_diag_variant_buffer(struct diag_variant_buffer *buffer) {
unsigned long flags;
if (!buffer->alloced)
return;
diag_variant_buffer_mutex_lock(buffer);
diag_variant_buffer_spin_lock(buffer, flags);
buffer->buffers[0].pos = buffer->buffers[1].pos = 0;
buffer->buffer_toggle = 0;
diag_variant_buffer_spin_unlock(buffer, flags);
diag_variant_buffer_mutex_unlock(buffer);
}
void backup_diag_variant_buffer(struct diag_variant_buffer *buffer) {
unsigned long flags;
if (!buffer->alloced)
return;
diag_variant_buffer_mutex_lock(buffer);
diag_variant_buffer_spin_lock(buffer, flags);
buffer->product.len = 0;
if (buffer->buffer_toggle == 0) {
if (buffer->buffers[1].pos) {
memcpy(buffer->product.data, buffer->buffers[1].data,
buffer->buffers[1].pos);
buffer->product.len = buffer->product.len + buffer->buffers[1].pos;
}
if (buffer->buffers[0].pos) {
memcpy(buffer->product.data + buffer->product.len,
buffer->buffers[0].data, buffer->buffers[0].pos);
buffer->product.len = buffer->product.len + buffer->buffers[0].pos;
}
} else {
if (buffer->buffers[0].pos) {
memcpy(buffer->product.data, buffer->buffers[0].data,
buffer->buffers[0].pos);
buffer->product.len = buffer->product.len + buffer->buffers[0].pos;
}
if (buffer->buffers[1].pos) {
memcpy(buffer->product.data + buffer->product.len,
buffer->buffers[1].data, buffer->buffers[1].pos);
buffer->product.len = buffer->product.len + buffer->buffers[1].pos;
}
}
buffer->buffers[0].pos = buffer->buffers[1].pos = 0;
buffer->buffers[0].head = buffer->buffers[1].head = NULL;
buffer->buffer_toggle = 0;
diag_variant_buffer_spin_unlock(buffer, flags);
diag_variant_buffer_mutex_unlock(buffer);
}
asmlinkage int diag_variant_buffer_reserve(struct diag_variant_buffer *buffer,
size_t len) {
int real_len = (len + sizeof(unsigned long)) & (sizeof(unsigned long) - 1);
real_len += sizeof(struct diag_variant_buffer_head);
/**
* 这样可以简单的略过整型溢出检查。
*/
if (len > 1024 * 1024 * 1024)
return len;
if (!buffer->alloced)
return len;
if (buffer->buffer_toggle == 0) {
if (buffer->buffers[0].pos + real_len >= buffer->buf_size) {
buffer->buffer_toggle = 1;
buffer->buffers[1].pos = sizeof(struct diag_variant_buffer_head);
buffer->buffers[1].head = (void *)buffer->buffers[1].data;
memset(buffer->buffers[1].head, 0,
sizeof(struct diag_variant_buffer_head));
} else {
buffer->buffers[0].head =
(void *)buffer->buffers[0].data + buffer->buffers[0].pos;
memset(buffer->buffers[0].head, 0,
sizeof(struct diag_variant_buffer_head));
buffer->buffers[0].pos += sizeof(struct diag_variant_buffer_head);
}
} else {
if (buffer->buffers[1].pos + real_len >= buffer->buf_size) {
buffer->buffer_toggle = 0;
buffer->buffers[0].pos = sizeof(struct diag_variant_buffer_head);
buffer->buffers[0].head = (void *)buffer->buffers[0].data;
memset(buffer->buffers[0].head, 0,
sizeof(struct diag_variant_buffer_head));
} else {
buffer->buffers[1].head =
(void *)buffer->buffers[1].data + buffer->buffers[1].pos;
memset(buffer->buffers[1].head, 0,
sizeof(struct diag_variant_buffer_head));
buffer->buffers[1].pos += sizeof(struct diag_variant_buffer_head);
}
}
return len;
}
asmlinkage int diag_variant_buffer_seal(struct diag_variant_buffer *buffer) {
int idx = !!buffer->buffer_toggle;
void *rbound = buffer->buffers[idx].data + buffer->buf_size;
if (!buffer->alloced)
return -EINVAL;
if ((void *)buffer->buffers[idx].head < (void *)buffer->buffers[idx].data)
return -EINVAL;
if ((void *)buffer->buffers[idx].head >
(rbound - sizeof(struct diag_variant_buffer_head)))
return -EINVAL;
buffer->buffers[idx].head->magic = DIAG_VARIANT_BUFFER_HEAD_MAGIC_SEALED;
buffer->buffers[idx].head->len = (void *)buffer->buffers[idx].data +
buffer->buffers[idx].pos -
(void *)buffer->buffers[idx].head;
return 0;
}
asmlinkage int
diag_variant_buffer_write_nolock(struct diag_variant_buffer *buffer,
const void *data, size_t len) {
unsigned int left;
int idx = !!buffer->buffer_toggle;
if (!buffer->alloced)
return -EINVAL;
left = buffer->buf_size - buffer->buffers[idx].pos;
if (len < left) {
memcpy(buffer->buffers[idx].data + buffer->buffers[idx].pos, data, len);
buffer->buffers[idx].pos += len;
}
return len;
}
void diag_variant_buffer_mutex_lock(struct diag_variant_buffer *buffer) {
mutex_lock(&buffer->mutex);
}
void diag_variant_buffer_mutex_unlock(struct diag_variant_buffer *buffer) {
mutex_unlock(&buffer->mutex);
}
int copy_to_user_variant_buffer(struct diag_variant_buffer *variant_buffer,
void __user *ptr_len, void __user *buf,
size_t size) {
size_t len;
int ret;
backup_diag_variant_buffer(variant_buffer);
len = variant_buffer->product.len;
if (size < len)
len = size;
ret = copy_to_user(buf, variant_buffer->product.data, len);
if (!ret)
ret = len;
if (ret >= 0) {
ret = copy_to_user(ptr_len, &ret, sizeof(int));
}
return ret;
}

View File

@@ -0,0 +1,64 @@
/*
* Linux内核诊断工具--工具通用调试缓冲区模块
* 这是为了解决procfs/trace的问题而编写
*
* Copyright (C) 2020 Alibaba Ltd.
*
* 作者: Baoyou Xie <baoyou.xie@linux.alibaba.com>
*
* License terms: GNU General Public License (GPL) version 3
*/
#include <linux/mutex.h>
#include <linux/spinlock.h>
#include <linux/stddef.h>
#define DIAG_VARIANT_BUFFER_HEAD_MAGIC_SEALED 197612031122
#define DIAG_VARIANT_BUFFER_HEAD_MAGIC_UNSEALED 197612031234
struct diag_variant_buffer_head {
unsigned long magic;
unsigned long len;
};
struct diag_variant_buffer {
struct {
char *data;
unsigned int pos;
struct diag_variant_buffer_head *head;
} buffers[2];
/* 0 or 1 */
int buffer_toggle;
struct {
char *data;
unsigned int len;
} product;
unsigned int buf_size;
unsigned int alloced;
spinlock_t lock;
struct mutex mutex;
};
#define diag_variant_buffer_spin_lock(__buffer, flags) \
spin_lock_irqsave(&((__buffer)->lock), flags)
#define diag_variant_buffer_spin_unlock(__buffer, flags) \
spin_unlock_irqrestore(&((__buffer)->lock), flags)
int init_diag_variant_buffer(struct diag_variant_buffer *buffer,
unsigned int buf_size);
int alloc_diag_variant_buffer(struct diag_variant_buffer *buffer);
void destroy_diag_variant_buffer(struct diag_variant_buffer *buffer);
void discard_diag_variant_buffer(struct diag_variant_buffer *buffer);
void backup_diag_variant_buffer(struct diag_variant_buffer *buffer);
asmlinkage int diag_variant_buffer_reserve(struct diag_variant_buffer *buffer,
size_t len);
asmlinkage int diag_variant_buffer_seal(struct diag_variant_buffer *buffer);
asmlinkage int
diag_variant_buffer_write_nolock(struct diag_variant_buffer *buffer,
const void *data, size_t len);
void diag_variant_buffer_mutex_lock(struct diag_variant_buffer *buffer);
void diag_variant_buffer_mutex_unlock(struct diag_variant_buffer *buffer);
int copy_to_user_variant_buffer(struct diag_variant_buffer *variant_buffer,
void __user *ptr_len, void __user *buf,
size_t size);