├── net ├── vnet │ ├── README │ ├── Makefile │ ├── App │ │ └── netconf.c │ └── vnet.c ├── netdevobj │ ├── README │ ├── Makefile │ └── netdevobj.c ├── qdisc │ ├── README.txt │ ├── Makefile │ └── qdisc.c └── shownetdev │ ├── README │ ├── Makefile │ └── shownetdev.c ├── kmod └── vtest │ ├── ext_func.c │ ├── ext_func.h │ ├── Makefile │ └── vmx_test.c ├── chap01 ├── README.txt ├── Makefile └── demodev.c ├── kmodule ├── A_mod │ ├── README │ ├── Makefile │ └── demodev.c ├── A_mod_bak │ ├── README │ ├── Makefile │ └── demodev.c ├── modref │ ├── Makefile │ └── modref.c ├── sysfs_race │ ├── create │ │ ├── Makefile │ │ ├── assem.c │ │ ├── assem.s │ │ ├── addobj.c │ │ └── BUG_ON.txt │ └── delete │ │ ├── Makefile │ │ ├── rmobj.c │ │ └── BUG_ON.txt ├── B_mod │ ├── Makefile │ └── dep_on_A.c └── finit_mod_api │ └── main.c ├── README.md ├── chap09 └── kobj │ ├── Makefile │ ├── app │ └── main.c │ ├── README.txt │ └── kobj_demo.c ├── chap10 ├── mmap │ ├── Makefile │ └── mmap_demo.c └── app │ └── main.c ├── chap11 ├── ramhd_req │ ├── Makefile │ └── ramhd_req.c └── ramhd_mkreq │ ├── Makefile │ └── ramhd_mkreq.c ├── chap07 └── fasync │ ├── driver │ ├── Makefile │ └── fasync_demo.c │ └── app │ └── main.c ├── chap02 ├── driver │ ├── Makefile │ └── demo_chr_dev.c └── app │ └── main.c └── aio └── aioapp.c /net/vnet/README: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /kmod/vtest/ext_func.c: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /net/netdevobj/README: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /net/qdisc/README.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /net/shownetdev/README: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /kmod/vtest/ext_func.h: -------------------------------------------------------------------------------- 1 | extern void just_a_func(void); 2 | -------------------------------------------------------------------------------- /chap01/README.txt: -------------------------------------------------------------------------------- 1 | set module parameters with below command: 2 | 3 | #insmod demodev.ko dolphin=5 demodev_str="hello,world" -------------------------------------------------------------------------------- /kmodule/A_mod/README: -------------------------------------------------------------------------------- 1 | set module parameters with below command: 2 | 3 | #insmod demodev.ko dolphin=5 demodev_str="hello,world" 4 | 5 | -------------------------------------------------------------------------------- /kmodule/A_mod_bak/README: -------------------------------------------------------------------------------- 1 | set module parameters with below command: 2 | 3 | #insmod demodev.ko dolphin=5 demodev_str="hello,world" 4 | 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Internals of Linux Device Driver(ILDD) (2nd edition) 2 | ==================================================== 3 | 4 | This repository is used to place the sample codes of the ILDD v2. 5 | 6 | 7 | 深入Linux设备驱动程序内核机制 -------------------------------------------------------------------------------- /chap09/kobj/Makefile: -------------------------------------------------------------------------------- 1 | obj-m := kobj_demo.o 2 | KERNELDIR := /lib/modules/$(shell uname -r)/build 3 | PWD := $(shell pwd) 4 | 5 | default: 6 | $(MAKE) -C $(KERNELDIR) M=$(PWD) modules 7 | clean: 8 | rm -f *.o *.ko *.mod.* *.order *.symvers 9 | -------------------------------------------------------------------------------- /chap10/mmap/Makefile: -------------------------------------------------------------------------------- 1 | obj-m := mmap_demo.o 2 | KERNELDIR := /lib/modules/$(shell uname -r)/build 3 | PWD := $(shell pwd) 4 | 5 | default: 6 | $(MAKE) -C $(KERNELDIR) M=$(PWD) modules 7 | clean: 8 | rm -f *.o *.ko *.mod.* *.order *.symvers 9 | -------------------------------------------------------------------------------- /chap11/ramhd_req/Makefile: -------------------------------------------------------------------------------- 1 | obj-m := ramhd_req.o 2 | KERNELDIR := /lib/modules/$(shell uname -r)/build 3 | PWD := $(shell pwd) 4 | 5 | default: 6 | $(MAKE) -C $(KERNELDIR) M=$(PWD) modules 7 | clean: 8 | rm -f *.o *.ko *.mod.* *.order *.symvers 9 | -------------------------------------------------------------------------------- /chap07/fasync/driver/Makefile: -------------------------------------------------------------------------------- 1 | obj-m := fasync_demo.o 2 | KERNELDIR := /lib/modules/$(shell uname -r)/build 3 | PWD := $(shell pwd) 4 | 5 | default: 6 | $(MAKE) -C $(KERNELDIR) M=$(PWD) modules 7 | clean: 8 | rm -f *.o *.ko *.mod.* *.order *.symvers 9 | -------------------------------------------------------------------------------- /chap11/ramhd_mkreq/Makefile: -------------------------------------------------------------------------------- 1 | obj-m := ramhd_mkreq.o 2 | KERNELDIR := /lib/modules/$(shell uname -r)/build 3 | PWD := $(shell pwd) 4 | 5 | default: 6 | $(MAKE) -C $(KERNELDIR) M=$(PWD) modules 7 | clean: 8 | rm -f *.o *.ko *.mod.* *.order *.symvers 9 | -------------------------------------------------------------------------------- /net/qdisc/Makefile: -------------------------------------------------------------------------------- 1 | 2 | obj-m := qdisc.o 3 | KERNELDIR := /lib/modules/$(shell uname -r)/build 4 | PWD := $(shell pwd) 5 | 6 | default: 7 | $(MAKE) -C $(KERNELDIR) M=$(PWD) modules 8 | clean: 9 | rm -f *.o *.ko *.mod.* *.order *.symvers 10 | -------------------------------------------------------------------------------- /chap01/Makefile: -------------------------------------------------------------------------------- 1 | #Chap1: a simple demo kernel module 2 | obj-m := demodev.o 3 | KERNELDIR := /lib/modules/$(shell uname -r)/build 4 | PWD := $(shell pwd) 5 | 6 | default: 7 | $(MAKE) -C $(KERNELDIR) M=$(PWD) modules 8 | clean: 9 | rm -f *.o *.ko *.mod.* *.order *.symvers 10 | -------------------------------------------------------------------------------- /kmodule/A_mod/Makefile: -------------------------------------------------------------------------------- 1 | #Chap1: a simple demo kernel module 2 | obj-m := demodev.o 3 | KERNELDIR := /lib/modules/$(shell uname -r)/build 4 | PWD := $(shell pwd) 5 | 6 | default: 7 | $(MAKE) -C $(KERNELDIR) M=$(PWD) modules 8 | clean: 9 | rm -f *.o *.ko *.mod.* *.order *.symvers 10 | -------------------------------------------------------------------------------- /kmodule/modref/Makefile: -------------------------------------------------------------------------------- 1 | #Chap1: a simple demo kernel module 2 | obj-m := modref.o 3 | KERNELDIR := /lib/modules/$(shell uname -r)/build 4 | PWD := $(shell pwd) 5 | 6 | default: 7 | $(MAKE) -C $(KERNELDIR) M=$(PWD) modules 8 | clean: 9 | rm -f *.o *.ko *.mod.* *.order *.symvers 10 | -------------------------------------------------------------------------------- /kmodule/A_mod_bak/Makefile: -------------------------------------------------------------------------------- 1 | #Chap1: a simple demo kernel module 2 | obj-m := demodev.o 3 | KERNELDIR := /lib/modules/$(shell uname -r)/build 4 | PWD := $(shell pwd) 5 | 6 | default: 7 | $(MAKE) -C $(KERNELDIR) M=$(PWD) modules 8 | clean: 9 | rm -f *.o *.ko *.mod.* *.order *.symvers 10 | -------------------------------------------------------------------------------- /net/vnet/Makefile: -------------------------------------------------------------------------------- 1 | #a virtual netdevice driver 2 | MOD_NAME := vnet 3 | obj-m := $(MOD_NAME).o 4 | KERNELDIR := /lib/modules/$(shell uname -r)/build 5 | PWD := $(shell pwd) 6 | 7 | default: 8 | $(MAKE) -C $(KERNELDIR) M=$(PWD) modules 9 | clean: 10 | rm -f *.o *.ko *.mod.* *.order *.symvers 11 | -------------------------------------------------------------------------------- /chap02/driver/Makefile: -------------------------------------------------------------------------------- 1 | #Chap2: a simple demo character type device driver kernel module 2 | obj-m := demo_chr_dev.o 3 | KERNELDIR := /lib/modules/$(shell uname -r)/build 4 | PWD := $(shell pwd) 5 | 6 | default: 7 | $(MAKE) -C $(KERNELDIR) M=$(PWD) modules 8 | clean: 9 | rm -f *.o *.ko *.mod.* *.order *.symvers 10 | -------------------------------------------------------------------------------- /kmod/vtest/Makefile: -------------------------------------------------------------------------------- 1 | #a simple kmod to test the kvm 2 | obj-m := vmx_kmod.o 3 | vmx_kmod-objs := vmx_test.o ext_func.o 4 | 5 | KERNELDIR := /lib/modules/$(shell uname -r)/build 6 | PWD := $(shell pwd) 7 | 8 | default: 9 | $(MAKE) -C $(KERNELDIR) M=$(PWD) modules 10 | clean: 11 | rm -f *.o *.ko *.mod.* *.order *.symvers 12 | -------------------------------------------------------------------------------- /kmodule/sysfs_race/create/Makefile: -------------------------------------------------------------------------------- 1 | #Chap1: a simple kernel module to register a file system into the kernel 2 | obj-m := addobj.o 3 | KERNELDIR := /lib/modules/$(shell uname -r)/build 4 | PWD := $(shell pwd) 5 | 6 | default: 7 | $(MAKE) -C $(KERNELDIR) M=$(PWD) modules 8 | clean: 9 | rm -f *.o *.ko *.mod.* *.order *.symvers 10 | -------------------------------------------------------------------------------- /kmodule/sysfs_race/delete/Makefile: -------------------------------------------------------------------------------- 1 | #Chap1: a simple kernel module to register a file system into the kernel 2 | obj-m := rmobj.o 3 | KERNELDIR := /lib/modules/$(shell uname -r)/build 4 | PWD := $(shell pwd) 5 | 6 | default: 7 | $(MAKE) -C $(KERNELDIR) M=$(PWD) modules 8 | clean: 9 | rm -f *.o *.ko *.mod.* *.order *.symvers 10 | -------------------------------------------------------------------------------- /kmodule/sysfs_race/create/assem.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct subent{ 5 | int a; 6 | int *p; 7 | }; 8 | 9 | struct kobject{ 10 | int a; 11 | int b; 12 | struct subent *sd; 13 | }; 14 | 15 | void npfs_remove_dir(struct kobject *kobj) 16 | { 17 | struct subent *sd = kobj->sd; 18 | kobj->sd = NULL; 19 | } 20 | -------------------------------------------------------------------------------- /net/netdevobj/Makefile: -------------------------------------------------------------------------------- 1 | #a simple kernel module to display all the net devices in the system 2 | MOD_NAME := netdevobj 3 | obj-m := $(MOD_NAME).o 4 | KERNELDIR := /lib/modules/$(shell uname -r)/build 5 | PWD := $(shell pwd) 6 | 7 | default: 8 | $(MAKE) -C $(KERNELDIR) M=$(PWD) modules 9 | clean: 10 | rm -f *.o *.ko *.mod.* *.order *.symvers 11 | -------------------------------------------------------------------------------- /kmodule/B_mod/Makefile: -------------------------------------------------------------------------------- 1 | #Chap1: a simple demo kernel module 2 | obj-m := dep_on_A.o 3 | KERNELDIR := /lib/modules/$(shell uname -r)/build 4 | KBUILD_EXTMOD := /home/dennis/workspace/Linux/book/kmodule/A_mod 5 | PWD := $(shell pwd) 6 | 7 | default: 8 | $(MAKE) -C $(KERNELDIR) M=$(PWD) modules 9 | clean: 10 | rm -f *.o *.ko *.mod.* *.order *.symvers 11 | -------------------------------------------------------------------------------- /net/shownetdev/Makefile: -------------------------------------------------------------------------------- 1 | #a simple kernel module to display all the net devices in the system 2 | MOD_NAME := shownetdev 3 | obj-m := $(MOD_NAME).o 4 | KERNELDIR := /lib/modules/$(shell uname -r)/build 5 | PWD := $(shell pwd) 6 | 7 | default: 8 | $(MAKE) -C $(KERNELDIR) M=$(PWD) modules 9 | clean: 10 | rm -f *.o *.ko *.mod.* *.order *.symvers .$(MOD_NAME)* 11 | -------------------------------------------------------------------------------- /kmodule/sysfs_race/create/assem.s: -------------------------------------------------------------------------------- 1 | .file "assem.c" 2 | .text 3 | .p2align 4,,15 4 | .globl npfs_remove_dir 5 | .type npfs_remove_dir, @function 6 | npfs_remove_dir: 7 | .LFB34: 8 | .cfi_startproc 9 | movq $0, 8(%rdi) 10 | ret 11 | .cfi_endproc 12 | .LFE34: 13 | .size npfs_remove_dir, .-npfs_remove_dir 14 | .ident "GCC: (Ubuntu/Linaro 4.7.2-2ubuntu1) 4.7.2" 15 | .section .note.GNU-stack,"",@progbits 16 | -------------------------------------------------------------------------------- /chap02/app/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define CHR_DEV_NAME "/dev/chr_dev" 6 | 7 | int main() 8 | { 9 | int ret; 10 | char buf[32]; 11 | int fd = open(CHR_DEV_NAME, O_RDONLY|O_NDELAY); 12 | if(fd < 0) 13 | { 14 | printf("open file %s failed!\n", CHR_DEV_NAME); 15 | return -1; 16 | } 17 | read(fd, buf, 32); 18 | close(fd); 19 | 20 | return 0; 21 | } 22 | 23 | -------------------------------------------------------------------------------- /chap09/kobj/app/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | extern char **environ; 5 | 6 | int main(int argc, char *argv[]) 7 | { 8 | char **var; 9 | 10 | syslog(LOG_INFO, "----------------------------------------\n"); 11 | syslog(LOG_INFO, "argv[1]=%s\n", argv[1]); 12 | for(var = environ; *var != NULL; ++ var) 13 | syslog(LOG_INFO, "env=%s\n", *var); 14 | syslog(LOG_INFO, "----------------------------------------\n"); 15 | 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /kmodule/B_mod/dep_on_A.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | extern void my_exp_function(void); 5 | 6 | static int demodev_init(void) 7 | { 8 | my_exp_function(); 9 | return 0; 10 | } 11 | 12 | static void demodev_exit(void) 13 | { 14 | printk(KERN_INFO "demodev_exit()\n"); 15 | } 16 | 17 | module_init(demodev_init); 18 | module_exit(demodev_exit); 19 | 20 | MODULE_LICENSE("GPL"); 21 | MODULE_AUTHOR("dennis chen @ AMDLinuxFGL"); 22 | MODULE_DESCRIPTION("A simple kernel module as an illustration"); 23 | -------------------------------------------------------------------------------- /kmod/vtest/vmx_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "ext_func.h" 5 | 6 | static int vmxtest_init(void) 7 | { 8 | printk(KERN_INFO "vmxtest_init()\n"); 9 | just_a_func(); 10 | return 0; 11 | } 12 | 13 | static void vmxtest_exit(void) 14 | { 15 | printk(KERN_INFO "vmxtest_exit()\n"); 16 | } 17 | 18 | module_init(vmxtest_init); 19 | module_exit(vmxtest_exit); 20 | 21 | MODULE_LICENSE("GPL"); 22 | MODULE_AUTHOR("kernel.org.gnu@gmail.com"); 23 | MODULE_DESCRIPTION("A simple kernel module to test the kvm module"); 24 | -------------------------------------------------------------------------------- /kmodule/sysfs_race/create/addobj.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | extern struct kobject *test_parent; 7 | static int addobj_init(void) 8 | { 9 | test_parent = kobject_create_and_add("parent", NULL); 10 | return 0; 11 | } 12 | 13 | static void addobj_exit(void) 14 | { 15 | kobject_del(test_parent); 16 | } 17 | 18 | module_init(addobj_init); 19 | module_exit(addobj_exit); 20 | 21 | MODULE_LICENSE("GPL"); 22 | MODULE_AUTHOR("dennis chen"); 23 | MODULE_DESCRIPTION("A simple kernel module as fs registration demo"); 24 | -------------------------------------------------------------------------------- /kmodule/sysfs_race/delete/rmobj.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | extern struct kobject *test_parent; 7 | struct kobject *child; 8 | 9 | static int rmobj_init(void) 10 | { 11 | child = kobject_create_and_add("child", test_parent); 12 | return 0; 13 | } 14 | 15 | static void rmobj_exit(void) 16 | { 17 | kobject_del(child); 18 | } 19 | 20 | module_init(rmobj_init); 21 | module_exit(rmobj_exit); 22 | 23 | MODULE_LICENSE("GPL"); 24 | MODULE_AUTHOR("dennis chen"); 25 | MODULE_DESCRIPTION("A simple kernel module as fs registration demo"); 26 | -------------------------------------------------------------------------------- /kmodule/finit_mod_api/main.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE /* See feature_test_macros(7) */ 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include /* For SYS_xxx definitions */ 7 | #include 8 | 9 | int main(void) 10 | { 11 | int fd, rt; 12 | 13 | fd = open("/home/dennis/workspace/Linux/book/kmodule/A_mod/demodev.ko", O_RDONLY); 14 | if (fd < 0) { 15 | perror("open file failed"); 16 | return -1; 17 | } 18 | 19 | rt = syscall(273, fd, NULL, 0); 20 | if (rt != 0) { 21 | perror("load kernel module failed"); 22 | close(fd); 23 | return -1; 24 | } 25 | 26 | close(fd); 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /chap09/kobj/README.txt: -------------------------------------------------------------------------------- 1 | 1. navigate into ./app folder and build it with command: gcc main.c -o main 2 | 2. the application 'main' in the ./app folder will be used as '/sbin/hotplug', so we need to copy it to /sbin folder with below command: 3 | #cp ./main /sbin/hotplug 4 | 3. navigate into the /proc/sys/kernel folder, execute the below command to make the hotplug application can be trigered: 5 | #echo "/sbin/hotplug" > hotplug 6 | make sure the hotplug file has the string with 'cat'command: #cat /proc/sys/kernel/hotplug, it should output the "/sbin/hotplug" 7 | 4. the syslog info will be routed to '/var/log/syslog' file, or '/var/log/messages' in some systems... 8 | 9 | This illustration demonstrates how the user space to monitor events happened in kernel space... 10 | -------------------------------------------------------------------------------- /kmodule/modref/modref.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | static struct module *mod = NULL; 5 | static int modref_init(void) 6 | { 7 | mod = find_module("demodev"); 8 | if (!mod) { 9 | printk("can't find module\n"); 10 | return -1; 11 | } 12 | __module_get(mod); 13 | printk("find the module, refcnt = %lu\n", module_refcount(mod)); 14 | return 0; 15 | } 16 | 17 | static void modref_exit(void) 18 | { 19 | if (mod) { 20 | module_put(mod); 21 | printk("mod refcnt = %lu\n", module_refcount(mod)); 22 | } 23 | printk(KERN_INFO "modref_exit()\n"); 24 | } 25 | 26 | module_init(modref_init); 27 | module_exit(modref_exit); 28 | 29 | MODULE_LICENSE("GPL"); 30 | MODULE_AUTHOR("dennis chen @ AMDLinuxFGL"); 31 | MODULE_DESCRIPTION("A simple kernel module as an illustration"); 32 | -------------------------------------------------------------------------------- /chap01/demodev.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | //exported function 5 | static void my_exp_function(void) 6 | { 7 | printk(KERN_INFO "A function exported to the external world...\n"); 8 | } 9 | 10 | EXPORT_SYMBOL(my_exp_function); 11 | 12 | //module parameters 13 | int dolphin; 14 | module_param(dolphin, int, 0); 15 | 16 | static char demodev_str[64] = "kernel module:demodev"; 17 | module_param_string(demodev_str, demodev_str, sizeof(demodev_str), 0);//(name, string, length, perm) 18 | 19 | static int demodev_init(void) 20 | { 21 | printk(KERN_INFO "demodev_init(): dolphin=%d, demodev_str=%s\n", dolphin, demodev_str); 22 | return 0; 23 | } 24 | 25 | static void demodev_exit(void) 26 | { 27 | printk(KERN_INFO "demodev_exit()\n"); 28 | } 29 | 30 | module_init(demodev_init); 31 | module_exit(demodev_exit); 32 | 33 | MODULE_LICENSE("GPL"); 34 | MODULE_AUTHOR("dennis chen @ AMDLinuxFGL"); 35 | MODULE_DESCRIPTION("A simple kernel module as an illustration"); 36 | -------------------------------------------------------------------------------- /kmodule/A_mod/demodev.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | //exported function 5 | static void my_exp_function(void) 6 | { 7 | printk(KERN_INFO "A function exported to the external world...\n"); 8 | } 9 | 10 | EXPORT_SYMBOL(my_exp_function); 11 | 12 | //module parameters 13 | int dolphin; 14 | module_param(dolphin, int, 0); 15 | 16 | static char demodev_str[64] = "kernel module:demodev"; 17 | module_param_string(demodev_str, demodev_str, sizeof(demodev_str), 0);//(name, string, length, perm) 18 | 19 | static int demodev_init(void) 20 | { 21 | printk(KERN_INFO "demodev_init(): dolphin=%d, demodev_str=%s\n", dolphin, demodev_str); 22 | return 0; 23 | } 24 | 25 | static void demodev_exit(void) 26 | { 27 | printk(KERN_INFO "demodev_exit()\n"); 28 | } 29 | 30 | module_init(demodev_init); 31 | module_exit(demodev_exit); 32 | 33 | MODULE_LICENSE("GPL"); 34 | MODULE_AUTHOR("dennis chen @ AMDLinuxFGL"); 35 | MODULE_DESCRIPTION("A simple kernel module as an illustration"); 36 | -------------------------------------------------------------------------------- /net/qdisc/qdisc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is used to play with the Qdisc for the net dev queue 3 | * Nov.12, 2014 4 | */ 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | 12 | static int qdisc_init(void) 13 | { 14 | struct net_device *dev; 15 | struct net *net = &init_net; 16 | struct Qdisc *qdisc; 17 | 18 | printk(KERN_INFO "++%s\n", __func__); 19 | for_each_netdev_rcu(net, dev) { 20 | qdisc = dev->_tx[0].qdisc; 21 | printk(KERN_INFO "[%s]tx->qdisc = 0x%p[%c]\n", dev->name, 22 | qdisc, netif_is_multiqueue(dev) ? 'M' : 'S'); 23 | if (qdisc->ops) 24 | printk(KERN_INFO "qdisc = %s\n", qdisc->ops->id); 25 | } 26 | 27 | 28 | return 0; 29 | } 30 | 31 | static void qdisc_exit(void) 32 | { 33 | printk(KERN_INFO "--%s\n", __func__); 34 | } 35 | 36 | module_init(qdisc_init); 37 | module_exit(qdisc_exit); 38 | 39 | MODULE_LICENSE("GPL"); 40 | MODULE_AUTHOR("dennis chen"); 41 | MODULE_DESCRIPTION("Qdisc in the net dev queue"); 42 | -------------------------------------------------------------------------------- /chap10/app/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define MAP_SIZE 4096 11 | #define USTR_DEF "String changed from the User Space" 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | int fd; 16 | char *pdata; 17 | 18 | if(argc <= 1){ 19 | printf("Usage: main devfile pa_mapped\n"); 20 | return -1; 21 | } 22 | //printf("argc[1] = %s, argc[2] = 0x%X\n", argv[1], strtoul(argv[2], 0, 16)); 23 | fd = open(argv[1], O_RDWR|O_NDELAY); 24 | if(fd >= 0){ 25 | pdata = (char *)mmap(0, MAP_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, strtoul(argv[2], 0, 16)); 26 | printf("UserAddr = %p, Data from kernel:%s\n", pdata, pdata); 27 | printf("Writing a string to the kernel space..."); 28 | strcpy(pdata, USTR_DEF); 29 | printf("Done\n"); 30 | munmap(pdata, MAP_SIZE); 31 | close(fd); 32 | } 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /kmodule/A_mod_bak/demodev.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | static void test_work(struct work_struct *work) 7 | { 8 | printk(KERN_INFO "++test_work--\n"); 9 | return; 10 | } 11 | 12 | struct work_struct *t_work; 13 | struct workqueue_struct *wq; 14 | static int demodev_init(void) 15 | { 16 | t_work = kzalloc(sizeof(struct work_struct), GFP_KERNEL); 17 | if (!t_work) { 18 | printk(KERN_INFO "kzalloc failed\n"); 19 | return -1; 20 | } 21 | INIT_WORK(t_work, test_work); 22 | wq = alloc_workqueue("ceph-writeback", 0, 1); 23 | if (!wq) { 24 | printk(KERN_INFO "alloc_workqueue failed\n"); 25 | return -1; 26 | } 27 | 28 | queue_work(wq, t_work); 29 | destroy_workqueue(wq); 30 | kfree(t_work); 31 | return 0; 32 | } 33 | 34 | static void demodev_exit(void) 35 | { 36 | //destroy_workqueue(wq); 37 | //kfree(t_work); 38 | printk(KERN_INFO "demodev_exit()\n"); 39 | } 40 | 41 | module_init(demodev_init); 42 | module_exit(demodev_exit); 43 | 44 | MODULE_LICENSE("GPL"); 45 | MODULE_AUTHOR("dennis chen @ AMDLinuxFGL"); 46 | MODULE_DESCRIPTION("A simple kernel module as an illustration"); 47 | -------------------------------------------------------------------------------- /net/netdevobj/netdevobj.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is used to display driver mode info of the net_device 3 | * which has been registered into the system 4 | * Mar.23, 2015 5 | */ 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | static int netdevobj_init(void) 14 | { 15 | struct pci_dev *pdev; 16 | struct device *dev, *parent; 17 | struct net_device *ndev; 18 | struct net *net = &init_net; 19 | struct bus_type *bus = NULL; 20 | 21 | printk(KERN_INFO "++%s\n", __func__); 22 | for_each_netdev_rcu(net, ndev) { 23 | dev = &(ndev->dev); 24 | if (dev) { 25 | parent = dev->parent; 26 | } 27 | if (dev && parent) { 28 | bus = parent->bus; 29 | pdev = container_of(parent, struct pci_dev, dev); 30 | printk(KERN_INFO "dev->name = %s, parent->name = %s\n", 31 | dev->kobj.name, parent->kobj.name); 32 | if (pdev) 33 | printk(KERN_INFO "device = 0x%x\n", pdev->device); 34 | if (bus) 35 | printk(KERN_INFO "bus = %s\n", bus->name); 36 | } 37 | } 38 | 39 | return 0; 40 | } 41 | 42 | static void netdevobj_exit(void) 43 | { 44 | printk(KERN_INFO "--%s\n", __func__); 45 | } 46 | 47 | module_init(netdevobj_init); 48 | module_exit(netdevobj_exit); 49 | 50 | MODULE_LICENSE("GPL"); 51 | MODULE_AUTHOR("dennis chen"); 52 | MODULE_DESCRIPTION("To display the driver mode info of the net_device object"); 53 | -------------------------------------------------------------------------------- /chap07/fasync/app/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define DEVFILE "/dev/fa_dev" 9 | static unsigned long eflag = 1; 10 | 11 | static void sigio_handler(int sigio) 12 | { 13 | printf("Get the SIGIO signal, we exit the application!\n"); 14 | eflag = 0; 15 | } 16 | 17 | static int block_sigio(void) 18 | { 19 | sigset_t set, old; 20 | int ret; 21 | 22 | sigemptyset(&set); 23 | sigaddset(&set, SIGIO); 24 | sigprocmask(SIG_BLOCK, &set, &old); 25 | ret = sigismember(&old, SIGIO); 26 | return ret; 27 | } 28 | 29 | static void unblock_sigio(int blocked) 30 | { 31 | sigset_t set; 32 | if(!blocked){ 33 | sigemptyset(&set); 34 | sigaddset(&set, SIGIO); 35 | sigprocmask(SIG_UNBLOCK, &set, NULL); 36 | } 37 | } 38 | 39 | int main(void) 40 | { 41 | int fd; 42 | struct sigaction sigact, oldact; 43 | int oflag; 44 | int blocked; 45 | 46 | blocked = block_sigio(); 47 | 48 | sigemptyset(&sigact.sa_mask); 49 | sigaddset(&sigact.sa_mask, SIGIO); 50 | sigact.sa_flags = 0; 51 | sigact.sa_handler=sigio_handler; 52 | if(sigaction(SIGIO, &sigact, &oldact) < 0){ 53 | printf("sigaction failed!\n"); 54 | unblock_sigio(blocked); 55 | return -1; 56 | } 57 | unblock_sigio(blocked); 58 | 59 | fd = open(DEVFILE, O_RDWR); 60 | if(fd >= 0){ 61 | fcntl(fd, F_SETOWN, getpid()); 62 | oflag = fcntl(fd, F_GETFL); 63 | fcntl(fd, F_SETFL, oflag | FASYNC); 64 | printf("Do everything you want until we get a signal...\n"); 65 | while(eflag); 66 | close(fd); 67 | } 68 | 69 | return 0; 70 | } 71 | -------------------------------------------------------------------------------- /net/shownetdev/shownetdev.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is used to display all the net_device which have been registered 3 | * into the system 4 | * Nov.7, 2014 5 | */ 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | static void dump_indev(struct in_device *idev) 16 | { 17 | struct in_ifaddr *iifa = idev->ifa_list; 18 | if (iifa) { 19 | printk(KERN_INFO "local = %pI4, address = %pI4\n", &iifa->ifa_local, &iifa->ifa_address); 20 | printk(KERN_INFO "Broadcast = %pI4, Mask = %pI4\n", &iifa->ifa_broadcast, &iifa->ifa_mask); 21 | printk(KERN_INFO "ifa_label = %s, scope = %d\n", iifa->ifa_label, iifa->ifa_scope); 22 | } 23 | } 24 | 25 | static int netdev_show_init(void) 26 | { 27 | struct net_device *dev; 28 | struct net *net = &init_net; 29 | struct in_device *in_dev; 30 | struct inet6_dev *ip6; 31 | int ns_cnt = 0; 32 | 33 | printk(KERN_INFO "++%s\n", __func__); 34 | for_each_netdev_rcu(net, dev) { 35 | printk(KERN_INFO "%s[%d], type = %d, qdisc = %s\n", dev->name, 36 | dev->ifindex, dev->type, dev->qdisc->ops->id); 37 | ip6 = __in6_dev_get(dev); 38 | if (ip6) 39 | printk(KERN_INFO "%s has ipv6 address\n", dev->name); 40 | else 41 | printk(KERN_INFO "%s hasn't ipv6 address\n", dev->name); 42 | 43 | in_dev = __in_dev_get_rtnl(dev); 44 | if (in_dev) 45 | dump_indev(in_dev); 46 | } 47 | 48 | for_each_net_rcu(net) { 49 | ns_cnt++; 50 | } 51 | printk(KERN_INFO "ns count = %d, page_sieze = 0x%lx, bits_long = %x\n", ns_cnt, PAGE_SIZE, ~(BITS_PER_LONG-1)); 52 | 53 | return 0; 54 | } 55 | 56 | static void netdev_show_exit(void) 57 | { 58 | printk(KERN_INFO "--%s\n", __func__); 59 | } 60 | 61 | module_init(netdev_show_init); 62 | module_exit(netdev_show_exit); 63 | 64 | MODULE_LICENSE("GPL"); 65 | MODULE_AUTHOR("dennis chen"); 66 | MODULE_DESCRIPTION("To display all the net devices registered into the system"); 67 | -------------------------------------------------------------------------------- /chap02/driver/demo_chr_dev.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | static struct cdev chr_dev; //An instance of a character device 7 | static dev_t ndev; //The node of the device 8 | 9 | static int chr_open(struct inode *nd, struct file *filp) 10 | { 11 | int major = MAJOR(nd->i_rdev); 12 | int minor = MINOR(nd->i_rdev); 13 | printk("chr_open, major=%d, minor=%d\n", major, minor); 14 | return 0; 15 | } 16 | 17 | static ssize_t chr_read(struct file *filp, char __user *u, size_t sz, loff_t *off) 18 | { 19 | printk("In the chr_read() function!\n"); 20 | return 0; 21 | } 22 | 23 | static int chr_release(struct inode *nd, struct file *filp) 24 | { 25 | printk("In the chr_release() function!\n"); 26 | return 0; 27 | } 28 | 29 | // file_operations is a very important data struct in character type device 30 | struct file_operations chr_ops = 31 | { 32 | .owner = THIS_MODULE, 33 | .open = chr_open, 34 | .read = chr_read, 35 | .release = chr_release, 36 | }; 37 | 38 | // initialization function of the module 39 | static int demo_init(void) 40 | { 41 | int ret; 42 | cdev_init(&chr_dev, &chr_ops); //initialize the device instance 43 | ret = alloc_chrdev_region(&ndev, 0, 1, "chr_dev"); //allocate the device node number dynamically 44 | if(ret < 0) 45 | return ret; 46 | printk("demo_init():major=%d, minor=%d\n", MAJOR(ndev), MINOR(ndev)); 47 | ret = cdev_add(&chr_dev, ndev, 1);//register the char_dev into the system 48 | if(ret < 0) 49 | return ret; 50 | 51 | return 0; 52 | } 53 | 54 | static void demo_exit(void) 55 | { 56 | printk("demo_exit...\n"); 57 | cdev_del(&chr_dev); //unregister the char_dev from the system 58 | unregister_chrdev_region(ndev, 1); //free the device node number 59 | } 60 | 61 | module_init(demo_init); 62 | module_exit(demo_exit); 63 | 64 | MODULE_LICENSE("GPL"); 65 | MODULE_AUTHOR("Dennis @AMDLinuxFGL"); 66 | MODULE_DESCRIPTION("A char device driver as an example"); 67 | -------------------------------------------------------------------------------- /net/vnet/App/netconf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include // for struct ifreq 8 | #include // for ETH_P_IP/ETH_P_ARP/ETH_P_ALL 9 | #include // for struct sockaddr_ll 10 | #include // for SIOCSIFFLAGS... flags 11 | 12 | int main(int argc, char *argv[]) 13 | { 14 | int rc = 0, sockfd; 15 | struct sockaddr_ll sock_address = {0}; 16 | struct ifreq ifr; 17 | int ifindex; 18 | size_t if_name_len; 19 | 20 | if (argc < 2) { 21 | printf("Usage:\n netconf ethx up|down\n"); 22 | return -1; 23 | } 24 | 25 | if_name_len = strlen(argv[1]); 26 | 27 | if ((sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) == -1) { 28 | perror("listener: socket "); 29 | return -1; 30 | } 31 | 32 | if (if_name_len < sizeof(ifr.ifr_name)) { 33 | memcpy(ifr.ifr_name, "eth1",if_name_len); 34 | ifr.ifr_name[if_name_len]=0; 35 | } else { 36 | printf("interface name is too long\n"); 37 | close(sockfd); 38 | return -1; 39 | } 40 | 41 | if (ioctl(sockfd,SIOCGIFINDEX,&ifr)==-1) { 42 | printf("ioctl failed:%s\n",strerror(errno)); 43 | close(sockfd); 44 | return -1; 45 | } 46 | 47 | sock_address.sll_family = AF_PACKET; 48 | sock_address.sll_protocol = htons(ETH_P_ALL); 49 | sock_address.sll_ifindex = ifr.ifr_ifindex; 50 | 51 | if (bind(sockfd, (struct sockaddr*) &sock_address, sizeof(struct sockaddr_ll)) < 0) { 52 | perror("bind failed\n"); 53 | close(sockfd); 54 | return -4; 55 | } 56 | 57 | // bring up/down the ethernet interface 58 | if (!strcasecmp(argv[2], "up")) 59 | ifr.ifr_flags |= IFF_UP; 60 | else if (!strcasecmp(argv[2], "down")) 61 | ifr.ifr_flags &= ~IFF_UP; 62 | else { 63 | printf("invalid argument:%s\n", argv[2]); 64 | return -1; 65 | } 66 | 67 | if (ioctl(sockfd, SIOCSIFFLAGS, &ifr) == -1) { 68 | perror("ioctl failed "); 69 | close(sockfd); 70 | return -1; 71 | } 72 | 73 | printf("%s is %s\n", argv[1], !strcasecmp(argv[2], "up") ? "up" : "down"); 74 | 75 | close(sockfd); 76 | 77 | return rc; 78 | } 79 | -------------------------------------------------------------------------------- /chap07/fasync/driver/fasync_demo.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | static struct cdev *pcdev; 10 | static dev_t ndev; 11 | static struct class *fa_cls; 12 | static struct device *fadev; 13 | 14 | static unsigned long flag = 0; 15 | static struct fasync_struct *sigio_list; 16 | 17 | static ssize_t read_flag(struct device *dev, struct device_attribute *attr, char *buf) 18 | { 19 | size_t count = 0; 20 | count += sprintf(&buf[count], "%lu\n", flag); 21 | 22 | return count; 23 | } 24 | 25 | static ssize_t write_flag(struct device *dev, struct device_attribute *attr, 26 | const char *buf, size_t count) 27 | { 28 | flag = buf[0] - '0'; 29 | //triger the signal to the user space... 30 | kill_fasync(&sigio_list, SIGIO, POLL_IN); 31 | return count; 32 | } 33 | 34 | static struct device_attribute flag_attr = 35 | __ATTR(flag, S_IRUGO | S_IWUSR, read_flag, write_flag); 36 | 37 | 38 | static int fa_open(struct inode *inode, struct file *flp) 39 | { 40 | return 0; 41 | } 42 | 43 | static int fa_async(int fd, struct file *filp, int onflag) 44 | { 45 | return fasync_helper(fd, filp, onflag, &sigio_list); 46 | } 47 | 48 | static struct file_operations ops = { 49 | .owner = THIS_MODULE, 50 | .open = fa_open, 51 | .fasync = fa_async, 52 | }; 53 | 54 | static int fa_init(void) 55 | { 56 | int ret = 0; 57 | 58 | ret = alloc_chrdev_region(&ndev, 0, 1, "fa_dev"); 59 | if(ret < 0) 60 | return ret; 61 | 62 | pcdev = cdev_alloc(); 63 | cdev_init(pcdev, &ops); 64 | pcdev->owner = THIS_MODULE; 65 | cdev_add(pcdev,ndev,1); 66 | 67 | fa_cls = class_create(THIS_MODULE, "fa_dev"); 68 | if(IS_ERR(fa_cls)) 69 | return PTR_ERR(fa_cls); 70 | fadev = device_create(fa_cls, NULL, ndev, NULL, "fa_dev"); 71 | if(IS_ERR(fadev)) 72 | return PTR_ERR(fadev); 73 | 74 | ret = device_create_file(fadev, &flag_attr); 75 | 76 | return ret; 77 | } 78 | 79 | static void fa_exit(void) 80 | { 81 | device_remove_file(fadev, &flag_attr); 82 | device_destroy(fa_cls, ndev); 83 | class_destroy(fa_cls); 84 | cdev_del(pcdev); 85 | unregister_chrdev_region(ndev, 1); 86 | } 87 | 88 | module_init(fa_init); 89 | module_exit(fa_exit); 90 | 91 | MODULE_LICENSE("GPL"); 92 | MODULE_AUTHOR("dennis chen @ AMDLinuxFGL"); 93 | MODULE_DESCRIPTION("A simple character device driver to demo the implementation of fasync method"); 94 | 95 | -------------------------------------------------------------------------------- /net/vnet/vnet.c: -------------------------------------------------------------------------------- 1 | /* 2 | * A software defined network device... 3 | * Mar.30, 2015 4 | */ 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | 13 | struct vnet_private { 14 | int a; 15 | int reserved; 16 | }; 17 | 18 | int vnet_open(struct net_device *dev) 19 | { 20 | printk(KERN_INFO "++%s\n", __func__); 21 | //dump_stack(); 22 | netif_carrier_on(dev); 23 | return 0; 24 | } 25 | 26 | int vnet_close(struct net_device *dev) 27 | { 28 | printk(KERN_INFO "++%s\n", __func__); 29 | 30 | return 0; 31 | } 32 | 33 | 34 | netdev_tx_t vnet_start_xmit(struct sk_buff *skb, struct net_device *dev) 35 | { 36 | struct ethhdr *hdr, *eth; 37 | u16 ether_type; 38 | printk(KERN_INFO "++%s\n", __func__); 39 | //dev->stats.tx_dropped++; 40 | hdr = (struct ethhdr *)skb->data; 41 | eth = eth_hdr(skb); 42 | ether_type = ntohs(hdr->h_proto); 43 | printk(KERN_INFO "ether_type = 0x%x, protocol = 0x%x\n", ether_type, ntohs(skb->protocol)); 44 | printk(KERN_INFO "h_proto = 0x%x, dest = %s, src = %s\n", ntohs(eth->h_proto), eth->h_dest, eth->h_source); 45 | dev_kfree_skb_any(skb); 46 | //netif_stop_queue(dev); 47 | return NETDEV_TX_OK; 48 | } 49 | 50 | void vnet_tx_timeout(struct net_device *dev) 51 | { 52 | printk(KERN_INFO "++%s\n", __func__); 53 | 54 | return; 55 | } 56 | 57 | static const struct net_device_ops vnet_ops = { 58 | .ndo_open = vnet_open, 59 | .ndo_stop = vnet_close, 60 | .ndo_start_xmit = vnet_start_xmit, 61 | .ndo_tx_timeout = vnet_tx_timeout, 62 | }; 63 | 64 | static struct net_device *ndev; 65 | 66 | static int vnet_init(void) 67 | { 68 | struct vnet_private *vnet_priv; 69 | int rc; 70 | 71 | printk(KERN_INFO "++%s\n", __func__); 72 | 73 | ndev = alloc_etherdev(sizeof(struct vnet_private)); 74 | if (!ndev) 75 | return -ENOMEM; 76 | 77 | //SET_NETDEV_DEV(ndev, &pdev->dev); 78 | ndev->netdev_ops = &vnet_ops; 79 | vnet_priv = netdev_priv(ndev); 80 | ndev->watchdog_timeo = 5 * HZ; 81 | 82 | rc = register_netdev(ndev); 83 | 84 | netif_carrier_off(ndev); 85 | 86 | return rc; 87 | 88 | 89 | } 90 | 91 | static void vnet_exit(void) 92 | { 93 | printk(KERN_INFO "--%s\n", __func__); 94 | unregister_netdev(ndev); 95 | if (ndev) 96 | free_netdev(ndev); 97 | } 98 | 99 | module_init(vnet_init); 100 | module_exit(vnet_exit); 101 | 102 | MODULE_LICENSE("GPL"); 103 | MODULE_AUTHOR("dennis chen"); 104 | MODULE_DESCRIPTION("A software defined network device driver"); 105 | -------------------------------------------------------------------------------- /chap09/kobj/kobj_demo.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | static struct kobject *parent; 8 | static struct kobject *child; 9 | static struct kset *c_kset; 10 | 11 | static unsigned long flag = 1; 12 | 13 | static ssize_t att_show(struct kobject *kobj, struct attribute *attr, char *buf) 14 | { 15 | size_t count = 0; 16 | count += sprintf(&buf[count], "%lu\n", flag); 17 | 18 | return count; 19 | } 20 | 21 | static ssize_t att_store(struct kobject *kobj, struct attribute *attr, 22 | const char *buf, size_t count) 23 | { 24 | flag = buf[0] - '0'; 25 | switch(flag){ 26 | case 0: 27 | kobject_uevent(kobj, KOBJ_ADD); 28 | break; 29 | case 1: 30 | kobject_uevent(kobj, KOBJ_REMOVE); 31 | break; 32 | case 2: 33 | kobject_uevent(kobj, KOBJ_CHANGE); 34 | break; 35 | case 3: 36 | kobject_uevent(kobj, KOBJ_MOVE); 37 | break; 38 | case 4: 39 | kobject_uevent(kobj, KOBJ_ONLINE); 40 | break; 41 | case 5: 42 | kobject_uevent(kobj, KOBJ_OFFLINE); 43 | break; 44 | case 6: 45 | kobj->uevent_suppress = 1; 46 | break; 47 | case 7: 48 | kobj->uevent_suppress = 0; 49 | break; 50 | } 51 | return count; 52 | } 53 | 54 | static struct attribute cld_att = { 55 | .name = "cldatt", 56 | .mode = S_IRUGO | S_IWUSR, 57 | }; 58 | 59 | static const struct sysfs_ops att_ops = { 60 | .show = att_show, 61 | .store = att_store, 62 | }; 63 | 64 | static struct kobj_type cld_ktype = { 65 | .sysfs_ops = &att_ops, 66 | }; 67 | 68 | static int kobj_demo_init(void) 69 | { 70 | int err; 71 | 72 | parent = kobject_create_and_add("pa_obj", NULL); 73 | child = kzalloc(sizeof(*child), GFP_KERNEL); 74 | if(!child) 75 | return PTR_ERR(child); 76 | 77 | c_kset = kset_create_and_add("c_kset", NULL, parent); 78 | if(!c_kset) 79 | return -1; 80 | child->kset = c_kset; 81 | 82 | err = kobject_init_and_add(child, &cld_ktype, parent, "cld_obj"); 83 | if(err) 84 | return err; 85 | err = sysfs_create_file(child, &cld_att); 86 | 87 | return err; 88 | } 89 | 90 | static void kobj_demo_exit(void) 91 | { 92 | sysfs_remove_file(child, &cld_att); 93 | 94 | kset_unregister(c_kset); 95 | kobject_del(child); 96 | kobject_del(parent); 97 | } 98 | 99 | module_init(kobj_demo_init); 100 | module_exit(kobj_demo_exit); 101 | 102 | MODULE_LICENSE("GPL"); 103 | MODULE_AUTHOR("dennis chen @ AMDLinuxFGL"); 104 | MODULE_DESCRIPTION("A simple kernel module to demo the kobject behavior"); 105 | 106 | -------------------------------------------------------------------------------- /chap10/mmap/mmap_demo.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #define KSTR_DEF "Hello world from kernel virtual space" 16 | 17 | static struct cdev *pcdev; 18 | static dev_t ndev; 19 | static struct page *pg; 20 | static struct timer_list timer; 21 | 22 | static void timer_func(unsigned long data) 23 | { 24 | printk("timer_func:%s\n", (char *)data); 25 | timer.expires = jiffies + HZ*10; 26 | add_timer(&timer); 27 | } 28 | 29 | static int demo_open(struct inode *inode, struct file *filp) 30 | { 31 | return 0; 32 | } 33 | 34 | static int demo_release(struct inode *inode, struct file *filp) 35 | { 36 | return 0; 37 | } 38 | 39 | static int demo_mmap(struct file *filp, struct vm_area_struct *vma) 40 | { 41 | int err = 0; 42 | unsigned long start = vma->vm_start; 43 | unsigned long size = vma->vm_end - vma->vm_start; 44 | 45 | err = remap_pfn_range(vma, start, vma->vm_pgoff, size, vma->vm_page_prot); 46 | return err; 47 | } 48 | 49 | 50 | static struct file_operations mmap_fops = 51 | { .owner = THIS_MODULE, 52 | .open = demo_open, 53 | .release = demo_release, 54 | .mmap = demo_mmap, 55 | }; 56 | 57 | 58 | 59 | static int demo_map_init(void) 60 | { 61 | int err = 0; 62 | char *kstr; 63 | 64 | // allocate a page in HIGH_MEM area 65 | pg = alloc_pages(GFP_HIGHUSER, 0); 66 | if(!pg) 67 | return -ENOMEM; 68 | SetPageReserved(pg); 69 | // page comes from the highmem area, so need to call kmap to establish the mapping mechanism... 70 | kstr = (char *)kmap(pg); 71 | strcpy(kstr, KSTR_DEF); 72 | printk("kpa = 0x%lx, kernel string = %s\n", page_to_phys(pg), kstr); 73 | 74 | pcdev = cdev_alloc(); 75 | if(!pcdev){ 76 | err = -ENOMEM; 77 | goto cdev_err; 78 | } 79 | cdev_init(pcdev, &mmap_fops); 80 | err = alloc_chrdev_region(&ndev, 0, 1, "mmap_dev"); 81 | if(err) 82 | goto region_err; 83 | printk("major = %d, minor = %d\n", MAJOR(ndev), MINOR(ndev)); 84 | pcdev->owner = THIS_MODULE; 85 | err = cdev_add(pcdev, ndev, 1); 86 | if(err) 87 | goto add_err; 88 | 89 | init_timer(&timer); 90 | timer.function = timer_func; 91 | timer.data = (unsigned long)kstr; 92 | timer.expires = jiffies + HZ*10; 93 | add_timer(&timer); 94 | goto done; 95 | 96 | add_err: 97 | unregister_chrdev_region(ndev, 1); 98 | region_err: 99 | cdev_del(pcdev); 100 | cdev_err: 101 | kunmap(pg); 102 | ClearPageReserved(pg); 103 | __free_pages(pg, 0); 104 | done: 105 | return err; 106 | } 107 | 108 | static void demo_map_exit(void) 109 | { 110 | del_timer_sync(&timer); 111 | cdev_del(pcdev); 112 | unregister_chrdev_region(ndev, 1); 113 | kunmap(pg); 114 | ClearPageReserved(pg); 115 | __free_pages(pg, 0); 116 | } 117 | 118 | module_init(demo_map_init); 119 | module_exit(demo_map_exit); 120 | 121 | MODULE_AUTHOR("dennis chen @ AMDLinuxFGL"); 122 | MODULE_DESCRIPTION("Remap a physical page in the kernel space to the user space"); 123 | MODULE_LICENSE("GPL"); 124 | -------------------------------------------------------------------------------- /chap11/ramhd_req/ramhd_req.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #define RAMHD_NAME "ramsd" 13 | #define RAMHD_MAX_DEVICE 2 14 | #define RAMHD_MAX_PARTITIONS 4 15 | 16 | #define RAMHD_SECTOR_SIZE 512 17 | #define RAMHD_SECTORS 16 18 | #define RAMHD_HEADS 4 19 | #define RAMHD_CYLINDERS 256 20 | 21 | #define RAMHD_SECTOR_TOTAL (RAMHD_SECTORS * RAMHD_HEADS * RAMHD_CYLINDERS) 22 | #define RAMHD_SIZE (RAMHD_SECTOR_SIZE * RAMHD_SECTOR_TOTAL) //8MB 23 | 24 | typedef struct{ 25 | unsigned char *data; 26 | struct request_queue *queue; 27 | spinlock_t lock; 28 | struct gendisk *gd; 29 | }RAMHD_DEV; 30 | 31 | static char *sdisk[RAMHD_MAX_DEVICE]; 32 | static RAMHD_DEV *rdev[RAMHD_MAX_DEVICE]; 33 | 34 | static dev_t ramhd_major; 35 | 36 | static int ramhd_space_init(void) 37 | { 38 | int i; 39 | int err = 0; 40 | for(i = 0; i < RAMHD_MAX_DEVICE; i++){ 41 | sdisk[i] = vmalloc(RAMHD_SIZE); 42 | if(!sdisk[i]){ 43 | err = -ENOMEM; 44 | return err; 45 | } 46 | memset(sdisk[i], 0, RAMHD_SIZE); 47 | } 48 | 49 | return err; 50 | } 51 | 52 | static void ramhd_space_clean(void) 53 | { 54 | int i; 55 | for(i = 0; i < RAMHD_MAX_DEVICE; i++){ 56 | vfree(sdisk[i]); 57 | } 58 | } 59 | 60 | static int alloc_ramdev(void) 61 | { 62 | int i; 63 | for(i = 0; i < RAMHD_MAX_DEVICE; i++){ 64 | rdev[i] = kzalloc(sizeof(RAMHD_DEV), GFP_KERNEL); 65 | if(!rdev[i]) 66 | return -ENOMEM; 67 | } 68 | return 0; 69 | } 70 | 71 | static void clean_ramdev(void) 72 | { 73 | int i; 74 | for(i = 0; i < RAMHD_MAX_DEVICE; i++){ 75 | if(rdev[i]) 76 | kfree(rdev[i]); 77 | } 78 | } 79 | 80 | int ramhd_open(struct block_device *bdev, fmode_t mode) 81 | { 82 | return 0; 83 | } 84 | 85 | int ramhd_release(struct gendisk *gd, fmode_t mode) 86 | { 87 | return 0; 88 | } 89 | 90 | static int ramhd_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) 91 | { 92 | int err; 93 | struct hd_geometry geo; 94 | 95 | switch(cmd) 96 | { 97 | case HDIO_GETGEO: 98 | err = !access_ok(VERIFY_WRITE, arg, sizeof(geo)); 99 | if(err) return -EFAULT; 100 | 101 | geo.cylinders = RAMHD_CYLINDERS; 102 | geo.heads = RAMHD_HEADS; 103 | geo.sectors = RAMHD_SECTORS; 104 | geo.start = get_start_sect(bdev); 105 | if(copy_to_user((void *)arg, &geo, sizeof(geo))) 106 | return -EFAULT; 107 | return 0; 108 | } 109 | 110 | return -ENOTTY; 111 | } 112 | 113 | static struct block_device_operations ramhd_fops = 114 | { .owner = THIS_MODULE, 115 | .open = ramhd_open, 116 | .release = ramhd_release, 117 | .ioctl = ramhd_ioctl, 118 | }; 119 | 120 | void ramhd_req_func (struct request_queue *q) 121 | { 122 | struct request *req; 123 | RAMHD_DEV *pdev; 124 | char *pData; 125 | unsigned long addr, size, start; 126 | req = blk_fetch_request(q); 127 | while (req) { 128 | start = blk_rq_pos(req); // The sector cursor of the current request 129 | pdev = (RAMHD_DEV *)req->rq_disk->private_data; 130 | pData = pdev->data; 131 | addr = (unsigned long)pData + start * RAMHD_SECTOR_SIZE; 132 | size = blk_rq_cur_bytes(req); 133 | if (rq_data_dir(req) == READ) 134 | memcpy(req->buffer, (char *)addr, size); 135 | else 136 | memcpy((char *)addr, req->buffer, size); 137 | 138 | if(!__blk_end_request_cur(req, 0)) 139 | req = blk_fetch_request(q); 140 | } 141 | } 142 | 143 | int ramhd_init(void) 144 | { 145 | int i; 146 | ramhd_space_init(); 147 | alloc_ramdev(); 148 | 149 | ramhd_major = register_blkdev(0, RAMHD_NAME); 150 | 151 | for(i = 0; i < RAMHD_MAX_DEVICE; i++) 152 | { 153 | rdev[i]->data = sdisk[i]; 154 | rdev[i]->gd = alloc_disk(RAMHD_MAX_PARTITIONS); 155 | spin_lock_init(&rdev[i]->lock); 156 | rdev[i]->queue = blk_init_queue(ramhd_req_func, &rdev[i]->lock); 157 | rdev[i]->gd->major = ramhd_major; 158 | rdev[i]->gd->first_minor = i * RAMHD_MAX_PARTITIONS; 159 | rdev[i]->gd->fops = &ramhd_fops; 160 | rdev[i]->gd->queue = rdev[i]->queue; 161 | rdev[i]->gd->private_data = rdev[i]; 162 | sprintf(rdev[i]->gd->disk_name, "ramsd%c", 'a'+i); 163 | set_capacity(rdev[i]->gd, RAMHD_SECTOR_TOTAL); 164 | add_disk(rdev[i]->gd); 165 | } 166 | 167 | return 0; 168 | } 169 | 170 | void ramhd_exit(void) 171 | { 172 | int i; 173 | for(i = 0; i < RAMHD_MAX_DEVICE; i++) 174 | { 175 | del_gendisk(rdev[i]->gd); 176 | put_disk(rdev[i]->gd); 177 | blk_cleanup_queue(rdev[i]->queue); 178 | } 179 | unregister_blkdev(ramhd_major,RAMHD_NAME); 180 | clean_ramdev(); 181 | ramhd_space_clean(); 182 | } 183 | 184 | module_init(ramhd_init); 185 | module_exit(ramhd_exit); 186 | 187 | MODULE_AUTHOR("dennis chen @ AMDLinuxFGL"); 188 | MODULE_DESCRIPTION("The ramdisk implementation with request function"); 189 | MODULE_LICENSE("GPL"); 190 | -------------------------------------------------------------------------------- /aio/aioapp.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | 11 | #define FLAGS_file_size 0x1000 12 | #define concurrent_requests 100 13 | #define FLAGS_min_nr 1 14 | #define FLAGS_max_nr 1 15 | 16 | // The size of operation that will occur on the device 17 | static const int kPageSize = 4096; 18 | 19 | class AIORequest { 20 | public: 21 | int* buffer_; 22 | 23 | virtual void Complete(int res) = 0; 24 | 25 | AIORequest() { 26 | int ret = posix_memalign(reinterpret_cast(&buffer_), 27 | kPageSize, kPageSize); 28 | } 29 | 30 | virtual ~AIORequest() { 31 | free(buffer_); 32 | } 33 | }; 34 | 35 | class Adder { 36 | public: 37 | virtual void Add(int amount) = 0; 38 | 39 | virtual ~Adder() { }; 40 | }; 41 | 42 | class AIOReadRequest : public AIORequest { 43 | private: 44 | Adder* adder_; 45 | 46 | public: 47 | AIOReadRequest(Adder* adder) : AIORequest(), adder_(adder) { } 48 | virtual void Complete(int res) { 49 | int value = buffer_[0]; 50 | cout << "Read of " << value << " completed" << endl; 51 | adder_->Add(value); 52 | } 53 | }; 54 | 55 | class AIOWriteRequest : public AIORequest { 56 | private: 57 | int value_; 58 | 59 | public: 60 | AIOWriteRequest(int value) : AIORequest(), value_(value) { 61 | buffer_[0] = value; 62 | } 63 | 64 | virtual void Complete(int res) { 65 | cout << "Write of " << value_ << " completed" << endl; 66 | } 67 | }; 68 | 69 | class AIOAdder : public Adder { 70 | public: 71 | int fd_; 72 | io_context_t ioctx_; 73 | int counter_; 74 | int reap_counter_; 75 | int sum_; 76 | int length_; 77 | 78 | AIOAdder(int length) 79 | : ioctx_(0), counter_(0), reap_counter_(0), sum_(0), length_(length) { } 80 | 81 | void Init() { 82 | cout << "Opening file" << endl; 83 | fd_ = open("/tmp/testfile", O_RDWR | O_DIRECT | O_CREAT, 0644); 84 | if (fd_ == -1) { 85 | cout << "open file failed" << endl; 86 | return; 87 | } 88 | 89 | if (fallocate(fd_, 0, 0, kPageSize * length_) != 0) { 90 | cout << "fallocate failed" << endl; 91 | return; 92 | } 93 | 94 | cout << "Allocating enough space for the sum" << endl; 95 | cout << "Setting up the io context" << endl; 96 | if (io_setup(100, &ioctx_) != 0) { 97 | cout << "io_setup failed" << endl; 98 | return; 99 | } 100 | } 101 | 102 | virtual void Add(int amount) { 103 | sum_ += amount; 104 | cout << "Adding " << amount << " for a total of " << sum_ << endl; 105 | } 106 | void SubmitWrite() { 107 | cout << "Submitting a write to " << counter_ << endl; 108 | struct iocb iocb; 109 | struct iocb* iocbs = &iocb; 110 | AIORequest *req = new AIOWriteRequest(counter_); 111 | io_prep_pwrite(&iocb, fd_, req->buffer_, kPageSize, counter_ * kPageSize); 112 | iocb.data = req; 113 | int res = io_submit(ioctx_, 1, &iocbs); 114 | } 115 | 116 | void WriteFile() { 117 | reap_counter_ = 0; 118 | for (counter_ = 0; counter_ < length_; counter_++) { 119 | SubmitWrite(); 120 | Reap(); 121 | } 122 | ReapRemaining(); 123 | } 124 | 125 | void SubmitRead() { 126 | cout << "Submitting a read from " << counter_ << endl; 127 | struct iocb iocb; 128 | struct iocb* iocbs = &iocb; 129 | AIORequest *req = new AIOReadRequest(this); 130 | io_prep_pread(&iocb, fd_, req->buffer_, kPageSize, counter_ * kPageSize); 131 | iocb.data = req; 132 | int res = io_submit(ioctx_, 1, &iocbs); 133 | } 134 | 135 | void ReadFile() { 136 | reap_counter_ = 0; 137 | for (counter_ = 0; counter_ < length_; counter_++) { 138 | SubmitRead(); 139 | Reap(); 140 | } 141 | ReapRemaining(); 142 | } 143 | 144 | int DoReap(int min_nr) { 145 | cout << "Reaping between " << min_nr << " and " 146 | << FLAGS_max_nr << " io_events" << endl; 147 | struct io_event* events = new io_event[FLAGS_max_nr]; 148 | struct timespec timeout; 149 | timeout.tv_sec = 0; 150 | timeout.tv_nsec = 100000000; 151 | int num_events; 152 | cout << "Calling io_getevents" << endl; 153 | num_events = io_getevents(ioctx_, min_nr, FLAGS_max_nr, events, 154 | &timeout); 155 | cout << "Calling completion function on results" << endl; 156 | for (int i = 0; i < num_events; i++) { 157 | struct io_event event = events[i]; 158 | AIORequest* req = static_cast(event.data); 159 | req->Complete(event.res); 160 | delete req; 161 | } 162 | delete events; 163 | 164 | cout << "Reaped " << num_events << " io_events" << endl; 165 | reap_counter_ += num_events; 166 | return num_events; 167 | } 168 | 169 | void Reap() { 170 | if (counter_ >= FLAGS_min_nr) { 171 | DoReap(FLAGS_min_nr); 172 | } 173 | } 174 | 175 | void ReapRemaining() { 176 | while (reap_counter_ < length_) { 177 | DoReap(1); 178 | } 179 | } 180 | 181 | ~AIOAdder() { 182 | cout << "Closing AIO context and file" << endl; 183 | io_destroy(ioctx_); 184 | close(fd_); 185 | } 186 | 187 | int Sum() { 188 | cout << "Writing consecutive integers to file" << endl; 189 | WriteFile(); 190 | cout << "Reading consecutive integers from file" << endl; 191 | ReadFile(); 192 | return sum_; 193 | } 194 | }; 195 | 196 | int main(int argc, char* argv[]) { 197 | AIOAdder adder(FLAGS_file_size); 198 | adder.Init(); 199 | int sum = adder.Sum(); 200 | int expected = (FLAGS_file_size * (FLAGS_file_size - 1)) / 2; 201 | cout << "AIO is complete" << endl; 202 | printf("Successfully calculated that the sum of integers from 0" 203 | " to %d is %d\n", FLAGS_file_size - 1, sum); 204 | return 0; 205 | } 206 | 207 | -------------------------------------------------------------------------------- /chap11/ramhd_mkreq/ramhd_mkreq.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #define RAMHD_NAME "ramhd" 13 | #define RAMHD_MAX_DEVICE 2 14 | #define RAMHD_MAX_PARTITIONS 4 15 | 16 | #define RAMHD_SECTOR_SIZE 512 17 | #define RAMHD_SECTORS 16 18 | #define RAMHD_HEADS 4 19 | #define RAMHD_CYLINDERS 256 20 | 21 | #define RAMHD_SECTOR_TOTAL (RAMHD_SECTORS * RAMHD_HEADS * RAMHD_CYLINDERS) 22 | #define RAMHD_SIZE (RAMHD_SECTOR_SIZE * RAMHD_SECTOR_TOTAL) //8MB 23 | 24 | typedef struct{ 25 | unsigned char *data; 26 | struct request_queue *queue; 27 | struct gendisk *gd; 28 | }RAMHD_DEV; 29 | 30 | static char *sdisk[RAMHD_MAX_DEVICE] = {NULL,}; 31 | static RAMHD_DEV *rdev[RAMHD_MAX_DEVICE] = {NULL,}; 32 | 33 | static dev_t ramhd_major; 34 | 35 | static int ramhd_space_init(void) 36 | { 37 | int i; 38 | int err = 0; 39 | for(i = 0; i < RAMHD_MAX_DEVICE; i++){ 40 | sdisk[i] = vmalloc(RAMHD_SIZE); 41 | if(!sdisk[i]){ 42 | printk("vmalloc failed!"); 43 | err = -ENOMEM; 44 | return err; 45 | } 46 | memset(sdisk[i], 0, RAMHD_SIZE); 47 | } 48 | 49 | return err; 50 | } 51 | 52 | static void ramhd_space_clean(void) 53 | { 54 | int i; 55 | for(i = 0; i < RAMHD_MAX_DEVICE; i++){ 56 | vfree(sdisk[i]); 57 | } 58 | } 59 | 60 | static int ramhd_open(struct block_device *bdev, fmode_t mode) 61 | { 62 | return 0; 63 | } 64 | 65 | static int ramhd_release(struct gendisk *gd, fmode_t mode) 66 | { 67 | return 0; 68 | } 69 | 70 | static int ramhd_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) 71 | { 72 | int err; 73 | struct hd_geometry geo; 74 | 75 | switch(cmd) 76 | { 77 | case HDIO_GETGEO: 78 | err = !access_ok(VERIFY_WRITE, arg, sizeof(geo)); 79 | if(err) return -EFAULT; 80 | 81 | geo.cylinders = RAMHD_CYLINDERS; 82 | geo.heads = RAMHD_HEADS; 83 | geo.sectors = RAMHD_SECTORS; 84 | geo.start = get_start_sect(bdev); 85 | if(copy_to_user((void *)arg, &geo, sizeof(geo))) 86 | return -EFAULT; 87 | return 0; 88 | } 89 | 90 | return -ENOTTY; 91 | } 92 | 93 | static struct block_device_operations ramhd_fops = 94 | { .owner = THIS_MODULE, 95 | .open = ramhd_open, 96 | .release = ramhd_release, 97 | .ioctl = ramhd_ioctl, 98 | }; 99 | 100 | static int ramhd_make_request(struct request_queue *q, struct bio *bio) 101 | { 102 | char *pRHdata; 103 | char *pBuffer; 104 | struct bio_vec *bvec; 105 | int i; 106 | int err = 0; 107 | 108 | struct block_device *bdev = bio->bi_bdev; 109 | RAMHD_DEV *pdev = bdev->bd_disk->private_data; 110 | 111 | if(((bio->bi_sector * RAMHD_SECTOR_SIZE) + bio->bi_size) > RAMHD_SIZE){ 112 | err = -EIO; 113 | goto out; 114 | } 115 | 116 | pRHdata = pdev->data + (bio->bi_sector * RAMHD_SECTOR_SIZE); 117 | 118 | bio_for_each_segment(bvec, bio, i) { 119 | pBuffer = kmap(bvec->bv_page) + bvec->bv_offset; 120 | switch(bio_data_dir(bio)) 121 | { 122 | case READ: 123 | memcpy(pBuffer, pRHdata, bvec->bv_len); 124 | flush_dcache_page(bvec->bv_page); 125 | break; 126 | case WRITE: 127 | flush_dcache_page(bvec->bv_page); 128 | memcpy(pRHdata, pBuffer, bvec->bv_len); 129 | break; 130 | default: 131 | kunmap(bvec->bv_page); 132 | goto out; 133 | } 134 | kunmap(bvec->bv_page); 135 | pRHdata += bvec->bv_len; 136 | } 137 | out: 138 | bio_endio(bio, err); 139 | return 0; 140 | } 141 | 142 | static int alloc_ramdev(void) 143 | { 144 | int i; 145 | for(i = 0; i < RAMHD_MAX_DEVICE; i++){ 146 | rdev[i] = kzalloc(sizeof(RAMHD_DEV), GFP_KERNEL); 147 | if(!rdev[i]) 148 | return -ENOMEM; 149 | } 150 | return 0; 151 | } 152 | 153 | static void clean_ramdev(void) 154 | { 155 | int i; 156 | for(i = 0; i < RAMHD_MAX_DEVICE; i++){ 157 | if(rdev[i]) 158 | kfree(rdev[i]); 159 | } 160 | } 161 | 162 | static int __init ramhd_init(void) 163 | { 164 | int i; 165 | int err; 166 | 167 | err = ramhd_space_init(); 168 | if(err) 169 | return err; 170 | alloc_ramdev(); 171 | 172 | ramhd_major = register_blkdev(0, RAMHD_NAME); 173 | 174 | for(i = 0; i < RAMHD_MAX_DEVICE; i++) 175 | { 176 | rdev[i]->data = sdisk[i]; 177 | rdev[i]->queue = blk_alloc_queue(GFP_KERNEL); 178 | blk_queue_make_request(rdev[i]->queue, ramhd_make_request); 179 | rdev[i]->gd = alloc_disk(RAMHD_MAX_PARTITIONS); 180 | rdev[i]->gd->major = ramhd_major; 181 | rdev[i]->gd->first_minor = i * RAMHD_MAX_PARTITIONS; 182 | rdev[i]->gd->fops = &ramhd_fops; 183 | rdev[i]->gd->queue = rdev[i]->queue; 184 | rdev[i]->gd->private_data = rdev[i]; 185 | sprintf(rdev[i]->gd->disk_name, "ramhd%c", 'a'+i); 186 | rdev[i]->gd->flags |= GENHD_FL_SUPPRESS_PARTITION_INFO; 187 | set_capacity(rdev[i]->gd, RAMHD_SECTOR_TOTAL); 188 | add_disk(rdev[i]->gd); 189 | } 190 | return 0; 191 | } 192 | 193 | static void __exit ramhd_exit(void) 194 | { 195 | int i; 196 | 197 | for(i = 0; i < RAMHD_MAX_DEVICE; i++) 198 | { 199 | del_gendisk(rdev[i]->gd); 200 | put_disk(rdev[i]->gd); 201 | blk_cleanup_queue(rdev[i]->queue); 202 | } 203 | clean_ramdev(); 204 | ramhd_space_clean(); 205 | unregister_blkdev(ramhd_major,RAMHD_NAME); 206 | } 207 | 208 | module_init(ramhd_init); 209 | module_exit(ramhd_exit); 210 | 211 | MODULE_AUTHOR("dennis chen @AMDLinuxFGL"); 212 | MODULE_DESCRIPTION("The ramdisk implementation with request function"); 213 | MODULE_LICENSE("GPL"); 214 | -------------------------------------------------------------------------------- /kmodule/sysfs_race/create/BUG_ON.txt: -------------------------------------------------------------------------------- 1 | 2 | ----------- BUG_ON(!root) output message --------------- 3 | [ 333.066327] +myfs_mount 4 | [ 333.066341] ------------[ cut here ]------------ 5 | [ 333.066389] kernel BUG at fs/super.c:1119! 6 | [ 333.066431] invalid opcode: 0000 [#1] SMP 7 | [ 333.066474] Modules linked in: fsmod(O+) rpcsec_gss_krb5 auth_rpcgss oid_registry nfsv4 target_core_mod configfs ip6table_filter ip6_tables ebtable_nat ebtables ipt_MASQUERADE iptable_nat nf_nat_ipv4 nf_nat nf_conntrack_ipv4 nf_defrag_ipv4 xt_conntrack nf_conntrack ipt_REJECT xt_CHECKSUM iptable_mangle xt_tcpudp iptable_filter ip_tables x_tables openvswitch ib_iser rdma_cm ib_cm iw_cm ib_sa ib_mad ib_core ib_addr iscsi_tcp libiscsi_tcp libiscsi scsi_transport_iscsi bridge stp dm_crypt llc rfcomm bnep bluetooth parport_pc ppdev nfsd nfs_acl nfs fscache lockd sunrpc kvm_intel kvm binfmt_misc psmouse dm_multipath microcode scsi_dh serio_raw dcdbas lpc_ich lp parport hid_generic ghash_clmulni_intel cryptd i915 drm_kms_helper r8169 drm usbhid hid i2c_algo_bit video [last unloaded: fsmod] 8 | [ 333.067153] CPU: 2 PID: 3277 Comm: insmod Tainted: G O 3.10.0 #4 9 | [ 333.067195] Hardware name: Dell Inc. OptiPlex 390/0M5DCD, BIOS A05 02/09/2012 10 | [ 333.067239] task: ffff88010a142e40 ti: ffff8800af186000 task.ti: ffff8800af186000 11 | [ 333.067284] RIP: 0010:[] [] mount_fs+0x1d2/0x1e0 12 | [ 333.067337] RSP: 0018:ffff8800af187c88 EFLAGS: 00010246 13 | [ 333.067369] RAX: 0000000000000000 RBX: ffff8800b7952f00 RCX: 0000000000000006 14 | [ 333.067412] RDX: 0000000000000007 RSI: 0000000000000046 RDI: ffff88012ec4d090 15 | [ 333.067455] RBP: ffff8800af187cc8 R08: 000000000000000a R09: 00000000000002f2 16 | [ 333.067498] R10: 0000000000000000 R11: 00000000000002f1 R12: 0000000000000000 17 | [ 333.067541] R13: ffffffffa050e000 R14: 0000000000000000 R15: 0000000000400000 18 | [ 333.067584] FS: 00007ffc21944700(0000) GS:ffff88012ec40000(0000) knlGS:0000000000000000 19 | [ 333.067633] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 20 | [ 333.067668] CR2: 00007ffc214813c0 CR3: 00000000b78df000 CR4: 00000000000407e0 21 | [ 333.067711] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 22 | [ 333.067753] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 23 | [ 333.067796] Stack: 24 | [ 333.067809] ffff8800af187c98 ffffffff81128ab0 ffff8800af187cc8 ffff8800b7952f00 25 | [ 333.067857] fffffffffffffff4 ffffffffa050e000 ffffffffa050d05d 0000000000400000 26 | [ 333.067905] ffff8800af187d18 ffffffff81189ea4 00000000fffffff0 0000000000000000 27 | [ 333.067953] Call Trace: 28 | [ 333.067974] [] ? __alloc_percpu+0x10/0x20 29 | [ 333.068011] [] vfs_kern_mount+0x74/0x110 30 | [ 333.068048] [] ? myfs_mount+0x20/0x20 [fsmod] 31 | [ 333.068086] [] kern_mount_data+0x19/0x30 32 | [ 333.068122] [] fsmod_init+0x46/0x80 [fsmod] 33 | [ 333.068162] [] do_one_initcall+0x112/0x170 34 | [ 333.068200] [] load_module+0x1bee/0x2570 35 | [ 333.068236] [] ? unset_module_init_ro_nx+0x80/0x80 36 | [ 333.068278] [] SyS_init_module+0xce/0x100 37 | [ 333.070311] [] system_call_fastpath+0x16/0x1b 38 | [ 333.072350] Code: a2 81 e8 92 01 ed ff e9 dc fe ff ff be 62 04 00 00 48 c7 c7 be d6 a2 81 e8 7c 01 ed ff 48 8b 83 28 01 00 00 e9 b3 fe ff ff 0f 0b <0f> 0b 4c 63 e0 e9 1b ff ff ff 0f 1f 40 00 66 66 66 66 90 55 48 39 | [ 333.077135] RIP [] mount_fs+0x1d2/0x1e0 40 | [ 333.079318] RSP 41 | [ 333.089600] ---[ end trace b2e799ffd0197c81 ]--- 42 | 43 | 44 | ----------- type->mount() direct msg --------------- 45 | [ 171.578861] BUG: unable to handle kernel NULL pointer dereference at (null) 46 | [ 171.578949] IP: [< (null)>] (null) 47 | [ 171.578973] PGD b1c7d067 PUD b1d31067 PMD 0 48 | [ 171.578996] Oops: 0010 [#1] SMP 49 | [ 171.579013] Modules linked in: fsmod(O+) rpcsec_gss_krb5 auth_rpcgss oid_registry nfsv4 ip6table_filter ip6_tables ebtable_nat ebtables target_core_mod configfs ipt_MASQUERADE iptable_nat nf_nat_ipv4 nf_nat nf_conntrack_ipv4 nf_defrag_ipv4 xt_conntrack nf_conntrack ipt_REJECT xt_CHECKSUM iptable_mangle xt_tcpudp iptable_filter ip_tables x_tables openvswitch ib_iser rdma_cm ib_cm iw_cm ib_sa ib_mad ib_core ib_addr iscsi_tcp libiscsi_tcp libiscsi scsi_transport_iscsi bridge stp llc dm_crypt rfcomm bnep bluetooth parport_pc ppdev nfsd nfs_acl nfs fscache lockd sunrpc kvm_intel kvm binfmt_misc psmouse dm_multipath serio_raw microcode scsi_dh dcdbas lpc_ich lp parport hid_generic ghash_clmulni_intel cryptd i915 drm_kms_helper usbhid r8169 hid drm i2c_algo_bit video 50 | [ 171.579347] CPU: 2 PID: 2909 Comm: insmod Tainted: G O 3.10.0 #6 51 | [ 171.579378] Hardware name: Dell Inc. OptiPlex 390/0M5DCD, BIOS A05 02/09/2012 52 | [ 171.579407] task: ffff8800c3e5c560 ti: ffff88002e130000 task.ti: ffff88002e130000 53 | [ 171.579437] RIP: 0010:[<0000000000000000>] [< (null)>] (null) 54 | [ 171.579470] RSP: 0018:ffff88002e131c80 EFLAGS: 00010246 55 | [ 171.579494] RAX: ffff8800bbbb2100 RBX: ffff8800bbbb2100 RCX: 0000000000000000 56 | [ 171.579524] RDX: ffffffffa04fc07a RSI: 0000000000400000 RDI: ffffffffa04fd000 57 | [ 171.579554] RBP: ffff88002e131cc8 R08: ffffffff81cdc0e0 R09: 0000000000000100 58 | [ 171.579573] R10: 00000000000000f8 R11: 0000000000000000 R12: fffffffffffffff4 59 | [ 171.579591] R13: ffffffffa04fd000 R14: 0000000000000000 R15: 0000000000400000 60 | [ 171.579614] FS: 00007f8c0dd97700(0000) GS:ffff88012ec40000(0000) knlGS:0000000000000000 61 | [ 171.579636] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 62 | [ 171.579651] CR2: 0000000000000000 CR3: 00000000b1c68000 CR4: 00000000000407e0 63 | [ 171.579669] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 64 | [ 171.579688] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 65 | [ 171.579706] Stack: 66 | [ 171.579712] ffffffff811707b3 ffff88002e131c98 ffffffff81128ab0 ffff88002e131cc8 67 | [ 171.579733] ffff8800bbbb2100 fffffffffffffff4 ffffffffa04fd000 ffffffffa04fc07a 68 | [ 171.579754] 0000000000400000 ffff88002e131d18 ffffffff81189e74 00000000fffffff0 69 | [ 171.579774] Call Trace: 70 | [ 171.579785] [] ? mount_fs+0x43/0x1b0 71 | [ 171.579801] [] ? __alloc_percpu+0x10/0x20 72 | [ 171.579818] [] vfs_kern_mount+0x74/0x110 73 | [ 171.579834] [] ? npfs_kill_sb+0x10/0x10 [fsmod] 74 | [ 171.579851] [] kern_mount_data+0x19/0x30 75 | [ 171.579866] [] fsmod_init+0x46/0x80 [fsmod] 76 | [ 171.579885] [] do_one_initcall+0x112/0x170 77 | [ 171.579903] [] load_module+0x1bee/0x2570 78 | [ 171.580856] [] ? unset_module_init_ro_nx+0x80/0x80 79 | [ 171.581801] [] SyS_init_module+0xce/0x100 80 | [ 171.582751] [] system_call_fastpath+0x16/0x1b 81 | [ 171.583712] Code: Bad RIP value. 82 | [ 171.584631] RIP [< (null)>] (null) 83 | [ 171.585551] RSP 84 | [ 171.587094] CR2: 0000000000000000 85 | [ 171.597161] ---[ end trace 9f3147bed7f16176 ]--- 86 | 87 | 88 | //diff 89 | fs/super.c; fs/namespace.c;fs/filesystems.c 90 | 91 | -------------------------------------------------------------------------------- /kmodule/sysfs_race/delete/BUG_ON.txt: -------------------------------------------------------------------------------- 1 | 2 | ----------- BUG_ON(!root) output message --------------- 3 | [ 333.066327] +myfs_mount 4 | [ 333.066341] ------------[ cut here ]------------ 5 | [ 333.066389] kernel BUG at fs/super.c:1119! 6 | [ 333.066431] invalid opcode: 0000 [#1] SMP 7 | [ 333.066474] Modules linked in: fsmod(O+) rpcsec_gss_krb5 auth_rpcgss oid_registry nfsv4 target_core_mod configfs ip6table_filter ip6_tables ebtable_nat ebtables ipt_MASQUERADE iptable_nat nf_nat_ipv4 nf_nat nf_conntrack_ipv4 nf_defrag_ipv4 xt_conntrack nf_conntrack ipt_REJECT xt_CHECKSUM iptable_mangle xt_tcpudp iptable_filter ip_tables x_tables openvswitch ib_iser rdma_cm ib_cm iw_cm ib_sa ib_mad ib_core ib_addr iscsi_tcp libiscsi_tcp libiscsi scsi_transport_iscsi bridge stp dm_crypt llc rfcomm bnep bluetooth parport_pc ppdev nfsd nfs_acl nfs fscache lockd sunrpc kvm_intel kvm binfmt_misc psmouse dm_multipath microcode scsi_dh serio_raw dcdbas lpc_ich lp parport hid_generic ghash_clmulni_intel cryptd i915 drm_kms_helper r8169 drm usbhid hid i2c_algo_bit video [last unloaded: fsmod] 8 | [ 333.067153] CPU: 2 PID: 3277 Comm: insmod Tainted: G O 3.10.0 #4 9 | [ 333.067195] Hardware name: Dell Inc. OptiPlex 390/0M5DCD, BIOS A05 02/09/2012 10 | [ 333.067239] task: ffff88010a142e40 ti: ffff8800af186000 task.ti: ffff8800af186000 11 | [ 333.067284] RIP: 0010:[] [] mount_fs+0x1d2/0x1e0 12 | [ 333.067337] RSP: 0018:ffff8800af187c88 EFLAGS: 00010246 13 | [ 333.067369] RAX: 0000000000000000 RBX: ffff8800b7952f00 RCX: 0000000000000006 14 | [ 333.067412] RDX: 0000000000000007 RSI: 0000000000000046 RDI: ffff88012ec4d090 15 | [ 333.067455] RBP: ffff8800af187cc8 R08: 000000000000000a R09: 00000000000002f2 16 | [ 333.067498] R10: 0000000000000000 R11: 00000000000002f1 R12: 0000000000000000 17 | [ 333.067541] R13: ffffffffa050e000 R14: 0000000000000000 R15: 0000000000400000 18 | [ 333.067584] FS: 00007ffc21944700(0000) GS:ffff88012ec40000(0000) knlGS:0000000000000000 19 | [ 333.067633] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 20 | [ 333.067668] CR2: 00007ffc214813c0 CR3: 00000000b78df000 CR4: 00000000000407e0 21 | [ 333.067711] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 22 | [ 333.067753] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 23 | [ 333.067796] Stack: 24 | [ 333.067809] ffff8800af187c98 ffffffff81128ab0 ffff8800af187cc8 ffff8800b7952f00 25 | [ 333.067857] fffffffffffffff4 ffffffffa050e000 ffffffffa050d05d 0000000000400000 26 | [ 333.067905] ffff8800af187d18 ffffffff81189ea4 00000000fffffff0 0000000000000000 27 | [ 333.067953] Call Trace: 28 | [ 333.067974] [] ? __alloc_percpu+0x10/0x20 29 | [ 333.068011] [] vfs_kern_mount+0x74/0x110 30 | [ 333.068048] [] ? myfs_mount+0x20/0x20 [fsmod] 31 | [ 333.068086] [] kern_mount_data+0x19/0x30 32 | [ 333.068122] [] fsmod_init+0x46/0x80 [fsmod] 33 | [ 333.068162] [] do_one_initcall+0x112/0x170 34 | [ 333.068200] [] load_module+0x1bee/0x2570 35 | [ 333.068236] [] ? unset_module_init_ro_nx+0x80/0x80 36 | [ 333.068278] [] SyS_init_module+0xce/0x100 37 | [ 333.070311] [] system_call_fastpath+0x16/0x1b 38 | [ 333.072350] Code: a2 81 e8 92 01 ed ff e9 dc fe ff ff be 62 04 00 00 48 c7 c7 be d6 a2 81 e8 7c 01 ed ff 48 8b 83 28 01 00 00 e9 b3 fe ff ff 0f 0b <0f> 0b 4c 63 e0 e9 1b ff ff ff 0f 1f 40 00 66 66 66 66 90 55 48 39 | [ 333.077135] RIP [] mount_fs+0x1d2/0x1e0 40 | [ 333.079318] RSP 41 | [ 333.089600] ---[ end trace b2e799ffd0197c81 ]--- 42 | 43 | 44 | ----------- type->mount() direct msg --------------- 45 | [ 171.578861] BUG: unable to handle kernel NULL pointer dereference at (null) 46 | [ 171.578949] IP: [< (null)>] (null) 47 | [ 171.578973] PGD b1c7d067 PUD b1d31067 PMD 0 48 | [ 171.578996] Oops: 0010 [#1] SMP 49 | [ 171.579013] Modules linked in: fsmod(O+) rpcsec_gss_krb5 auth_rpcgss oid_registry nfsv4 ip6table_filter ip6_tables ebtable_nat ebtables target_core_mod configfs ipt_MASQUERADE iptable_nat nf_nat_ipv4 nf_nat nf_conntrack_ipv4 nf_defrag_ipv4 xt_conntrack nf_conntrack ipt_REJECT xt_CHECKSUM iptable_mangle xt_tcpudp iptable_filter ip_tables x_tables openvswitch ib_iser rdma_cm ib_cm iw_cm ib_sa ib_mad ib_core ib_addr iscsi_tcp libiscsi_tcp libiscsi scsi_transport_iscsi bridge stp llc dm_crypt rfcomm bnep bluetooth parport_pc ppdev nfsd nfs_acl nfs fscache lockd sunrpc kvm_intel kvm binfmt_misc psmouse dm_multipath serio_raw microcode scsi_dh dcdbas lpc_ich lp parport hid_generic ghash_clmulni_intel cryptd i915 drm_kms_helper usbhid r8169 hid drm i2c_algo_bit video 50 | [ 171.579347] CPU: 2 PID: 2909 Comm: insmod Tainted: G O 3.10.0 #6 51 | [ 171.579378] Hardware name: Dell Inc. OptiPlex 390/0M5DCD, BIOS A05 02/09/2012 52 | [ 171.579407] task: ffff8800c3e5c560 ti: ffff88002e130000 task.ti: ffff88002e130000 53 | [ 171.579437] RIP: 0010:[<0000000000000000>] [< (null)>] (null) 54 | [ 171.579470] RSP: 0018:ffff88002e131c80 EFLAGS: 00010246 55 | [ 171.579494] RAX: ffff8800bbbb2100 RBX: ffff8800bbbb2100 RCX: 0000000000000000 56 | [ 171.579524] RDX: ffffffffa04fc07a RSI: 0000000000400000 RDI: ffffffffa04fd000 57 | [ 171.579554] RBP: ffff88002e131cc8 R08: ffffffff81cdc0e0 R09: 0000000000000100 58 | [ 171.579573] R10: 00000000000000f8 R11: 0000000000000000 R12: fffffffffffffff4 59 | [ 171.579591] R13: ffffffffa04fd000 R14: 0000000000000000 R15: 0000000000400000 60 | [ 171.579614] FS: 00007f8c0dd97700(0000) GS:ffff88012ec40000(0000) knlGS:0000000000000000 61 | [ 171.579636] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 62 | [ 171.579651] CR2: 0000000000000000 CR3: 00000000b1c68000 CR4: 00000000000407e0 63 | [ 171.579669] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 64 | [ 171.579688] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 65 | [ 171.579706] Stack: 66 | [ 171.579712] ffffffff811707b3 ffff88002e131c98 ffffffff81128ab0 ffff88002e131cc8 67 | [ 171.579733] ffff8800bbbb2100 fffffffffffffff4 ffffffffa04fd000 ffffffffa04fc07a 68 | [ 171.579754] 0000000000400000 ffff88002e131d18 ffffffff81189e74 00000000fffffff0 69 | [ 171.579774] Call Trace: 70 | [ 171.579785] [] ? mount_fs+0x43/0x1b0 71 | [ 171.579801] [] ? __alloc_percpu+0x10/0x20 72 | [ 171.579818] [] vfs_kern_mount+0x74/0x110 73 | [ 171.579834] [] ? npfs_kill_sb+0x10/0x10 [fsmod] 74 | [ 171.579851] [] kern_mount_data+0x19/0x30 75 | [ 171.579866] [] fsmod_init+0x46/0x80 [fsmod] 76 | [ 171.579885] [] do_one_initcall+0x112/0x170 77 | [ 171.579903] [] load_module+0x1bee/0x2570 78 | [ 171.580856] [] ? unset_module_init_ro_nx+0x80/0x80 79 | [ 171.581801] [] SyS_init_module+0xce/0x100 80 | [ 171.582751] [] system_call_fastpath+0x16/0x1b 81 | [ 171.583712] Code: Bad RIP value. 82 | [ 171.584631] RIP [< (null)>] (null) 83 | [ 171.585551] RSP 84 | [ 171.587094] CR2: 0000000000000000 85 | [ 171.597161] ---[ end trace 9f3147bed7f16176 ]--- 86 | 87 | 88 | //diff 89 | fs/super.c; fs/namespace.c;fs/filesystems.c 90 | 91 | --------------------------------------------------------------------------------