From mboxrd@z Thu Jan 1 00:00:00 1970 From: Vasiliy G Tolstov Subject: xenstore watch not working under 32 bit domU (xen stable 2.6.32 from jeremy git tree) Date: Mon, 22 Nov 2010 14:53:35 +0300 Message-ID: <1290426815.17994.111.camel@vase> Reply-To: v.tolstov@selfip.ru Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xensource.com Errors-To: xen-devel-bounces@lists.xensource.com To: "xen-devel@lists.xensource.com" List-Id: xen-devel@lists.xenproject.org Hello. Can You helps me, i'm try to investigate why under 64 bit domU this kernel module work's correct, but under 686 watch does not work: compile and running aginst curent running kernel. #define LINUX #include #include #include #include //Xen specific #include //Memory state #include //Disk state #include #include #include //tokenize #include #define ENABLE_DEPRECATED 1 extern void *sys_call_table[]; #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,36) static void argv_cleanup(struct subprocess_info *info) { argv_free(info->argv); } #else static void argv_cleanup(char **argv, char **envp) { argv_free(argv); } #endif static int xenmgm_exec(char *cmd) { int argc; char **argv = argv_split(GFP_ATOMIC, cmd, &argc); static char *envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/bin:/usr/sbin:/usr/bin", NULL }; int ret = -ENOMEM; struct subprocess_info *info; if (argv == NULL) { printk(KERN_WARNING "%s failed to allocate memory for \"%s\"\n", __func__, cmd); goto out; } info = call_usermodehelper_setup(argv[0], argv, envp, GFP_ATOMIC); if (info == NULL) { argv_free(argv); goto out; } #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,36) call_usermodehelper_setfns(info, NULL, argv_cleanup, NULL); #else call_usermodehelper_setcleanup(info, argv_cleanup); #endif ret = call_usermodehelper_exec(info, UMH_WAIT_PROC); out: return ret; } static void watch_cmd(struct xenbus_watch *watch, const char **vec, unsigned int len) { char *cmd; cmd = xenbus_read(XBT_NIL, "data/mgm", "cmd_in", NULL); if (IS_ERR(cmd)) { printk(KERN_ERR "Unable to read cmd_in string in data/mgm/cmd_in\n"); return; } if (strcmp(cmd, "\0") != 0) { char *key, *cp; cp = kstrdup(cmd, GFP_KERNEL); do { key = strsep(&cp, ";"); if (key) { xenmgm_exec(key); } } while (key); kfree(cp); } kfree(cmd); } static unsigned int memstat_interval_ms; static unsigned int diskstat_interval_ms; static struct workqueue_struct *xenmgm_memory_workqueue; static struct workqueue_struct *xenmgm_disk_workqueue; static void xenmgm_memory_process(struct work_struct *); static void xenmgm_disk_process(struct work_struct *); static DECLARE_DELAYED_WORK(xenmgm_memory_worker, xenmgm_memory_process); static DECLARE_DELAYED_WORK(xenmgm_disk_worker, xenmgm_disk_process); static void xenmgm_memory_queue_delayed_work(unsigned long delay) { if (!queue_delayed_work(xenmgm_memory_workqueue, &xenmgm_memory_worker, delay)) printk(KERN_ERR "xenmgm: bad xenmgm_memory_workqueue\n"); } static void xenmgm_disk_queue_delayed_work(unsigned long delay) { if (!queue_delayed_work(xenmgm_disk_workqueue, &xenmgm_disk_worker, delay)) printk(KERN_ERR "xenmgm: bad xenmgm_disk_workqueue\n"); } static void xenmgm_memory_process(struct work_struct *work) { struct sysinfo meminfo; int err; unsigned long long totalbytes, freebytes, usedbytes; si_meminfo(&meminfo); totalbytes = (unsigned long long) meminfo.totalram << PAGE_SHIFT; freebytes = ((unsigned long long) meminfo.freeram + (unsigned long long) global_page_state(NR_FILE_PAGES) + (unsigned long long) meminfo.bufferram) << PAGE_SHIFT; usedbytes = (unsigned long long) totalbytes - freebytes; err = xenbus_printf(XBT_NIL, "data/memory", "totalbytes", "%llu", totalbytes); if(err) printk("xenmgm: error writing to xenbus: /data/memory/totalbytes, %d\n", err); err = xenbus_printf(XBT_NIL, "data/memory", "freebytes", "%llu", freebytes); if(err) printk("xenmgm: error writing to xenbus: /data/memory/freebytes, %d\n", err); err = xenbus_printf(XBT_NIL, "data/memory", "usedbytes", "%llu", usedbytes); if(err) printk("xenmgm: error writing to xenbus: /data/memory/usedbytes, %d\n", err); #ifdef ENABLE_DEPRECATED err = xenbus_printf(XBT_NIL, "memory", "memtotalbytes", "%llu", totalbytes); if(err) printk("xenmgm: error writing to xenbus: /memory/memtotalbytes, %d\n", err); err = xenbus_printf(XBT_NIL, "memory", "memfreebytes", "%llu", freebytes); if(err) printk("xenmgm: error writing to xenbus: /memory/memfreebytes, %d\n", err); #endif xenmgm_memory_queue_delayed_work(memstat_interval_ms / (1000 / HZ)); } static void xenmgm_disk_process(struct work_struct *work) { struct path path; int err; struct kstatfs buf; unsigned long long totalbytes, freebytes, usedbytes; err = user_path("/", &path); if (!err) { #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,36) vfs_statfs(&path, &buf); #else vfs_statfs(path.dentry, &buf); #endif path_put(&path); totalbytes = buf.f_blocks * (u64) buf.f_bsize; freebytes = buf.f_bfree * (u64) buf.f_bsize; usedbytes = totalbytes - freebytes; err = xenbus_printf(XBT_NIL, "data/disk", "totalbytes", "%llu", totalbytes); if(err) printk("xenmgm: error writing to xenbus: /data/disk/totalbytes: %d\n", err); err = xenbus_printf(XBT_NIL, "data/disk", "freebytes", "%llu", freebytes); if(err) printk("xenmgm: error writing to xenbus: /data/disk/freebytes: %d\n", err); err = xenbus_printf(XBT_NIL, "data/disk", "usedbytes", "%llu", usedbytes); if(err) printk("xenmgm: error writing to xenbus: /data/disk/usedbytes: %d\n", err); #ifdef ENABLE_DEPRECATED err = xenbus_printf(XBT_NIL, "memory", "disktotalbytes", "%llu", totalbytes); if(err) printk("xenmgm: error writing to xenbus: /memory/disktotalbytes: %d\n", err); err = xenbus_printf(XBT_NIL, "memory", "diskfreebytes", "%llu", freebytes); if(err) printk("xenmgm: error writing to xenbus: /memory/diskfreebytes: %d\n", err); #endif } xenmgm_disk_queue_delayed_work(diskstat_interval_ms / (1000 / HZ)); } static int xenmgm_init_watcher(struct notifier_block *notifier, unsigned long event, void *data) { int err; static struct xenbus_watch xenmgm_xenbus_watch = { .node = "data/mgm/cmd_in", .callback = watch_cmd}; printk("xenmgm: xenstore watcher init\n"); err = register_xenbus_watch(&xenmgm_xenbus_watch); if (err) { printk(KERN_ERR "xenmgm: Failed to set xenmgm watcher \n"); return err; } return NOTIFY_DONE; } static int __init xenmgm_init(void) { static struct notifier_block xenmgm_xenstore_notifier = { .notifier_call = xenmgm_init_watcher }; diskstat_interval_ms = 1000; memstat_interval_ms = 1000; printk("xenmgm: module init\n"); register_xenstore_notifier(&xenmgm_xenstore_notifier); xenmgm_memory_workqueue = create_singlethread_workqueue("xenmgm_memory"); xenmgm_disk_workqueue = create_singlethread_workqueue("xenmgm_disk"); xenmgm_memory_queue_delayed_work(60UL * HZ); printk("xenmgm: xenmgm_memory init\n"); xenmgm_disk_queue_delayed_work(60UL * HZ); printk("xenmgm: xenmgm_disk init\n"); return 0; } static void __exit xenmgm_exit(void) { cancel_delayed_work(&xenmgm_memory_worker); cancel_delayed_work(&xenmgm_disk_worker); flush_workqueue(xenmgm_memory_workqueue); flush_workqueue(xenmgm_disk_workqueue); destroy_workqueue(xenmgm_memory_workqueue); destroy_workqueue(xenmgm_disk_workqueue); // unregister_xenstore_notifier(&xenmgm_xenstore_notifier); printk("xenmgm: module exit\n"); return; } module_init(xenmgm_init); module_exit(xenmgm_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Vasiliy G Tolstov "); MODULE_DESCRIPTION("Xen DomU management module"); MODULE_VERSION("0.0.1"); -- Vasiliy G Tolstov Selfip.Ru