mconsole_kern.c
来自「LINUX 2.6.17.4的源码」· C语言 代码 · 共 914 行 · 第 1/2 页
C
914 行
*end_out = 0; return 0;}static int mem_remove(int n){ return -EBUSY;}static struct mc_device mem_mc = { .name = "mem", .config = mem_config, .get_config = mem_get_config, .id = mem_id, .remove = mem_remove,};static int mem_mc_init(void){ if(can_drop_memory()) mconsole_register_dev(&mem_mc); else printk("Can't release memory to the host - memory hotplug won't " "be supported\n"); return 0;}__initcall(mem_mc_init);#define CONFIG_BUF_SIZE 64static void mconsole_get_config(int (*get_config)(char *, char *, int, char **), struct mc_request *req, char *name){ char default_buf[CONFIG_BUF_SIZE], *error, *buf; int n, size; if(get_config == NULL){ mconsole_reply(req, "No get_config routine defined", 1, 0); return; } error = NULL; size = sizeof(default_buf)/sizeof(default_buf[0]); buf = default_buf; while(1){ n = (*get_config)(name, buf, size, &error); if(error != NULL){ mconsole_reply(req, error, 1, 0); goto out; } if(n <= size){ mconsole_reply(req, buf, 0, 0); goto out; } if(buf != default_buf) kfree(buf); size = n; buf = kmalloc(size, GFP_KERNEL); if(buf == NULL){ mconsole_reply(req, "Failed to allocate buffer", 1, 0); return; } } out: if(buf != default_buf) kfree(buf);}void mconsole_config(struct mc_request *req){ struct mc_device *dev; char *ptr = req->request.data, *name; int err; ptr += strlen("config"); while(isspace(*ptr)) ptr++; dev = mconsole_find_dev(ptr); if(dev == NULL){ mconsole_reply(req, "Bad configuration option", 1, 0); return; } name = &ptr[strlen(dev->name)]; ptr = name; while((*ptr != '=') && (*ptr != '\0')) ptr++; if(*ptr == '='){ err = (*dev->config)(name); mconsole_reply(req, "", err, 0); } else mconsole_get_config(dev->get_config, req, name);}void mconsole_remove(struct mc_request *req){ struct mc_device *dev; char *ptr = req->request.data, *err_msg = ""; char error[256]; int err, start, end, n; ptr += strlen("remove"); while(isspace(*ptr)) ptr++; dev = mconsole_find_dev(ptr); if(dev == NULL){ mconsole_reply(req, "Bad remove option", 1, 0); return; } ptr = &ptr[strlen(dev->name)]; err = 1; n = (*dev->id)(&ptr, &start, &end); if(n < 0){ err_msg = "Couldn't parse device number"; goto out; } else if((n < start) || (n > end)){ sprintf(error, "Invalid device number - must be between " "%d and %d", start, end); err_msg = error; goto out; } err = (*dev->remove)(n); switch(err){ case -ENODEV: err_msg = "Device doesn't exist"; break; case -EBUSY: err_msg = "Device is currently open"; break; default: break; }out: mconsole_reply(req, err_msg, err, 0);}static DEFINE_SPINLOCK(console_lock);static LIST_HEAD(clients);static char console_buf[MCONSOLE_MAX_DATA];static int console_index = 0;static void console_write(struct console *console, const char *string, unsigned len){ struct list_head *ele; int n; if(list_empty(&clients)) return; while(1){ n = min((size_t) len, ARRAY_SIZE(console_buf) - console_index); strncpy(&console_buf[console_index], string, n); console_index += n; string += n; len -= n; if(len == 0) return; list_for_each(ele, &clients){ struct mconsole_entry *entry; entry = list_entry(ele, struct mconsole_entry, list); mconsole_reply_len(&entry->request, console_buf, console_index, 0, 1); } console_index = 0; }}static struct console mc_console = { .name = "mc", .write = console_write, .flags = CON_ENABLED, .index = -1 };static int mc_add_console(void){ register_console(&mc_console); return 0;}late_initcall(mc_add_console);static void with_console(struct mc_request *req, void (*proc)(void *), void *arg){ struct mconsole_entry entry; unsigned long flags; entry.request = *req; list_add(&entry.list, &clients); spin_lock_irqsave(&console_lock, flags); (*proc)(arg); mconsole_reply_len(req, console_buf, console_index, 0, 0); console_index = 0; spin_unlock_irqrestore(&console_lock, flags); list_del(&entry.list);}#ifdef CONFIG_MAGIC_SYSRQstatic void sysrq_proc(void *arg){ char *op = arg; handle_sysrq(*op, ¤t->thread.regs, NULL);}void mconsole_sysrq(struct mc_request *req){ char *ptr = req->request.data; ptr += strlen("sysrq"); while(isspace(*ptr)) ptr++; /* With 'b', the system will shut down without a chance to reply, * so in this case, we reply first. */ if(*ptr == 'b') mconsole_reply(req, "", 0, 0); with_console(req, sysrq_proc, ptr);}#elsevoid mconsole_sysrq(struct mc_request *req){ mconsole_reply(req, "Sysrq not compiled in", 1, 0);}#endif#ifdef CONFIG_MODE_SKASstatic void stack_proc(void *arg){ struct task_struct *from = current, *to = arg; to->thread.saved_task = from; switch_to(from, to, from);}/* Mconsole stack trace * Added by Allan Graves, Jeff Dike * Dumps a stacks registers to the linux console. * Usage stack <pid>. */static void do_stack_trace(struct mc_request *req){ char *ptr = req->request.data; int pid_requested= -1; struct task_struct *from = NULL; struct task_struct *to = NULL; /* Would be nice: * 1) Send showregs output to mconsole. * 2) Add a way to stack dump all pids. */ ptr += strlen("stack"); while(isspace(*ptr)) ptr++; /* Should really check for multiple pids or reject bad args here */ /* What do the arguments in mconsole_reply mean? */ if(sscanf(ptr, "%d", &pid_requested) == 0){ mconsole_reply(req, "Please specify a pid", 1, 0); return; } from = current; to = find_task_by_pid(pid_requested); if((to == NULL) || (pid_requested == 0)) { mconsole_reply(req, "Couldn't find that pid", 1, 0); return; } with_console(req, stack_proc, to);}#endif /* CONFIG_MODE_SKAS */void mconsole_stack(struct mc_request *req){ /* This command doesn't work in TT mode, so let's check and then * get out of here */ CHOOSE_MODE(mconsole_reply(req, "Sorry, this doesn't work in TT mode", 1, 0), do_stack_trace(req));}/* Changed by mconsole_setup, which is __setup, and called before SMP is * active. */static char *notify_socket = NULL;static int mconsole_init(void){ /* long to avoid size mismatch warnings from gcc */ long sock; int err; char file[256]; if(umid_file_name("mconsole", file, sizeof(file))) return(-1); snprintf(mconsole_socket_name, sizeof(file), "%s", file); sock = os_create_unix_socket(file, sizeof(file), 1); if (sock < 0){ printk("Failed to initialize management console\n"); return(1); } register_reboot_notifier(&reboot_notifier); err = um_request_irq(MCONSOLE_IRQ, sock, IRQ_READ, mconsole_interrupt, SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, "mconsole", (void *)sock); if (err){ printk("Failed to get IRQ for management console\n"); return(1); } if(notify_socket != NULL){ notify_socket = kstrdup(notify_socket, GFP_KERNEL); if(notify_socket != NULL) mconsole_notify(notify_socket, MCONSOLE_SOCKET, mconsole_socket_name, strlen(mconsole_socket_name) + 1); else printk(KERN_ERR "mconsole_setup failed to strdup " "string\n"); } printk("mconsole (version %d) initialized on %s\n", MCONSOLE_VERSION, mconsole_socket_name); return(0);}__initcall(mconsole_init);static int write_proc_mconsole(struct file *file, const char __user *buffer, unsigned long count, void *data){ char *buf; buf = kmalloc(count + 1, GFP_KERNEL); if(buf == NULL) return(-ENOMEM); if(copy_from_user(buf, buffer, count)){ count = -EFAULT; goto out; } buf[count] = '\0'; mconsole_notify(notify_socket, MCONSOLE_USER_NOTIFY, buf, count); out: kfree(buf); return(count);}static int create_proc_mconsole(void){ struct proc_dir_entry *ent; if(notify_socket == NULL) return(0); ent = create_proc_entry("mconsole", S_IFREG | 0200, NULL); if(ent == NULL){ printk(KERN_INFO "create_proc_mconsole : create_proc_entry failed\n"); return(0); } ent->read_proc = NULL; ent->write_proc = write_proc_mconsole; return(0);}static DEFINE_SPINLOCK(notify_spinlock);void lock_notify(void){ spin_lock(¬ify_spinlock);}void unlock_notify(void){ spin_unlock(¬ify_spinlock);}__initcall(create_proc_mconsole);#define NOTIFY "=notify:"static int mconsole_setup(char *str){ if(!strncmp(str, NOTIFY, strlen(NOTIFY))){ str += strlen(NOTIFY); notify_socket = str; } else printk(KERN_ERR "mconsole_setup : Unknown option - '%s'\n", str); return(1);}__setup("mconsole", mconsole_setup);__uml_help(mconsole_setup,"mconsole=notify:<socket>\n"" Requests that the mconsole driver send a message to the named Unix\n"" socket containing the name of the mconsole socket. This also serves\n"" to notify outside processes when UML has booted far enough to respond\n"" to mconsole requests.\n\n");static int notify_panic(struct notifier_block *self, unsigned long unused1, void *ptr){ char *message = ptr; if(notify_socket == NULL) return(0); mconsole_notify(notify_socket, MCONSOLE_PANIC, message, strlen(message) + 1); return(0);}static struct notifier_block panic_exit_notifier = { .notifier_call = notify_panic, .next = NULL, .priority = 1};static int add_notifier(void){ atomic_notifier_chain_register(&panic_notifier_list, &panic_exit_notifier); return(0);}__initcall(add_notifier);char *mconsole_notify_socket(void){ return(notify_socket);}EXPORT_SYMBOL(mconsole_notify_socket);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?