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 <linux/module.h>
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/init.h>
//Xen specific
#include <xen/xenbus.h>
//Memory state
#include <linux/mm.h>
//Disk state
#include <linux/statfs.h>
#include <linux/namei.h>
#include <linux/fs.h>
//tokenize
#include <linux/string.h>
#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 <v.tolstov@xxxxxxxxx>");
MODULE_DESCRIPTION("Xen DomU management module");
MODULE_VERSION("0.0.1");
--
Vasiliy G Tolstov <v.tolstov@xxxxxxxxx>
Selfip.Ru
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|