seq_file, printk to pr_info, disk persistency

This commit is contained in:
Ciro Santilli
2017-07-13 13:06:25 +01:00
parent 32855c325e
commit 8058ee9f2b
9 changed files with 201 additions and 20 deletions

View File

@@ -123,6 +123,19 @@ We have not managed to track this problem down yet, but the following workaround
This started happening when we switched to building QEMU through Buildroot, and has not been observed on later Ubuntu.
## Filesystem persistency
The root filesystem is persistent across:
./runqemu
./runqemu
However, when you do:
./run
it gets overwritten by a fresh filesystem and you lose all changes.
## Text mode
Show serial output of QEMU directly on the current terminal, without opening a QEMU window:

View File

@@ -9,24 +9,26 @@
1. [panic](panic.c)
1. [params](params.c)
1. [fops](fops.c)
1. [ioctl](ioctl.c)
1. [poll](poll.c)
1. [anonymous_inode](anonymous_inode.c)
1. [ioctl](ioctl.c)
1. [poll](poll.c)
1. [anonymous_inode](anonymous_inode.c)
1. [seq_file](seq_file.c)
1. [seq_file_single](seq_file_inode.c)
1. Asynchronous
1. [workqueue](workqueue.c)
1. [sleep](sleep.c)
1. [kthread](kthread.c)
1. [kthreads](kthreads.c)
1. [schedule](schedule.c)
1. [timer](timer.c)
1. [work_from_work](work_from_work.c)
1. [workqueue](workqueue.c)
1. [sleep](sleep.c)
1. [kthread](kthread.c)
1. [kthreads](kthreads.c)
1. [schedule](schedule.c)
1. [timer](timer.c)
1. [work_from_work](work_from_work.c)
1. [irq](irq.c)
1. Module dependencies
1. [dep](dep.c)
1. [dep2](dep2.c)
1. [dep](dep.c)
1. [dep2](dep2.c)
1. [character_device](character_device.c)
1. Hardware device drivers
1. [pci_min](pci_min.c)
1. [pci](pci.c)
1. [platform_device](platform_device.c)
1. [pci_min](pci_min.c)
1. [pci](pci.c)
1. [platform_device](platform_device.c)
1. [user](user/)

View File

@@ -20,7 +20,7 @@ Here we use debugfs.
#include <asm/uaccess.h> /* copy_from_user, copy_to_user */
#include <linux/debugfs.h>
#include <linux/errno.h> /* EFAULT */
#include <linux/fs.h>
#include <linux/fs.h> /* file_operations */
#include <linux/kernel.h> /* min */
#include <linux/module.h>
#include <linux/printk.h> /* printk */

View File

@@ -15,13 +15,13 @@ MODULE_LICENSE("GPL");
static int myinit(void)
{
printk(KERN_INFO "hello init\n");
pr_info("hello init\n");
return 0;
}
static void myexit(void)
{
printk(KERN_INFO "hello exit\n");
pr_info("hello exit\n");
}
module_init(myinit)

View File

@@ -11,13 +11,13 @@ MODULE_LICENSE("GPL");
static int myinit(void)
{
printk(KERN_INFO "hello2 init\n");
pr_info("hello2 init\n");
return 0;
}
static void myexit(void)
{
printk(KERN_INFO "hello2 exit\n");
pr_info("hello2 exit\n");
}
module_init(myinit)

90
kernel_module/seq_file.c Normal file
View File

@@ -0,0 +1,90 @@
/*
Adapted from: http://allskyee.blogspot.co.uk/2011/12/proc-seqfile-write.html
Writting trivial read fops is repetitive and error prone.
The seq_file API makes the process much easier for those trivial cases.
There is not write version however, as writes are more complex:
https://stackoverflow.com/questions/30710517/how-to-implement-a-writable-proc-file-by-using-seq-file-in-a-driver-module
*/
#include <asm/uaccess.h> /* copy_from_user, copy_to_user */
#include <linux/debugfs.h>
#include <linux/errno.h> /* EFAULT */
#include <linux/fs.h>
#include <linux/module.h>
#include <linux/printk.h> /* pr_info */
#include <linux/seq_file.h> /* seq_read, seq_lseek, single_release */
#include <uapi/linux/stat.h> /* S_IRUSR */
MODULE_LICENSE("GPL");
static struct dentry *debugfs_file;
static void * next(struct seq_file *s, void *v, loff_t *pos)
{
pr_info("next\n");
(*(unsigned long *)v)++;
(*pos)++;
return *pos < 3 ? v : NULL;
}
static void * start(struct seq_file *s, loff_t *pos)
{
static unsigned long counter = 0;
pr_info("start pos = %llx\n", (unsigned long long)*pos);
if (*pos == 0) {
return &counter;
} else {
*pos = 0;
return NULL;
}
}
static int show(struct seq_file *s, void *v)
{
pr_info("show\n");
seq_printf(s, "%lx\n", *(unsigned long *)v);
return 0;
}
static void stop(struct seq_file *s, void *v)
{
pr_info("stop\n");
}
static struct seq_operations my_seq_ops = {
.next = next,
.show = show,
.start = start,
.stop = stop,
};
static int open(struct inode *inode, struct file *file)
{
return seq_open(file, &my_seq_ops);
}
static struct file_operations fops = {
.owner = THIS_MODULE,
.llseek = seq_lseek,
.open = open,
.read = seq_read,
.release = seq_release
};
static int myinit(void)
{
debugfs_file = debugfs_create_file("lkmc_seq_file", S_IRUSR | S_IWUSR, NULL, NULL, &fops);
return 0;
}
static void myexit(void)
{
debugfs_remove(debugfs_file);
}
module_init(myinit)
module_exit(myexit)

View File

@@ -0,0 +1,49 @@
/*
For single reads, single_open is an even more convenient version of seq_file.
*/
#include <asm/uaccess.h> /* copy_from_user, copy_to_user */
#include <linux/debugfs.h>
#include <linux/errno.h> /* EFAULT */
#include <linux/fs.h>
#include <linux/module.h>
#include <linux/printk.h> /* pr_info */
#include <linux/seq_file.h> /* seq_read, seq_lseek, single_release */
#include <uapi/linux/stat.h> /* S_IRUSR */
MODULE_LICENSE("GPL");
static struct dentry *debugfs_file;
static int show(struct seq_file *m, void *v)
{
seq_printf(m, "abcd\n");
return 0;
}
static int open(struct inode *inode, struct file *file)
{
return single_open(file, show, NULL);
}
static const struct file_operations fops = {
.llseek = seq_lseek,
.open = open,
.owner = THIS_MODULE,
.read = seq_read,
.release = single_release,
};
static int myinit(void)
{
debugfs_file = debugfs_create_file("lkmc_seq_file", S_IRUSR | S_IWUSR, NULL, NULL, &fops);
return 0;
}
static void myexit(void)
{
debugfs_remove(debugfs_file);
}
module_init(myinit)
module_exit(myexit)

19
rootfs_overlay/seq_file.sh Executable file
View File

@@ -0,0 +1,19 @@
#!/bin/sh
set -ex
insmod /seq_file.ko
cd /sys/kernel/debug
cat 'lkmc_seq_file'
# => 0
# => 1
# => 2
cat 'lkmc_seq_file'
# => 3
# => 4
# => 5
# TODO understand, why does this print nothing?
dd if='lkmc_seq_file' bs=1 count=2 skip=2

View File

@@ -0,0 +1,8 @@
#!/bin/sh
set -ex
insmod /seq_file_single.ko
cd /sys/kernel/debug
cat 'lkmc_seq_file_single'
# => abcd
dd if='lkmc_seq_file_single' bs=1 skip=2
# => cd