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 + -
显示快捷键?