tracefile.c
来自「lustre 1.6.5 source code」· C语言 代码 · 共 1,115 行 · 第 1/3 页
C
1,115 行
nob = usr_buffer_nob; if (copy_to_user(usr_buffer, knl_buffer, nob)) return -EFAULT; if (append != NULL && nob < usr_buffer_nob) { if (copy_to_user(usr_buffer + nob, append, 1)) return -EFAULT; nob++; } return nob;}int trace_allocate_string_buffer(char **str, int nob){ if (nob > 2 * CFS_PAGE_SIZE) /* string must be "sensible" */ return -EINVAL; *str = cfs_alloc(nob, CFS_ALLOC_STD | CFS_ALLOC_ZERO); if (*str == NULL) return -ENOMEM; return 0;}void trace_free_string_buffer(char *str, int nob){ cfs_free(str);}int trace_dump_debug_buffer_usrstr(void *usr_str, int usr_str_nob){ char *str; int rc; rc = trace_allocate_string_buffer(&str, usr_str_nob + 1); if (rc != 0) return rc; rc = trace_copyin_string(str, usr_str_nob + 1, usr_str, usr_str_nob); if (rc != 0) goto out;#if !defined(__WINNT__) if (str[0] != '/') { rc = -EINVAL; goto out; }#endif rc = tracefile_dump_all_pages(str);out: trace_free_string_buffer(str, usr_str_nob + 1); return rc;}int trace_daemon_command(char *str){ int rc = 0; tracefile_write_lock(); if (strcmp(str, "stop") == 0) { trace_stop_thread(); memset(tracefile, 0, sizeof(tracefile)); } else if (strncmp(str, "size=", 5) == 0) { tracefile_size = simple_strtoul(str + 5, NULL, 0); if (tracefile_size < 10 || tracefile_size > 20480) tracefile_size = TRACEFILE_SIZE; else tracefile_size <<= 20; } else if (strlen(str) >= sizeof(tracefile)) { rc = -ENAMETOOLONG;#ifndef __WINNT__ } else if (str[0] != '/') { rc = -EINVAL;#endif } else { strcpy(tracefile, str); printk(KERN_INFO "Lustre: debug daemon will attempt to start writing " "to %s (%lukB max)\n", tracefile, (long)(tracefile_size >> 10)); trace_start_thread(); } tracefile_write_unlock(); return rc;}int trace_daemon_command_usrstr(void *usr_str, int usr_str_nob){ char *str; int rc; rc = trace_allocate_string_buffer(&str, usr_str_nob + 1); if (rc != 0) return rc; rc = trace_copyin_string(str, usr_str_nob + 1, usr_str, usr_str_nob); if (rc == 0) rc = trace_daemon_command(str); trace_free_string_buffer(str, usr_str_nob + 1); return rc;}int trace_set_debug_mb(int mb){ int i; int j; int pages; int limit = trace_max_debug_mb(); struct trace_cpu_data *tcd; if (mb < num_possible_cpus()) return -EINVAL; if (mb > limit) { printk(KERN_ERR "Lustre: Refusing to set debug buffer size to " "%dMB - limit is %d\n", mb, limit); return -EINVAL; } mb /= num_possible_cpus(); pages = mb << (20 - CFS_PAGE_SHIFT); tracefile_write_lock(); tcd_for_each(tcd, i, j) tcd->tcd_max_pages = (pages * tcd->tcd_pages_factor) / 100; tracefile_write_unlock(); return 0;}int trace_set_debug_mb_usrstr(void *usr_str, int usr_str_nob){ char str[32]; int rc; rc = trace_copyin_string(str, sizeof(str), usr_str, usr_str_nob); if (rc < 0) return rc; return trace_set_debug_mb(simple_strtoul(str, NULL, 0));}int trace_get_debug_mb(void){ int i; int j; struct trace_cpu_data *tcd; int total_pages = 0; tracefile_read_lock(); tcd_for_each(tcd, i, j) total_pages += tcd->tcd_max_pages; tracefile_read_unlock(); return (total_pages >> (20 - CFS_PAGE_SHIFT)) + 1;}static int tracefiled(void *arg){ struct page_collection pc; struct tracefiled_ctl *tctl = arg; struct trace_page *tage; struct trace_page *tmp; struct ptldebug_header *hdr; cfs_file_t *filp; int rc; CFS_DECL_MMSPACE; /* we're started late enough that we pick up init's fs context */ /* this is so broken in uml? what on earth is going on? */ cfs_daemonize("ktracefiled"); spin_lock_init(&pc.pc_lock); complete(&tctl->tctl_start); while (1) { cfs_waitlink_t __wait; cfs_waitlink_init(&__wait); cfs_waitq_add(&tctl->tctl_waitq, &__wait); set_current_state(TASK_INTERRUPTIBLE); cfs_waitq_timedwait(&__wait, CFS_TASK_INTERRUPTIBLE, cfs_time_seconds(1)); cfs_waitq_del(&tctl->tctl_waitq, &__wait); if (atomic_read(&tctl->tctl_shutdown)) break; pc.pc_want_daemon_pages = 0; collect_pages(&pc); if (list_empty(&pc.pc_pages)) continue; filp = NULL; tracefile_read_lock(); if (tracefile[0] != 0) { filp = cfs_filp_open(tracefile, O_CREAT | O_RDWR | O_LARGEFILE, 0600, &rc); if (!(filp)) printk(KERN_WARNING "couldn't open %s: %d\n", tracefile, rc); } tracefile_read_unlock(); if (filp == NULL) { put_pages_on_daemon_list(&pc); __LASSERT(list_empty(&pc.pc_pages)); continue; } CFS_MMSPACE_OPEN; /* mark the first header, so we can sort in chunks */ tage = tage_from_list(pc.pc_pages.next); __LASSERT_TAGE_INVARIANT(tage); hdr = cfs_page_address(tage->page); hdr->ph_flags |= PH_FLAG_FIRST_RECORD; list_for_each_entry_safe(tage, tmp, &pc.pc_pages, linkage) { static loff_t f_pos; __LASSERT_TAGE_INVARIANT(tage); if (f_pos >= (off_t)tracefile_size) f_pos = 0; else if (f_pos > cfs_filp_size(filp)) f_pos = cfs_filp_size(filp); rc = cfs_filp_write(filp, cfs_page_address(tage->page), tage->used, &f_pos); if (rc != (int)tage->used) { printk(KERN_WARNING "wanted to write %u but " "wrote %d\n", tage->used, rc); put_pages_back(&pc); __LASSERT(list_empty(&pc.pc_pages)); } } CFS_MMSPACE_CLOSE; cfs_filp_close(filp); put_pages_on_daemon_list(&pc); __LASSERT(list_empty(&pc.pc_pages)); } complete(&tctl->tctl_stop); return 0;}int trace_start_thread(void){ struct tracefiled_ctl *tctl = &trace_tctl; int rc = 0; mutex_down(&trace_thread_sem); if (thread_running) goto out; init_completion(&tctl->tctl_start); init_completion(&tctl->tctl_stop); cfs_waitq_init(&tctl->tctl_waitq); atomic_set(&tctl->tctl_shutdown, 0); if (cfs_kernel_thread(tracefiled, tctl, 0) < 0) { rc = -ECHILD; goto out; } wait_for_completion(&tctl->tctl_start); thread_running = 1;out: mutex_up(&trace_thread_sem); return rc;}void trace_stop_thread(void){ struct tracefiled_ctl *tctl = &trace_tctl; mutex_down(&trace_thread_sem); if (thread_running) { printk(KERN_INFO "Lustre: shutting down debug daemon thread...\n"); atomic_set(&tctl->tctl_shutdown, 1); wait_for_completion(&tctl->tctl_stop); thread_running = 0; } mutex_up(&trace_thread_sem);}int tracefile_init(int max_pages){ struct trace_cpu_data *tcd; int i; int j; int rc; int factor; rc = tracefile_init_arch(); if (rc != 0) return rc; tcd_for_each(tcd, i, j) { /* tcd_pages_factor is initialized int tracefile_init_arch. */ factor = tcd->tcd_pages_factor; CFS_INIT_LIST_HEAD(&tcd->tcd_pages); CFS_INIT_LIST_HEAD(&tcd->tcd_stock_pages); CFS_INIT_LIST_HEAD(&tcd->tcd_daemon_pages); tcd->tcd_cur_pages = 0; tcd->tcd_cur_stock_pages = 0; tcd->tcd_cur_daemon_pages = 0; tcd->tcd_max_pages = (max_pages * factor) / 100; LASSERT(tcd->tcd_max_pages > 0); tcd->tcd_shutting_down = 0; } return 0;}static void trace_cleanup_on_cpu(void *info){ struct trace_cpu_data *tcd; struct trace_page *tage; struct trace_page *tmp; int i; tcd_for_each_type_lock(tcd, i) { tcd->tcd_shutting_down = 1; list_for_each_entry_safe(tage, tmp, &tcd->tcd_pages, linkage) { __LASSERT_TAGE_INVARIANT(tage); list_del(&tage->linkage); tage_free(tage); } tcd->tcd_cur_pages = 0; }}static void trace_cleanup(void){ struct page_collection pc; CFS_INIT_LIST_HEAD(&pc.pc_pages); spin_lock_init(&pc.pc_lock); trace_call_on_all_cpus(trace_cleanup_on_cpu, &pc); tracefile_fini_arch();}void tracefile_exit(void){ trace_stop_thread(); trace_cleanup();}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?