All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/9] Add blockconsole version 1.1 (try 2)
@ 2013-02-28 21:39 Joern Engel
  2013-02-28 21:39 ` [PATCH 1/9] do_mounts: constify name_to_dev_t parameter Joern Engel
                   ` (10 more replies)
  0 siblings, 11 replies; 36+ messages in thread
From: Joern Engel @ 2013-02-28 21:39 UTC (permalink / raw)
  To: linux-kernel; +Cc: Andrew Morton, Borislav Petkov, Jeff Moyer, Joern Engel

Blockconsole is a console driver very roughly similar to netconsole.
Instead of sending messages out via UDP, they are written to a block
device.  Typically a USB stick is chosen, although in principle any
block device will do.

In most cases blockconsole is useful where netconsole is not, i.e.
single machines without network access or without an accessable
netconsole capture server.  When using both blockconsole and
netconsole, I have found netconsole to sometimes create a mess under
high message load (sysrq-t, etc.) while blockconsole does not.

Most importantly, a number of bugs were identified and fixed that
would have been unexplained machine reboots without blockconsole.

More highlights:
* reasonably small and self-contained code,
* some 100+ machine years of runtime,
* nice tutorial with a 30-sec guide for the impatient.

Special thanks to Borislav Petkov for many improvements and kicking my
behind to provide a proper git tree and resend patches.

A number of cleanup patches could be folded into the main patch, but I
decided not to mess with git history and leave any further mistakes
for the world to laugh at:
git://git.kernel.org/pub/scm/linux/kernel/git/joern/bcon2.git

Joern Engel (8):
  do_mounts: constify name_to_dev_t parameter
  add blockconsole version 1.1
  printk: add CON_ALLDATA console flag
  netconsole: use CON_ALLDATA
  blockconsole: use CON_ALLDATA
  bcon: add a release work struct
  bcon: check for hdparm in bcon_tail
  bcon: remove version 1.0 support

Takashi Iwai (1):
  blockconsole: Allow to pass a device file path to bcon_tail

 Documentation/block/blockconsole.txt            |   94 ++++
 Documentation/block/blockconsole/bcon_tail      |   82 +++
 Documentation/block/blockconsole/mkblockconsole |   29 ++
 block/partitions/Makefile                       |    1 +
 block/partitions/blockconsole.c                 |   22 +
 block/partitions/check.c                        |    3 +
 block/partitions/check.h                        |    3 +
 drivers/block/Kconfig                           |    6 +
 drivers/block/Makefile                          |    1 +
 drivers/block/blockconsole.c                    |  617 +++++++++++++++++++++++
 drivers/net/netconsole.c                        |    2 +-
 include/linux/blockconsole.h                    |    7 +
 include/linux/console.h                         |    1 +
 include/linux/mount.h                           |    2 +-
 init/do_mounts.c                                |    2 +-
 kernel/printk.c                                 |    5 +-
 16 files changed, 872 insertions(+), 5 deletions(-)
 create mode 100644 Documentation/block/blockconsole.txt
 create mode 100755 Documentation/block/blockconsole/bcon_tail
 create mode 100755 Documentation/block/blockconsole/mkblockconsole
 create mode 100644 block/partitions/blockconsole.c
 create mode 100644 drivers/block/blockconsole.c
 create mode 100644 include/linux/blockconsole.h

-- 
1.7.10.4


^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH 1/9] do_mounts: constify name_to_dev_t parameter
  2013-02-28 21:39 [PATCH 0/9] Add blockconsole version 1.1 (try 2) Joern Engel
@ 2013-02-28 21:39 ` Joern Engel
  2013-02-28 21:39 ` [PATCH 2/9] add blockconsole version 1.1 Joern Engel
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 36+ messages in thread
From: Joern Engel @ 2013-02-28 21:39 UTC (permalink / raw)
  To: linux-kernel; +Cc: Andrew Morton, Borislav Petkov, Jeff Moyer, Joern Engel

Signed-off-by: Joern Engel <joern@logfs.org>
---
 include/linux/mount.h |    2 +-
 init/do_mounts.c      |    2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/linux/mount.h b/include/linux/mount.h
index d7029f4..6b5fa77 100644
--- a/include/linux/mount.h
+++ b/include/linux/mount.h
@@ -74,6 +74,6 @@ extern struct vfsmount *vfs_kern_mount(struct file_system_type *type,
 extern void mnt_set_expiry(struct vfsmount *mnt, struct list_head *expiry_list);
 extern void mark_mounts_for_expiry(struct list_head *mounts);
 
-extern dev_t name_to_dev_t(char *name);
+extern dev_t name_to_dev_t(const char *name);
 
 #endif /* _LINUX_MOUNT_H */
diff --git a/init/do_mounts.c b/init/do_mounts.c
index 1d1b634..da96f85 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -202,7 +202,7 @@ done:
  *	bangs.
  */
 
-dev_t name_to_dev_t(char *name)
+dev_t name_to_dev_t(const char *name)
 {
 	char s[32];
 	char *p;
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 2/9] add blockconsole version 1.1
  2013-02-28 21:39 [PATCH 0/9] Add blockconsole version 1.1 (try 2) Joern Engel
  2013-02-28 21:39 ` [PATCH 1/9] do_mounts: constify name_to_dev_t parameter Joern Engel
@ 2013-02-28 21:39 ` Joern Engel
  2013-02-28 21:39 ` [PATCH 3/9] printk: add CON_ALLDATA console flag Joern Engel
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 36+ messages in thread
From: Joern Engel @ 2013-02-28 21:39 UTC (permalink / raw)
  To: linux-kernel
  Cc: Andrew Morton, Borislav Petkov, Jeff Moyer, Joern Engel,
	Steve Hodgson, Borislav Petkov

Console driver similar to netconsole, except it writes to a block
device.  Can be useful in a setup where netconsole, for whatever
reasons, is impractical.

Changes since version 1.0:
- Header format overhaul, addressing several annoyances when actually
  using blockconsole for production.
- Steve Hodgson added a panic notifier.
- Added improvements and cleanups from Borislav Petkov.

Signed-off-by: Steve Hodgson <steve@purestorage.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
Signed-off-by: Joern Engel <joern@logfs.org>
---
 Documentation/block/blockconsole.txt            |   94 ++++
 Documentation/block/blockconsole/bcon_tail      |   62 +++
 Documentation/block/blockconsole/mkblockconsole |   29 ++
 block/partitions/Makefile                       |    1 +
 block/partitions/blockconsole.c                 |   22 +
 block/partitions/check.c                        |    3 +
 block/partitions/check.h                        |    3 +
 drivers/block/Kconfig                           |    6 +
 drivers/block/Makefile                          |    1 +
 drivers/block/blockconsole.c                    |  621 +++++++++++++++++++++++
 include/linux/blockconsole.h                    |    7 +
 11 files changed, 849 insertions(+)
 create mode 100644 Documentation/block/blockconsole.txt
 create mode 100755 Documentation/block/blockconsole/bcon_tail
 create mode 100755 Documentation/block/blockconsole/mkblockconsole
 create mode 100644 block/partitions/blockconsole.c
 create mode 100644 drivers/block/blockconsole.c
 create mode 100644 include/linux/blockconsole.h

diff --git a/Documentation/block/blockconsole.txt b/Documentation/block/blockconsole.txt
new file mode 100644
index 0000000..2b45516
--- /dev/null
+++ b/Documentation/block/blockconsole.txt
@@ -0,0 +1,94 @@
+started by Jörn Engel <joern@logfs.org> 2012.03.17
+
+Blocksonsole for the impatient
+==============================
+
+1. Find an unused USB stick and prepare it for blockconsole by writing
+   the blockconsole signature to it:
+   $ ./mkblockconsole /dev/<usb_stick>
+
+2. USB stick is ready for use, replug it so that the kernel can start
+   logging to it.
+
+3. After you've done logging, read out the logs from it like this:
+   $ ./bcon_tail
+
+   This creates a file called /var/log/bcon.<UUID> which contains the
+   last 16M of the logs.  Open it with a sane editor like vim which
+   can display zeroed gaps as a single line and start staring at the
+   logs.
+   For the really impatient, use:
+   $ vi `./bcon_tail`
+
+Introduction:
+=============
+
+This module logs kernel printk messages to block devices, e.g. usb
+sticks.  It allows after-the-fact debugging when the main
+disk/filesystem fails and serial consoles and netconsole are
+impractical.
+
+It can currently only be used built-in.  Blockconsole hooks into the
+partition scanning code and will bring up configured block devices as
+soon as possible.  While this doesn't allow capture of early kernel
+panics, it does capture most of the boot process.
+
+Block device configuration:
+==================================
+
+Blockconsole has no configuration parameter.  In order to use a block
+device for logging, the blockconsole header has to be written to the
+device in question.  Logging to partitions is not supported.
+
+The example program mkblockconsole can be used to generate such a
+header on a device.
+
+Header format:
+==============
+
+A legal header looks like this:
+
+Linux blockconsole version 1.1
+818cf322
+00000000
+00000000
+
+It consists of a newline, the "Linux blockconsole version 1.1" string
+plus three numbers on separate lines each.  Numbers are all 32bit,
+represented as 8-byte hex strings, with letters in lowercase.  The
+first number is a uuid for this particular console device.  Just pick
+a random number when generating the device.  The second number is a
+wrap counter and unlikely to ever increment.  The third is a tile
+counter, with a tile being one megabyte in size.
+
+Miscellaneous notes:
+====================
+
+Blockconsole will write a new header for every tile or once every
+megabyte.  The header starts with a newline in order to ensure the
+"Linux blockconsole...' string always ends up at the beginning of a
+line if you read the blockconsole in a text editor.
+
+The blockconsole header is constructed such that opening the log
+device in a text editor, ignoring memory constraints due to large
+devices, should just work and be reasonably non-confusing to readers.
+However, the example program bcon_tail can be used to copy the last 16
+tiles of the log device to /var/log/bcon.<uuid>, which should be much
+easier to handle.
+
+The wrap counter is used by blockconsole to determine where to
+continue logging after a reboot.  New logs will be written to the
+first tile that wasn't written to by the last instance of
+blockconsole.  Similarly bcon_tail is doing a binary search to find
+the end of the log.
+
+Writing to the log device is strictly circular.  This should give
+optimal performance and reliability on cheap devices, like usb sticks.
+
+Writing to block devices has to happen in sector granularity, while
+kernel logging happens in byte granularity.  In order not to lose
+messages in important cases like kernel crashes, a timer will write
+out partial sectors if no new messages appear for a while.  The
+unwritten part of the sector will be filled with spaces and a single
+newline.  In a quiet system, these empty lines can make up the bulk of
+the log.
diff --git a/Documentation/block/blockconsole/bcon_tail b/Documentation/block/blockconsole/bcon_tail
new file mode 100755
index 0000000..b4bd660
--- /dev/null
+++ b/Documentation/block/blockconsole/bcon_tail
@@ -0,0 +1,62 @@
+#!/bin/bash
+
+TAIL_LEN=16
+TEMPLATE=/tmp/bcon_template
+BUF=/tmp/bcon_buf
+
+if [ $(whoami) != "root" ]; then
+	echo "You need to be root to run this."
+	exit 1
+fi
+
+if [ -z "$(which lsscsi)" ]; then
+	echo "You need to install the lsscsi package on your distro."
+	exit 1
+fi
+
+end_of_log() {
+	DEV=$1
+	UUID=`head -c40 $DEV|tail -c8`
+	LOGFILE=/var/log/bcon.$UUID
+	SECTORS=`hdparm -g $DEV|grep sectors|sed 's/.*sectors = \([0-9]*\).*/\1/'`
+	#MSIZE=`expr $SECTORS / 2048`
+	dd if=$DEV iflag=direct bs=512 2>/dev/null|head -c50 > $TEMPLATE
+	#START, MIDDLE and END are in sectors
+	START=0
+	MIDDLE=$SECTORS
+	END=$SECTORS
+	while true; do
+		MIDDLE=`expr \( \( $END + $START \) / 4096 \) \* 2048`
+		if [ $MIDDLE -eq $START ]; then
+			break
+		fi
+		dd if=$DEV iflag=direct bs=512 count=1 skip=$MIDDLE 2>/dev/null|head -c50 > $BUF
+		if diff -q $BUF $TEMPLATE > /dev/null; then
+			START=$MIDDLE
+		else
+			END=$MIDDLE
+		fi
+	done
+	#switch to megabytes
+	END=`expr $END / 2048`
+	START=`expr $START / 2048`
+	if [ $START -lt $TAIL_LEN ]; then
+		START=0
+	else
+		START=`expr $START - $TAIL_LEN + 1`
+	fi
+	LEN=`expr $END - $START`
+	dd if=$DEV iflag=direct bs=1M count=$LEN skip=$START >$LOGFILE 2>/dev/null
+	echo $LOGFILE
+}
+
+# HEADER contains a newline, so the funny quoting is necessary
+HEADER='
+Linux blockconsole version 1.1'
+CANDIDATES=`lsscsi |sed 's|.*/dev|/dev|'`
+
+for DEV in $CANDIDATES; do
+	if [ "`head -c32 $DEV`" == "$HEADER" ]; then
+		end_of_log $DEV
+	fi
+done
diff --git a/Documentation/block/blockconsole/mkblockconsole b/Documentation/block/blockconsole/mkblockconsole
new file mode 100755
index 0000000..c48f995
--- /dev/null
+++ b/Documentation/block/blockconsole/mkblockconsole
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+# handle the case when using files for logging instead of
+# real devices (with kvm, for example)
+DD_OPTS="conv=notrunc"
+
+if [ ! $# -eq 1 ]; then
+	echo "Usage: $0 <dev>"
+	exit 1
+elif mount|fgrep -q $1; then
+	echo Device appears to be mounted - aborting
+	exit 1
+else
+	dd if=/dev/zero of=$1 bs=1M count=1 $DD_OPTS
+	# The funky formatting is actually needed!
+	UUID=`head -c4 /dev/urandom |hexdump -e '/4 "%08x"'`
+	echo > /tmp/$UUID
+	echo 'Linux blockconsole version 1.1' >> /tmp/$UUID
+	echo "$UUID" >> /tmp/$UUID
+	echo 00000000 >> /tmp/$UUID
+	echo 00000000 >> /tmp/$UUID
+	for i in `seq 452`; do echo -n " " >> /tmp/$UUID; done
+	echo >> /tmp/$UUID
+
+	dd if=/tmp/$UUID of=$1 $DD_OPTS
+	rm /tmp/$UUID
+	sync
+	exit 0
+fi
diff --git a/block/partitions/Makefile b/block/partitions/Makefile
index 03af8ea..bf26d4a 100644
--- a/block/partitions/Makefile
+++ b/block/partitions/Makefile
@@ -18,3 +18,4 @@ obj-$(CONFIG_IBM_PARTITION) += ibm.o
 obj-$(CONFIG_EFI_PARTITION) += efi.o
 obj-$(CONFIG_KARMA_PARTITION) += karma.o
 obj-$(CONFIG_SYSV68_PARTITION) += sysv68.o
+obj-$(CONFIG_BLOCKCONSOLE) += blockconsole.o
diff --git a/block/partitions/blockconsole.c b/block/partitions/blockconsole.c
new file mode 100644
index 0000000..79796a8
--- /dev/null
+++ b/block/partitions/blockconsole.c
@@ -0,0 +1,22 @@
+#include <linux/blockconsole.h>
+
+#include "check.h"
+
+int blockconsole_partition(struct parsed_partitions *state)
+{
+	Sector sect;
+	void *data;
+	int err = 0;
+
+	data = read_part_sector(state, 0, &sect);
+	if (!data)
+		return -EIO;
+	if (!bcon_magic_present(data))
+		goto out;
+
+	bcon_add(state->name);
+	err = 1;
+out:
+	put_dev_sector(sect);
+	return err;
+}
diff --git a/block/partitions/check.c b/block/partitions/check.c
index bc90867..c3e325b 100644
--- a/block/partitions/check.c
+++ b/block/partitions/check.c
@@ -41,6 +41,9 @@ static int (*check_part[])(struct parsed_partitions *) = {
 	 * Probe partition formats with tables at disk address 0
 	 * that also have an ADFS boot block at 0xdc0.
 	 */
+#ifdef CONFIG_BLOCKCONSOLE
+	blockconsole_partition,
+#endif
 #ifdef CONFIG_ACORN_PARTITION_ICS
 	adfspart_check_ICS,
 #endif
diff --git a/block/partitions/check.h b/block/partitions/check.h
index 52b1003..064bf6f 100644
--- a/block/partitions/check.h
+++ b/block/partitions/check.h
@@ -50,3 +50,6 @@ put_partition(struct parsed_partitions *p, int n, sector_t from, sector_t size)
 
 extern int warn_no_part;
 
+#ifdef CONFIG_BLOCKCONSOLE
+int blockconsole_partition(struct parsed_partitions *state);
+#endif
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index 824e09c..06eb42f 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -544,4 +544,10 @@ config BLK_DEV_RBD
 
 	  If unsure, say N.
 
+config BLOCKCONSOLE
+	bool "Block device console logging support"
+	help
+	  This enables logging to block devices.
+	  See <file:Documentation/block/blockconsole.txt> for details.
+
 endif # BLK_DEV
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index 17e82df..99c5c2e 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -40,5 +40,6 @@ obj-$(CONFIG_XEN_BLKDEV_BACKEND)	+= xen-blkback/
 obj-$(CONFIG_BLK_DEV_DRBD)     += drbd/
 obj-$(CONFIG_BLK_DEV_RBD)     += rbd.o
 obj-$(CONFIG_BLK_DEV_PCIESSD_MTIP32XX)	+= mtip32xx/
+obj-$(CONFIG_BLOCKCONSOLE)	+= blockconsole.o
 
 swim_mod-y	:= swim.o swim_asm.o
diff --git a/drivers/block/blockconsole.c b/drivers/block/blockconsole.c
new file mode 100644
index 0000000..7f8ac5b
--- /dev/null
+++ b/drivers/block/blockconsole.c
@@ -0,0 +1,621 @@
+/*
+ * Blockconsole - write kernel console to a block device
+ *
+ * Copyright (C) 2012  Joern Engel <joern@logfs.org>
+ */
+#include <linux/bio.h>
+#include <linux/blockconsole.h>
+#include <linux/console.h>
+#include <linux/fs.h>
+#include <linux/kref.h>
+#include <linux/kthread.h>
+#include <linux/mm.h>
+#include <linux/mount.h>
+#include <linux/random.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/workqueue.h>
+#include <linux/sched.h>
+#include <linux/ctype.h>
+
+#define BLOCKCONSOLE_MAGIC_OLD	"\nLinux blockconsole version 1.0\n"
+#define BLOCKCONSOLE_MAGIC	"\nLinux blockconsole version 1.1\n"
+#define BCON_UUID_OFS		(32)
+#define BCON_ROUND_OFS		(41)
+#define BCON_TILE_OFS		(50)
+#define BCON_HEADERSIZE		(50)
+#define BCON_LONG_HEADERSIZE	(59) /* with tile index */
+
+#define PAGE_COUNT		(256)
+#define SECTOR_COUNT		(PAGE_COUNT * (PAGE_SIZE >> 9))
+#define CACHE_PAGE_MASK		(PAGE_COUNT - 1)
+#define CACHE_SECTOR_MASK	(SECTOR_COUNT - 1)
+#define CACHE_SIZE		(PAGE_COUNT << PAGE_SHIFT)
+#define CACHE_MASK		(CACHE_SIZE - 1)
+#define SECTOR_SHIFT		(9)
+#define SECTOR_SIZE		(1 << SECTOR_SHIFT)
+#define SECTOR_MASK		(~(SECTOR_SIZE-1))
+#define PG_SECTOR_MASK		((PAGE_SIZE >> 9) - 1)
+
+#undef pr_fmt
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+struct bcon_bio {
+	struct bio bio;
+	struct bio_vec bvec;
+	void *sector;
+	int in_flight;
+};
+
+struct blockconsole {
+	char devname[32];
+	spinlock_t end_io_lock;
+	struct timer_list pad_timer;
+	int error_count;
+	struct kref kref;
+	u64 console_bytes;
+	u64 write_bytes;
+	u64 max_bytes;
+	u32 round;
+	u32 uuid;
+	struct bcon_bio bio_array[SECTOR_COUNT];
+	struct page *pages;
+	struct bcon_bio zero_bios[PAGE_COUNT];
+	struct page *zero_page;
+	struct block_device *bdev;
+	struct console console;
+	struct work_struct unregister_work;
+	struct task_struct *writeback_thread;
+	struct notifier_block panic_block;
+};
+
+static void bcon_get(struct blockconsole *bc)
+{
+	kref_get(&bc->kref);
+}
+
+static void bcon_release(struct kref *kref)
+{
+	struct blockconsole *bc = container_of(kref, struct blockconsole, kref);
+
+	__free_pages(bc->zero_page, 0);
+	__free_pages(bc->pages, 8);
+	invalidate_mapping_pages(bc->bdev->bd_inode->i_mapping, 0, -1);
+	blkdev_put(bc->bdev, FMODE_READ|FMODE_WRITE);
+	kfree(bc);
+}
+
+static void bcon_put(struct blockconsole *bc)
+{
+	kref_put(&bc->kref, bcon_release);
+}
+
+static int __bcon_console_ofs(u64 console_bytes)
+{
+	return console_bytes & ~SECTOR_MASK;
+}
+
+static int bcon_console_ofs(struct blockconsole *bc)
+{
+	return __bcon_console_ofs(bc->console_bytes);
+}
+
+static int __bcon_console_sector(u64 console_bytes)
+{
+	return (console_bytes >> SECTOR_SHIFT) & CACHE_SECTOR_MASK;
+}
+
+static int bcon_console_sector(struct blockconsole *bc)
+{
+	return __bcon_console_sector(bc->console_bytes);
+}
+
+static int bcon_write_sector(struct blockconsole *bc)
+{
+	return (bc->write_bytes >> SECTOR_SHIFT) & CACHE_SECTOR_MASK;
+}
+
+static void clear_sector(void *sector)
+{
+	memset(sector, ' ', 511);
+	memset(sector + 511, 10, 1);
+}
+
+static void bcon_init_first_page(struct blockconsole *bc)
+{
+	char *buf = page_address(bc->pages);
+	size_t len = strlen(BLOCKCONSOLE_MAGIC);
+	u32 tile = bc->console_bytes >> 20; /* We overflow after 4TB - fine */
+
+	clear_sector(buf);
+	memcpy(buf, BLOCKCONSOLE_MAGIC, len);
+	sprintf(buf + BCON_UUID_OFS, "%08x", bc->uuid);
+	sprintf(buf + BCON_ROUND_OFS, "%08x", bc->round);
+	sprintf(buf + BCON_TILE_OFS, "%08x", tile);
+	/* replace NUL with newline */
+	buf[BCON_UUID_OFS + 8] = 10;
+	buf[BCON_ROUND_OFS + 8] = 10;
+	buf[BCON_TILE_OFS + 8] = 10;
+}
+
+static void bcon_advance_console_bytes(struct blockconsole *bc, int bytes)
+{
+	u64 old, new;
+
+	do {
+		old = bc->console_bytes;
+		new = old + bytes;
+		if (new >= bc->max_bytes)
+			new = 0;
+		if ((new & CACHE_MASK) == 0) {
+			bcon_init_first_page(bc);
+			new += BCON_LONG_HEADERSIZE;
+		}
+	} while (cmpxchg64(&bc->console_bytes, old, new) != old);
+}
+
+static void request_complete(struct bio *bio, int err)
+{
+	complete((struct completion *)bio->bi_private);
+}
+
+static int sync_read(struct blockconsole *bc, u64 ofs)
+{
+	struct bio bio;
+	struct bio_vec bio_vec;
+	struct completion complete;
+
+	bio_init(&bio);
+	bio.bi_io_vec = &bio_vec;
+	bio_vec.bv_page = bc->pages;
+	bio_vec.bv_len = SECTOR_SIZE;
+	bio_vec.bv_offset = 0;
+	bio.bi_vcnt = 1;
+	bio.bi_idx = 0;
+	bio.bi_size = SECTOR_SIZE;
+	bio.bi_bdev = bc->bdev;
+	bio.bi_sector = ofs >> SECTOR_SHIFT;
+	init_completion(&complete);
+	bio.bi_private = &complete;
+	bio.bi_end_io = request_complete;
+
+	submit_bio(READ, &bio);
+	wait_for_completion(&complete);
+	return test_bit(BIO_UPTODATE, &bio.bi_flags) ? 0 : -EIO;
+}
+
+static void bcon_erase_segment(struct blockconsole *bc)
+{
+	int i;
+
+	for (i = 0; i < PAGE_COUNT; i++) {
+		struct bcon_bio *bcon_bio = bc->zero_bios + i;
+		struct bio *bio = &bcon_bio->bio;
+
+		/*
+		 * If the last erase hasn't finished yet, just skip it.  The log
+		 * will look messy, but that's all.
+		 */
+		rmb();
+		if (bcon_bio->in_flight)
+			continue;
+		bio_init(bio);
+		bio->bi_io_vec = &bcon_bio->bvec;
+		bio->bi_vcnt = 1;
+		bio->bi_size = PAGE_SIZE;
+		bio->bi_bdev = bc->bdev;
+		bio->bi_private = bc;
+		bio->bi_idx = 0;
+		bio->bi_sector = (bc->write_bytes + i * PAGE_SIZE) >> 9;
+		bcon_bio->in_flight = 1;
+		wmb();
+		/* We want the erase to go to the device first somehow */
+		submit_bio(WRITE | REQ_SOFTBARRIER, bio);
+	}
+}
+
+static void bcon_advance_write_bytes(struct blockconsole *bc, int bytes)
+{
+	bc->write_bytes += bytes;
+	if (bc->write_bytes >= bc->max_bytes) {
+		bc->write_bytes = 0;
+		bcon_init_first_page(bc);
+		bc->round++;
+	}
+}
+
+static int bcon_convert_old_format(struct blockconsole *bc)
+{
+	bc->uuid = get_random_int();
+	bc->round = 0;
+	bc->console_bytes = bc->write_bytes = 0;
+	bcon_advance_console_bytes(bc, 0); /* To skip the header */
+	bcon_advance_write_bytes(bc, 0); /* To wrap around, if necessary */
+	bcon_erase_segment(bc);
+	pr_info("converted %s from old format\n", bc->devname);
+	return 0;
+}
+
+static int bcon_find_end_of_log(struct blockconsole *bc)
+{
+	u64 start = 0, end = bc->max_bytes, middle;
+	void *sec0 = bc->bio_array[0].sector;
+	void *sec1 = bc->bio_array[1].sector;
+	int err, version;
+
+	err = sync_read(bc, 0);
+	if (err)
+		return err;
+	/* Second sanity check, out of sheer paranoia */
+	version = bcon_magic_present(sec0);
+	if (version == 10)
+		return bcon_convert_old_format(bc);
+
+	bc->uuid = simple_strtoull(sec0 + BCON_UUID_OFS, NULL, 16);
+	bc->round = simple_strtoull(sec0 + BCON_ROUND_OFS, NULL, 16);
+
+	memcpy(sec1, sec0, BCON_HEADERSIZE);
+	for (;;) {
+		middle = (start + end) / 2;
+		middle &= ~CACHE_MASK;
+		if (middle == start)
+			break;
+		err = sync_read(bc, middle);
+		if (err)
+			return err;
+		if (memcmp(sec1, sec0, BCON_HEADERSIZE)) {
+			/* If the two differ, we haven't written that far yet */
+			end = middle;
+		} else {
+			start = middle;
+		}
+	}
+	bc->console_bytes = bc->write_bytes = end;
+	bcon_advance_console_bytes(bc, 0); /* To skip the header */
+	bcon_advance_write_bytes(bc, 0); /* To wrap around, if necessary */
+	bcon_erase_segment(bc);
+	return 0;
+}
+
+static void bcon_unregister(struct work_struct *work)
+{
+	struct blockconsole *bc = container_of(work, struct blockconsole,
+			unregister_work);
+
+	atomic_notifier_chain_unregister(&panic_notifier_list, &bc->panic_block);
+	unregister_console(&bc->console);
+	del_timer_sync(&bc->pad_timer);
+	kthread_stop(bc->writeback_thread);
+	/* No new io will be scheduled anymore now */
+	bcon_put(bc);
+}
+
+#define BCON_MAX_ERRORS	10
+static void bcon_end_io(struct bio *bio, int err)
+{
+	struct bcon_bio *bcon_bio = container_of(bio, struct bcon_bio, bio);
+	struct blockconsole *bc = bio->bi_private;
+	unsigned long flags;
+
+	/*
+	 * We want to assume the device broken and free this console if
+	 * we accumulate too many errors.  But if errors are transient,
+	 * we also want to forget about them once writes succeed again.
+	 * Oh, and we only want to reset the counter if it hasn't reached
+	 * the limit yet, so we don't bcon_put() twice from here.
+	 */
+	spin_lock_irqsave(&bc->end_io_lock, flags);
+	if (err) {
+		if (bc->error_count++ == BCON_MAX_ERRORS) {
+			pr_info("no longer logging to %s\n", bc->devname);
+			schedule_work(&bc->unregister_work);
+		}
+	} else {
+		if (bc->error_count && bc->error_count < BCON_MAX_ERRORS)
+			bc->error_count = 0;
+	}
+	/*
+	 * Add padding (a bunch of spaces and a newline) early so bcon_pad
+	 * only has to advance a pointer.
+	 */
+	clear_sector(bcon_bio->sector);
+	bcon_bio->in_flight = 0;
+	spin_unlock_irqrestore(&bc->end_io_lock, flags);
+	bcon_put(bc);
+}
+
+static void bcon_writesector(struct blockconsole *bc, int index)
+{
+	struct bcon_bio *bcon_bio = bc->bio_array + index;
+	struct bio *bio = &bcon_bio->bio;
+
+	rmb();
+	if (bcon_bio->in_flight)
+		return;
+	bcon_get(bc);
+
+	bio_init(bio);
+	bio->bi_io_vec = &bcon_bio->bvec;
+	bio->bi_vcnt = 1;
+	bio->bi_size = SECTOR_SIZE;
+	bio->bi_bdev = bc->bdev;
+	bio->bi_private = bc;
+	bio->bi_end_io = bcon_end_io;
+
+	bio->bi_idx = 0;
+	bio->bi_sector = bc->write_bytes >> 9;
+	bcon_bio->in_flight = 1;
+	wmb();
+	submit_bio(WRITE, bio);
+}
+
+static int bcon_writeback(void *_bc)
+{
+	struct blockconsole *bc = _bc;
+	struct sched_param(sp);
+
+	sp.sched_priority = MAX_RT_PRIO - 1; /* Highest realtime prio */
+	sched_setscheduler_nocheck(current, SCHED_FIFO, &sp);
+	for (;;) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule();
+		if (kthread_should_stop())
+			break;
+		while (bcon_write_sector(bc) != bcon_console_sector(bc)) {
+			bcon_writesector(bc, bcon_write_sector(bc));
+			bcon_advance_write_bytes(bc, SECTOR_SIZE);
+			if (bcon_write_sector(bc) == 0)
+				bcon_erase_segment(bc);
+		}
+	}
+	return 0;
+}
+
+static void bcon_pad(unsigned long data)
+{
+	struct blockconsole *bc = (void *)data;
+	unsigned int n;
+
+	/*
+	 * We deliberately race against bcon_write here.  If we lose the race,
+	 * our padding is no longer where we expected it to be, i.e. it is
+	 * no longer a bunch of spaces with a newline at the end.  There could
+	 * not be a newline at all or it could be somewhere in the middle.
+	 * Either way, the log corruption is fairly obvious to spot and ignore
+	 * for human readers.
+	 */
+	n = SECTOR_SIZE - bcon_console_ofs(bc);
+	if (n != SECTOR_SIZE) {
+		bcon_advance_console_bytes(bc, n);
+		wake_up_process(bc->writeback_thread);
+	}
+}
+
+static void bcon_write(struct console *console, const char *msg,
+		unsigned int len)
+{
+	struct blockconsole *bc = container_of(console, struct blockconsole,
+			console);
+	unsigned int n;
+	u64 console_bytes;
+	int i;
+
+	while (len) {
+		console_bytes = bc->console_bytes;
+		i = __bcon_console_sector(console_bytes);
+		rmb();
+		if (bc->bio_array[i].in_flight)
+			break;
+		n = min_t(int, len, SECTOR_SIZE -
+				__bcon_console_ofs(console_bytes));
+		memcpy(bc->bio_array[i].sector +
+				__bcon_console_ofs(console_bytes), msg, n);
+		len -= n;
+		msg += n;
+		bcon_advance_console_bytes(bc, n);
+	}
+	wake_up_process(bc->writeback_thread);
+	mod_timer(&bc->pad_timer, jiffies + HZ);
+}
+
+static void bcon_init_bios(struct blockconsole *bc)
+{
+	int i;
+
+	for (i = 0; i < SECTOR_COUNT; i++) {
+		int page_index = i >> (PAGE_SHIFT - SECTOR_SHIFT);
+		struct page *page = bc->pages + page_index;
+		struct bcon_bio *bcon_bio = bc->bio_array + i;
+		struct bio_vec *bvec = &bcon_bio->bvec;
+
+		bcon_bio->in_flight = 0;
+		bcon_bio->sector = page_address(bc->pages + page_index)
+			+ SECTOR_SIZE * (i & PG_SECTOR_MASK);
+		clear_sector(bcon_bio->sector);
+		bvec->bv_page = page;
+		bvec->bv_len = SECTOR_SIZE;
+		bvec->bv_offset = SECTOR_SIZE * (i & PG_SECTOR_MASK);
+	}
+}
+
+static void bcon_init_zero_bio(struct blockconsole *bc)
+{
+	int i;
+
+	memset(page_address(bc->zero_page), 0, PAGE_SIZE);
+	for (i = 0; i < PAGE_COUNT; i++) {
+		struct bcon_bio *bcon_bio = bc->zero_bios + i;
+		struct bio_vec *bvec = &bcon_bio->bvec;
+
+		bcon_bio->in_flight = 0;
+		bvec->bv_page = bc->zero_page;
+		bvec->bv_len = PAGE_SIZE;
+		bvec->bv_offset = 0;
+	}
+}
+
+static int blockconsole_panic(struct notifier_block *this, unsigned long event,
+		void *ptr)
+{
+	struct blockconsole *bc = container_of(this, struct blockconsole,
+			panic_block);
+	unsigned int n;
+
+	n = SECTOR_SIZE - bcon_console_ofs(bc);
+	if (n != SECTOR_SIZE)
+		bcon_advance_console_bytes(bc, n);
+	bcon_writeback(bc);
+	return NOTIFY_DONE;
+}
+
+static int bcon_create(const char *devname)
+{
+	const fmode_t mode = FMODE_READ | FMODE_WRITE;
+	struct blockconsole *bc;
+	int err;
+
+	bc = kzalloc(sizeof(*bc), GFP_KERNEL);
+	if (!bc)
+		return -ENOMEM;
+	memset(bc->devname, ' ', sizeof(bc->devname));
+	strlcpy(bc->devname, devname, sizeof(bc->devname));
+	spin_lock_init(&bc->end_io_lock);
+	strcpy(bc->console.name, "bcon");
+	bc->console.flags = CON_PRINTBUFFER | CON_ENABLED;
+	bc->console.write = bcon_write;
+	bc->bdev = blkdev_get_by_path(devname, mode, NULL);
+#ifndef MODULE
+	if (IS_ERR(bc->bdev)) {
+		dev_t devt = name_to_dev_t(devname);
+		if (devt)
+			bc->bdev = blkdev_get_by_dev(devt, mode, NULL);
+	}
+#endif
+	if (IS_ERR(bc->bdev))
+		goto out;
+	bc->pages = alloc_pages(GFP_KERNEL, 8);
+	if (!bc->pages)
+		goto out;
+	bc->zero_page = alloc_pages(GFP_KERNEL, 0);
+	if (!bc->zero_page)
+		goto out1;
+	bcon_init_bios(bc);
+	bcon_init_zero_bio(bc);
+	setup_timer(&bc->pad_timer, bcon_pad, (unsigned long)bc);
+	bc->max_bytes = bc->bdev->bd_inode->i_size & ~CACHE_MASK;
+	err = bcon_find_end_of_log(bc);
+	if (err)
+		goto out2;
+	kref_init(&bc->kref); /* This reference gets freed on errors */
+	bc->writeback_thread = kthread_run(bcon_writeback, bc, "bcon_%s",
+			devname);
+	if (IS_ERR(bc->writeback_thread))
+		goto out2;
+	INIT_WORK(&bc->unregister_work, bcon_unregister);
+	register_console(&bc->console);
+	bc->panic_block.notifier_call = blockconsole_panic;
+	bc->panic_block.priority = INT_MAX;
+	atomic_notifier_chain_register(&panic_notifier_list, &bc->panic_block);
+	pr_info("now logging to %s at %llx\n", devname, bc->console_bytes >> 20);
+
+	return 0;
+
+out2:
+	__free_pages(bc->zero_page, 0);
+out1:
+	__free_pages(bc->pages, 8);
+out:
+	kfree(bc);
+	/* Not strictly correct, be the caller doesn't care */
+	return -ENOMEM;
+}
+
+static void bcon_create_fuzzy(const char *name)
+{
+	char *longname;
+	int err;
+
+	err = bcon_create(name);
+	if (err) {
+		longname = kzalloc(strlen(name) + 6, GFP_KERNEL);
+		if (!longname)
+			return;
+		strcpy(longname, "/dev/");
+		strcat(longname, name);
+		bcon_create(longname);
+		kfree(longname);
+	}
+}
+
+static DEFINE_SPINLOCK(device_lock);
+static char scanned_devices[80];
+
+static void bcon_do_add(struct work_struct *work)
+{
+	char local_devices[80], *name, *remainder = local_devices;
+
+	spin_lock(&device_lock);
+	memcpy(local_devices, scanned_devices, sizeof(local_devices));
+	memset(scanned_devices, 0, sizeof(scanned_devices));
+	spin_unlock(&device_lock);
+
+	while (remainder && remainder[0]) {
+		name = strsep(&remainder, ",");
+		bcon_create_fuzzy(name);
+	}
+}
+
+DECLARE_WORK(bcon_add_work, bcon_do_add);
+
+void bcon_add(const char *name)
+{
+	/*
+	 * We add each name to a small static buffer and ask for a workqueue
+	 * to go pick it up asap.  Once it is picked up, the buffer is empty
+	 * again, so hopefully it will suffice for all sane users.
+	 */
+	spin_lock(&device_lock);
+	if (scanned_devices[0])
+		strncat(scanned_devices, ",", sizeof(scanned_devices));
+	strncat(scanned_devices, name, sizeof(scanned_devices));
+	spin_unlock(&device_lock);
+	schedule_work(&bcon_add_work);
+}
+
+/*
+ * Check if we have an 8-digit hex number followed by newline
+ */
+static bool is_four_byte_hex(const void *data)
+{
+	const char *str = data;
+	int len = 0;
+
+	while (isxdigit(*str) && len++ < 9)
+		str++;
+
+	if (len != 8)
+		return false;
+
+	/* str should point to a \n now */
+	if (*str != 0xa)
+		return false;
+
+	return true;
+}
+
+int bcon_magic_present(const void *data)
+{
+	size_t len = strlen(BLOCKCONSOLE_MAGIC);
+
+	if (!memcmp(data, BLOCKCONSOLE_MAGIC_OLD, len))
+		return 10;
+	if (memcmp(data, BLOCKCONSOLE_MAGIC, len))
+		return 0;
+	if (!is_four_byte_hex(data + BCON_UUID_OFS))
+		return 0;
+	if (!is_four_byte_hex(data + BCON_ROUND_OFS))
+		return 0;
+	if (!is_four_byte_hex(data + BCON_TILE_OFS))
+		return 0;
+	return 11;
+}
diff --git a/include/linux/blockconsole.h b/include/linux/blockconsole.h
new file mode 100644
index 0000000..114f7c5
--- /dev/null
+++ b/include/linux/blockconsole.h
@@ -0,0 +1,7 @@
+#ifndef LINUX_BLOCKCONSOLE_H
+#define LINUX_BLOCKCONSOLE_H
+
+int bcon_magic_present(const void *data);
+void bcon_add(const char *name);
+
+#endif
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 3/9] printk: add CON_ALLDATA console flag
  2013-02-28 21:39 [PATCH 0/9] Add blockconsole version 1.1 (try 2) Joern Engel
  2013-02-28 21:39 ` [PATCH 1/9] do_mounts: constify name_to_dev_t parameter Joern Engel
  2013-02-28 21:39 ` [PATCH 2/9] add blockconsole version 1.1 Joern Engel
@ 2013-02-28 21:39 ` Joern Engel
  2013-03-01 14:52   ` Jeff Moyer
  2013-02-28 21:39 ` [PATCH 4/9] netconsole: use CON_ALLDATA Joern Engel
                   ` (7 subsequent siblings)
  10 siblings, 1 reply; 36+ messages in thread
From: Joern Engel @ 2013-02-28 21:39 UTC (permalink / raw)
  To: linux-kernel; +Cc: Andrew Morton, Borislav Petkov, Jeff Moyer, Joern Engel

For consoles like netconsole and blockconsole the loglevel filtering
really doesn't make any sense.  If a line gets printed at all, please
send it down to that console, no questions asked.

For vga_con, it is a completely different matter, as the user sitting in
front of his console could get spammed by messages while trying to login
or similar.  So ignore_loglevel doesn't work as a one-size-fits-all
approach.  Add a per-console flag instead so that netconsole and
blockconsole can opt-in.

Signed-off-by: Joern Engel <joern@logfs.org>
---
 include/linux/console.h |    1 +
 kernel/printk.c         |    5 +++--
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/include/linux/console.h b/include/linux/console.h
index dedb082..eed92ad 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -116,6 +116,7 @@ static inline int con_debug_leave(void)
 #define CON_BOOT	(8)
 #define CON_ANYTIME	(16) /* Safe to call when cpu is offline */
 #define CON_BRL		(32) /* Used for a braille device */
+#define CON_ALLDATA	(64) /* per-console ignore_loglevel */
 
 struct console {
 	char	name[16];
diff --git a/kernel/printk.c b/kernel/printk.c
index 267ce78..5221c59 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -1261,8 +1261,6 @@ static void call_console_drivers(int level, const char *text, size_t len)
 
 	trace_console(text, 0, len, len);
 
-	if (level >= console_loglevel && !ignore_loglevel)
-		return;
 	if (!console_drivers)
 		return;
 
@@ -1276,6 +1274,9 @@ static void call_console_drivers(int level, const char *text, size_t len)
 		if (!cpu_online(smp_processor_id()) &&
 		    !(con->flags & CON_ANYTIME))
 			continue;
+		if (level >= console_loglevel && !ignore_loglevel &&
+		    !(con->flags & CON_ALLDATA))
+			continue;
 		con->write(con, text, len);
 	}
 }
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 4/9] netconsole: use CON_ALLDATA
  2013-02-28 21:39 [PATCH 0/9] Add blockconsole version 1.1 (try 2) Joern Engel
                   ` (2 preceding siblings ...)
  2013-02-28 21:39 ` [PATCH 3/9] printk: add CON_ALLDATA console flag Joern Engel
@ 2013-02-28 21:39 ` Joern Engel
  2013-02-28 21:39 ` [PATCH 5/9] blockconsole: " Joern Engel
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 36+ messages in thread
From: Joern Engel @ 2013-02-28 21:39 UTC (permalink / raw)
  To: linux-kernel; +Cc: Andrew Morton, Borislav Petkov, Jeff Moyer, Joern Engel

Netconsole should really see every message ever printed.  The
alternative is to try debugging with information like this:
[166135.633974] Stack:
[166135.634016] Call Trace:
[166135.634029]  <IRQ>
[166135.634156]  <EOI>
[166135.634177] Code: 00 00 55 48 89 e5 0f 1f 44 00 00 ff 15 31 49 80 00 c9 c3 66 66 66 66 66 66 2e 0f 1f 84 00 00 00 00 00 55 48 89 e5 0f 1f 44 00 00
[166135.634384]  48 8b 14 25 98 24 01 00 48 8d 14 92 48 8d 04 bd 00 00 00 00

Signed-off-by: Joern Engel <joern@logfs.org>
---
 drivers/net/netconsole.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index 6989ebe..77783fe 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -718,7 +718,7 @@ static void write_msg(struct console *con, const char *msg, unsigned int len)
 
 static struct console netconsole = {
 	.name	= "netcon",
-	.flags	= CON_ENABLED,
+	.flags	= CON_ENABLED | CON_ALLDATA,
 	.write	= write_msg,
 };
 
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 5/9] blockconsole: use CON_ALLDATA
  2013-02-28 21:39 [PATCH 0/9] Add blockconsole version 1.1 (try 2) Joern Engel
                   ` (3 preceding siblings ...)
  2013-02-28 21:39 ` [PATCH 4/9] netconsole: use CON_ALLDATA Joern Engel
@ 2013-02-28 21:39 ` Joern Engel
  2013-03-01 16:11   ` Jeff Moyer
  2013-02-28 21:39 ` [PATCH 6/9] bcon: add a release work struct Joern Engel
                   ` (5 subsequent siblings)
  10 siblings, 1 reply; 36+ messages in thread
From: Joern Engel @ 2013-02-28 21:39 UTC (permalink / raw)
  To: linux-kernel; +Cc: Andrew Morton, Borislav Petkov, Jeff Moyer, Joern Engel

Blockconsole should really see every message ever printed.  The
alternative is to try debugging with information like this:
[166135.633974] Stack:
[166135.634016] Call Trace:
[166135.634029]  <IRQ>
[166135.634156]  <EOI>
[166135.634177] Code: 00 00 55 48 89 e5 0f 1f 44 00 00 ff 15 31 49 80 00 c9 c3 66 66 66 66 66 66 2e 0f 1f 84 00 00 00 00 00 55 48 89 e5 0f 1f 44 00 00
[166135.634384]  48 8b 14 25 98 24 01 00 48 8d 14 92 48 8d 04 bd 00 00 00 00

Signed-off-by: Joern Engel <joern@logfs.org>
---
 drivers/block/blockconsole.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/block/blockconsole.c b/drivers/block/blockconsole.c
index 7f8ac5b..32f6c62 100644
--- a/drivers/block/blockconsole.c
+++ b/drivers/block/blockconsole.c
@@ -481,7 +481,7 @@ static int bcon_create(const char *devname)
 	strlcpy(bc->devname, devname, sizeof(bc->devname));
 	spin_lock_init(&bc->end_io_lock);
 	strcpy(bc->console.name, "bcon");
-	bc->console.flags = CON_PRINTBUFFER | CON_ENABLED;
+	bc->console.flags = CON_PRINTBUFFER | CON_ENABLED | CON_ALLDATA;
 	bc->console.write = bcon_write;
 	bc->bdev = blkdev_get_by_path(devname, mode, NULL);
 #ifndef MODULE
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 6/9] bcon: add a release work struct
  2013-02-28 21:39 [PATCH 0/9] Add blockconsole version 1.1 (try 2) Joern Engel
                   ` (4 preceding siblings ...)
  2013-02-28 21:39 ` [PATCH 5/9] blockconsole: " Joern Engel
@ 2013-02-28 21:39 ` Joern Engel
  2013-02-28 21:40 ` [PATCH 7/9] bcon: check for hdparm in bcon_tail Joern Engel
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 36+ messages in thread
From: Joern Engel @ 2013-02-28 21:39 UTC (permalink / raw)
  To: linux-kernel; +Cc: Andrew Morton, Borislav Petkov, Jeff Moyer, Joern Engel

The final bcon_put() can be called from atomic context, by way of
bio_endio().  In that case we would sleep in invalidate_mapping_pages(),
with the usual unhappy results.

In nearly a year of production use, I have only seen a matching
backtrace once.  There was a second known issue that could be reproduced
by "yes h > /proc/sysrq-trigger" and concurrently pulling and replugging
the blockconsole device.  It took be somewhere around 30 pulls and sore
thumbs to reproduce and I never found the time to get to the bottom of
it.  Quite likely the two issues are identical.

Signed-off-by: Joern Engel <joern@logfs.org>
---
 drivers/block/blockconsole.c |   15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/drivers/block/blockconsole.c b/drivers/block/blockconsole.c
index 32f6c62..b4730f8 100644
--- a/drivers/block/blockconsole.c
+++ b/drivers/block/blockconsole.c
@@ -65,6 +65,7 @@ struct blockconsole {
 	struct block_device *bdev;
 	struct console console;
 	struct work_struct unregister_work;
+	struct work_struct release_work;
 	struct task_struct *writeback_thread;
 	struct notifier_block panic_block;
 };
@@ -74,9 +75,10 @@ static void bcon_get(struct blockconsole *bc)
 	kref_get(&bc->kref);
 }
 
-static void bcon_release(struct kref *kref)
+static void __bcon_release(struct work_struct *work)
 {
-	struct blockconsole *bc = container_of(kref, struct blockconsole, kref);
+	struct blockconsole *bc = container_of(work, struct blockconsole,
+			release_work);
 
 	__free_pages(bc->zero_page, 0);
 	__free_pages(bc->pages, 8);
@@ -85,6 +87,14 @@ static void bcon_release(struct kref *kref)
 	kfree(bc);
 }
 
+static void bcon_release(struct kref *kref)
+{
+	struct blockconsole *bc = container_of(kref, struct blockconsole, kref);
+
+	/* bcon_release can be called from atomic context */
+	schedule_work(&bc->release_work);
+}
+
 static void bcon_put(struct blockconsole *bc)
 {
 	kref_put(&bc->kref, bcon_release);
@@ -512,6 +522,7 @@ static int bcon_create(const char *devname)
 	if (IS_ERR(bc->writeback_thread))
 		goto out2;
 	INIT_WORK(&bc->unregister_work, bcon_unregister);
+	INIT_WORK(&bc->release_work, __bcon_release);
 	register_console(&bc->console);
 	bc->panic_block.notifier_call = blockconsole_panic;
 	bc->panic_block.priority = INT_MAX;
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 7/9] bcon: check for hdparm in bcon_tail
  2013-02-28 21:39 [PATCH 0/9] Add blockconsole version 1.1 (try 2) Joern Engel
                   ` (5 preceding siblings ...)
  2013-02-28 21:39 ` [PATCH 6/9] bcon: add a release work struct Joern Engel
@ 2013-02-28 21:40 ` Joern Engel
  2013-02-28 21:40 ` [PATCH 8/9] blockconsole: Allow to pass a device file path to bcon_tail Joern Engel
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 36+ messages in thread
From: Joern Engel @ 2013-02-28 21:40 UTC (permalink / raw)
  To: linux-kernel; +Cc: Andrew Morton, Borislav Petkov, Jeff Moyer, Joern Engel

From: Borislav Petkov <bp@alien8.de>
Signed-off-by: Joern Engel <joern@logfs.org>
---
 Documentation/block/blockconsole/bcon_tail |    5 +++++
 1 file changed, 5 insertions(+)

diff --git a/Documentation/block/blockconsole/bcon_tail b/Documentation/block/blockconsole/bcon_tail
index b4bd660..eb3524b 100755
--- a/Documentation/block/blockconsole/bcon_tail
+++ b/Documentation/block/blockconsole/bcon_tail
@@ -14,6 +14,11 @@ if [ -z "$(which lsscsi)" ]; then
 	exit 1
 fi
 
+if [ -z "$(which hdparm)" ]; then
+	echo "You need to install the hdparm package on your distro."
+	exit 1
+fi
+
 end_of_log() {
 	DEV=$1
 	UUID=`head -c40 $DEV|tail -c8`
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 8/9] blockconsole: Allow to pass a device file path to bcon_tail
  2013-02-28 21:39 [PATCH 0/9] Add blockconsole version 1.1 (try 2) Joern Engel
                   ` (6 preceding siblings ...)
  2013-02-28 21:40 ` [PATCH 7/9] bcon: check for hdparm in bcon_tail Joern Engel
@ 2013-02-28 21:40 ` Joern Engel
  2013-02-28 21:40 ` [PATCH 9/9] bcon: remove version 1.0 support Joern Engel
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 36+ messages in thread
From: Joern Engel @ 2013-02-28 21:40 UTC (permalink / raw)
  To: linux-kernel
  Cc: Andrew Morton, Borislav Petkov, Jeff Moyer, Takashi Iwai, Joern Engel

From: Takashi Iwai <tiwai@suse.de>

... instead of always looking through all devices.

Minor tweak: Moved the "CANDIDATES=" line below Takashi's new code.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Joern Engel <joern@logfs.org>
---
 Documentation/block/blockconsole/bcon_tail |   15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/Documentation/block/blockconsole/bcon_tail b/Documentation/block/blockconsole/bcon_tail
index eb3524b..70926c6 100755
--- a/Documentation/block/blockconsole/bcon_tail
+++ b/Documentation/block/blockconsole/bcon_tail
@@ -58,6 +58,21 @@ end_of_log() {
 # HEADER contains a newline, so the funny quoting is necessary
 HEADER='
 Linux blockconsole version 1.1'
+
+DEV="$1"
+if [ -n "$DEV" ]; then
+	if [ ! -b "$DEV" ]; then
+		echo "bcon_tail: No block device file $DEV"
+		exit 1
+	fi
+	if [ "`head -c32 $DEV`" != "$HEADER" ]; then
+		echo "bcon_tail: Invalid device file $DEV"
+		exit 1
+	fi
+	end_of_log $DEV
+	exit 0
+fi
+
 CANDIDATES=`lsscsi |sed 's|.*/dev|/dev|'`
 
 for DEV in $CANDIDATES; do
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 9/9] bcon: remove version 1.0 support
  2013-02-28 21:39 [PATCH 0/9] Add blockconsole version 1.1 (try 2) Joern Engel
                   ` (7 preceding siblings ...)
  2013-02-28 21:40 ` [PATCH 8/9] blockconsole: Allow to pass a device file path to bcon_tail Joern Engel
@ 2013-02-28 21:40 ` Joern Engel
  2013-03-01 17:15 ` [PATCH 0/9] Add blockconsole version 1.1 (try 2) Takashi Iwai
  2013-03-20 22:52 ` [PATCH 0/9] Add blockconsole version 1.1 (try 2) Borislav Petkov
  10 siblings, 0 replies; 36+ messages in thread
From: Joern Engel @ 2013-02-28 21:40 UTC (permalink / raw)
  To: linux-kernel; +Cc: Andrew Morton, Borislav Petkov, Jeff Moyer, Joern Engel

Very few machines ever ran with 1.0 format and by now I doubt whether a
single one still does.  No need to carry that code along.

Signed-off-by: Joern Engel <joern@logfs.org>
---
 drivers/block/blockconsole.c |   19 ++-----------------
 1 file changed, 2 insertions(+), 17 deletions(-)

diff --git a/drivers/block/blockconsole.c b/drivers/block/blockconsole.c
index b4730f8..e88b8ee 100644
--- a/drivers/block/blockconsole.c
+++ b/drivers/block/blockconsole.c
@@ -18,7 +18,6 @@
 #include <linux/sched.h>
 #include <linux/ctype.h>
 
-#define BLOCKCONSOLE_MAGIC_OLD	"\nLinux blockconsole version 1.0\n"
 #define BLOCKCONSOLE_MAGIC	"\nLinux blockconsole version 1.1\n"
 #define BCON_UUID_OFS		(32)
 #define BCON_ROUND_OFS		(41)
@@ -234,18 +233,6 @@ static void bcon_advance_write_bytes(struct blockconsole *bc, int bytes)
 	}
 }
 
-static int bcon_convert_old_format(struct blockconsole *bc)
-{
-	bc->uuid = get_random_int();
-	bc->round = 0;
-	bc->console_bytes = bc->write_bytes = 0;
-	bcon_advance_console_bytes(bc, 0); /* To skip the header */
-	bcon_advance_write_bytes(bc, 0); /* To wrap around, if necessary */
-	bcon_erase_segment(bc);
-	pr_info("converted %s from old format\n", bc->devname);
-	return 0;
-}
-
 static int bcon_find_end_of_log(struct blockconsole *bc)
 {
 	u64 start = 0, end = bc->max_bytes, middle;
@@ -258,8 +245,8 @@ static int bcon_find_end_of_log(struct blockconsole *bc)
 		return err;
 	/* Second sanity check, out of sheer paranoia */
 	version = bcon_magic_present(sec0);
-	if (version == 10)
-		return bcon_convert_old_format(bc);
+	if (!version)
+		return -EINVAL;
 
 	bc->uuid = simple_strtoull(sec0 + BCON_UUID_OFS, NULL, 16);
 	bc->round = simple_strtoull(sec0 + BCON_ROUND_OFS, NULL, 16);
@@ -618,8 +605,6 @@ int bcon_magic_present(const void *data)
 {
 	size_t len = strlen(BLOCKCONSOLE_MAGIC);
 
-	if (!memcmp(data, BLOCKCONSOLE_MAGIC_OLD, len))
-		return 10;
 	if (memcmp(data, BLOCKCONSOLE_MAGIC, len))
 		return 0;
 	if (!is_four_byte_hex(data + BCON_UUID_OFS))
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* Re: [PATCH 3/9] printk: add CON_ALLDATA console flag
  2013-02-28 21:39 ` [PATCH 3/9] printk: add CON_ALLDATA console flag Joern Engel
@ 2013-03-01 14:52   ` Jeff Moyer
  2013-03-01 14:58     ` Borislav Petkov
  0 siblings, 1 reply; 36+ messages in thread
From: Jeff Moyer @ 2013-03-01 14:52 UTC (permalink / raw)
  To: Joern Engel; +Cc: linux-kernel, Andrew Morton, Borislav Petkov

Joern Engel <joern@logfs.org> writes:

> For consoles like netconsole and blockconsole the loglevel filtering
> really doesn't make any sense.  If a line gets printed at all, please
> send it down to that console, no questions asked.

Could you please explain this a bit further?  Why wouldn't you want to
allow the admin to filter log messages to the block or network console?
This doesn't make a whole lot of sense to me, and in fact could cause
problems for netconsole now that you're potentially sending a ton more
traffic over the wire.

Cheers,
Jeff

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 3/9] printk: add CON_ALLDATA console flag
  2013-03-01 14:52   ` Jeff Moyer
@ 2013-03-01 14:58     ` Borislav Petkov
  2013-03-01 15:08       ` Jeff Moyer
  0 siblings, 1 reply; 36+ messages in thread
From: Borislav Petkov @ 2013-03-01 14:58 UTC (permalink / raw)
  To: Jeff Moyer; +Cc: Joern Engel, linux-kernel, Andrew Morton

On Fri, Mar 01, 2013 at 09:52:27AM -0500, Jeff Moyer wrote:
> > For consoles like netconsole and blockconsole the loglevel filtering
> > really doesn't make any sense.  If a line gets printed at all, please
> > send it down to that console, no questions asked.
> 
> Could you please explain this a bit further?  Why wouldn't you want to
> allow the admin to filter log messages to the block or network console?
> This doesn't make a whole lot of sense to me, and in fact could cause
> problems for netconsole now that you're potentially sending a ton more
> traffic over the wire.

Let's reverse the question: why would the admin ever want to filter
messages to debugging consoles like netconsole or blockconsole?

When running a debugging session, you generally want to see *all*
messages.

-- 
Regards/Gruss,
    Boris.

Sent from a fat crate under my desk. Formatting is fine.
--

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 3/9] printk: add CON_ALLDATA console flag
  2013-03-01 14:58     ` Borislav Petkov
@ 2013-03-01 15:08       ` Jeff Moyer
  2013-03-01 15:31         ` Borislav Petkov
  2013-03-01 16:15         ` Jörn Engel
  0 siblings, 2 replies; 36+ messages in thread
From: Jeff Moyer @ 2013-03-01 15:08 UTC (permalink / raw)
  To: Borislav Petkov; +Cc: Joern Engel, linux-kernel, Andrew Morton

Borislav Petkov <bp@alien8.de> writes:

> On Fri, Mar 01, 2013 at 09:52:27AM -0500, Jeff Moyer wrote:
>> > For consoles like netconsole and blockconsole the loglevel filtering
>> > really doesn't make any sense.  If a line gets printed at all, please
>> > send it down to that console, no questions asked.
>> 
>> Could you please explain this a bit further?  Why wouldn't you want to
>> allow the admin to filter log messages to the block or network console?
>> This doesn't make a whole lot of sense to me, and in fact could cause
>> problems for netconsole now that you're potentially sending a ton more
>> traffic over the wire.
>
> Let's reverse the question: why would the admin ever want to filter
> messages to debugging consoles like netconsole or blockconsole?
>
> When running a debugging session, you generally want to see *all*
> messages.

People don't just use this for "debugging sessions."  They use it in
production, and I already gave you one reason why you might not want to
do this with netconsole (udp is unreliable, and I've definitely seem
cases where netconsole suffered due to dropped packets; this won't make
that better, especially when you multiply the extra bytes times the
number of servers on the subnet).

Cheers,
Jeff

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 3/9] printk: add CON_ALLDATA console flag
  2013-03-01 15:08       ` Jeff Moyer
@ 2013-03-01 15:31         ` Borislav Petkov
  2013-03-01 15:42           ` Jeff Moyer
  2013-03-01 16:15         ` Jörn Engel
  1 sibling, 1 reply; 36+ messages in thread
From: Borislav Petkov @ 2013-03-01 15:31 UTC (permalink / raw)
  To: Jeff Moyer; +Cc: Joern Engel, linux-kernel, Andrew Morton

On Fri, Mar 01, 2013 at 10:08:00AM -0500, Jeff Moyer wrote:
> People don't just use this for "debugging sessions." They use it in
> production, and I already gave you one reason why you might not want
> to do this with netconsole (udp is unreliable, and I've definitely
> seem cases where netconsole suffered due to dropped packets; this
> won't make that better, especially when you multiply the extra bytes
> times the number of servers on the subnet).

Ok, so we probably need to drop 4/9 for netconsole.

-- 
Regards/Gruss,
    Boris.

Sent from a fat crate under my desk. Formatting is fine.
--

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 3/9] printk: add CON_ALLDATA console flag
  2013-03-01 15:31         ` Borislav Petkov
@ 2013-03-01 15:42           ` Jeff Moyer
  2013-03-01 15:58             ` Borislav Petkov
  0 siblings, 1 reply; 36+ messages in thread
From: Jeff Moyer @ 2013-03-01 15:42 UTC (permalink / raw)
  To: Borislav Petkov; +Cc: Joern Engel, linux-kernel, Andrew Morton

Borislav Petkov <bp@alien8.de> writes:

> On Fri, Mar 01, 2013 at 10:08:00AM -0500, Jeff Moyer wrote:
>> People don't just use this for "debugging sessions." They use it in
>> production, and I already gave you one reason why you might not want
>> to do this with netconsole (udp is unreliable, and I've definitely
>> seem cases where netconsole suffered due to dropped packets; this
>> won't make that better, especially when you multiply the extra bytes
>> times the number of servers on the subnet).
>
> Ok, so we probably need to drop 4/9 for netconsole.

I don't think you've provided a very strong case for ignoring the
administrator's configuration settings.  I'm against the patches that
introduce this behaviour, for whatever that's worth (2 cents is the
going rate, I think).

Cheers,
Jeff

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 3/9] printk: add CON_ALLDATA console flag
  2013-03-01 15:42           ` Jeff Moyer
@ 2013-03-01 15:58             ` Borislav Petkov
  0 siblings, 0 replies; 36+ messages in thread
From: Borislav Petkov @ 2013-03-01 15:58 UTC (permalink / raw)
  To: Jeff Moyer; +Cc: Joern Engel, linux-kernel, Andrew Morton

On Fri, Mar 01, 2013 at 10:42:16AM -0500, Jeff Moyer wrote:
> I don't think you've provided a very strong case for ignoring the

Maybe you should've looked at the 5/9 commit message - there's your
strong case.

> administrator's configuration settings.  I'm against the patches that
> introduce this behaviour, for whatever that's worth (2 cents is the
> going rate, I think).

I'm fine with netconsole retaining old behavior since people reportedly
use it not only as a debugging console.

blockconsole, OTOH, is purely a debugging console and has to log
*everything* *out-of-the-box* once the block device is plugged in. No
configuration, no user intervention, no admin fiddling with whatever.

-- 
Regards/Gruss,
    Boris.

Sent from a fat crate under my desk. Formatting is fine.
--

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 5/9] blockconsole: use CON_ALLDATA
  2013-02-28 21:39 ` [PATCH 5/9] blockconsole: " Joern Engel
@ 2013-03-01 16:11   ` Jeff Moyer
  2013-03-01 16:20     ` Jörn Engel
  0 siblings, 1 reply; 36+ messages in thread
From: Jeff Moyer @ 2013-03-01 16:11 UTC (permalink / raw)
  To: Joern Engel; +Cc: linux-kernel, Andrew Morton, Borislav Petkov

Joern Engel <joern@logfs.org> writes:

> Blockconsole should really see every message ever printed.  The
> alternative is to try debugging with information like this:
> [166135.633974] Stack:
> [166135.634016] Call Trace:
> [166135.634029]  <IRQ>
> [166135.634156]  <EOI>
> [166135.634177] Code: 00 00 55 48 89 e5 0f 1f 44 00 00 ff 15 31 49 80 00 c9 c3 66 66 66 66 66 66 2e 0f 1f 84 00 00 00 00 00 55 48 89 e5 0f 1f 44 00 00
> [166135.634384]  48 8b 14 25 98 24 01 00 48 8d 14 92 48 8d 04 bd 00 00 00 00

What was your log level set to at the time?  By default, all of the
information for a kernel panic should show up on the console, no?

Cheers,
Jeff

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 3/9] printk: add CON_ALLDATA console flag
  2013-03-01 15:08       ` Jeff Moyer
  2013-03-01 15:31         ` Borislav Petkov
@ 2013-03-01 16:15         ` Jörn Engel
  1 sibling, 0 replies; 36+ messages in thread
From: Jörn Engel @ 2013-03-01 16:15 UTC (permalink / raw)
  To: Jeff Moyer; +Cc: Borislav Petkov, linux-kernel, Andrew Morton

On Fri, 1 March 2013 10:08:00 -0500, Jeff Moyer wrote:
> 
> People don't just use this for "debugging sessions."  They use it in
> production, and I already gave you one reason why you might not want to
> do this with netconsole (udp is unreliable, and I've definitely seem
> cases where netconsole suffered due to dropped packets; this won't make
> that better, especially when you multiply the extra bytes times the
> number of servers on the subnet).

I think I maintain a fairly sizeable production setup with netconsole.
A few hundred machines run netconsole and send all messages to a
single recipient.  And all those machines have the patch we are
discussing applied.  That has caused roughly zero problems so far.

We constantly see problems with netconsole and presumably packet loss
(haven't checked yet) when show_state() runs.  That amount of load
appears to be too much for the network.  Regular production netconsole
is utterly unimpressed in my network, with or without CON_ALLDATA.

Which is not to say you are wrong.  It just means that noone has shown
an example supporting your argument yet, while I have one supporting
mine.

More fundamentally, I believe the console log levels used to make
sense when systems had exactly one console.  With multiple consoles
and vastly different properties of those consoles, you simply cannot
find one good answer for all.  A 9600 baud serial console will usually
add several seconds to your boot process, so eliminating extra
messages is hugely important.  Blockconsole can take several megabytes
a second without blinking, so the cost of extra messages is near-zero,
while the benefit remains identical.

Maybe the correct solution would be to have a separate loglevel for
each console.  I don't know.  For my purposes the coarser CON_ALLDATA
approach is good enough.

Jörn

--
"Security vulnerabilities are here to stay."
-- Scott Culp, Manager of the Microsoft Security Response Center, 2001

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 5/9] blockconsole: use CON_ALLDATA
  2013-03-01 16:11   ` Jeff Moyer
@ 2013-03-01 16:20     ` Jörn Engel
  2013-03-01 17:52       ` Borislav Petkov
  0 siblings, 1 reply; 36+ messages in thread
From: Jörn Engel @ 2013-03-01 16:20 UTC (permalink / raw)
  To: Jeff Moyer; +Cc: linux-kernel, Andrew Morton, Borislav Petkov

On Fri, 1 March 2013 11:11:58 -0500, Jeff Moyer wrote:
> Joern Engel <joern@logfs.org> writes:
> 
> > Blockconsole should really see every message ever printed.  The
> > alternative is to try debugging with information like this:
> > [166135.633974] Stack:
> > [166135.634016] Call Trace:
> > [166135.634029]  <IRQ>
> > [166135.634156]  <EOI>
> > [166135.634177] Code: 00 00 55 48 89 e5 0f 1f 44 00 00 ff 15 31 49 80 00 c9 c3 66 66 66 66 66 66 2e 0f 1f 84 00 00 00 00 00 55 48 89 e5 0f 1f 44 00 00
> > [166135.634384]  48 8b 14 25 98 24 01 00 48 8d 14 92 48 8d 04 bd 00 00 00 00
> 
> What was your log level set to at the time?  By default, all of the
> information for a kernel panic should show up on the console, no?

I believe it was the distro default, which should be 4.  We used to
play silly games with setting the loglevel to "just send everything".
But that applies equally to all consoles, so you could no longer type
on the console and retain your sanity at the same time.

If you and/or other people are strongly opposed to the CON_ALLDATA
patches, I can either keep them private (we will never drop them from
our kernel) or add a config option.

Jörn

--
Doubt is not a pleasant condition, but certainty is an absurd one.
-- Voltaire

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 0/9] Add blockconsole version 1.1 (try 2)
  2013-03-01 17:15 ` [PATCH 0/9] Add blockconsole version 1.1 (try 2) Takashi Iwai
@ 2013-03-01 16:22   ` Jörn Engel
  2013-03-05 17:36     ` Takashi Iwai
  2013-03-01 17:17   ` [PATCH 1/3] blockconsole: Fix undefined MAX_RT_PRIO Takashi Iwai
  1 sibling, 1 reply; 36+ messages in thread
From: Jörn Engel @ 2013-03-01 16:22 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: linux-kernel, Andrew Morton, Borislav Petkov, Jeff Moyer

On Fri, 1 March 2013 18:15:10 +0100, Takashi Iwai wrote:
> 
> I got a build error after pulling onto the latest Linus tree.  Also I
> have another couple of trivial fixes.  The patches will follow.

Awesome, thanks!  Please give me some time for caffeine and sunshine
to take effect before merging.  I want to s/bc_/bcon_/g one of the
patches, otherwise they look fine.

Jörn

--
Computer system analysis is like child-rearing; you can do grievous damage,
but you cannot ensure success."
-- Tom DeMarco

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 5/9] blockconsole: use CON_ALLDATA
  2013-03-01 17:52       ` Borislav Petkov
@ 2013-03-01 16:31         ` Jörn Engel
  2013-03-01 17:56           ` Borislav Petkov
  0 siblings, 1 reply; 36+ messages in thread
From: Jörn Engel @ 2013-03-01 16:31 UTC (permalink / raw)
  To: Borislav Petkov; +Cc: Jeff Moyer, linux-kernel, Andrew Morton

On Fri, 1 March 2013 18:52:20 +0100, Borislav Petkov wrote:
> On Fri, Mar 01, 2013 at 11:20:29AM -0500, Jörn Engel wrote:
> > If you and/or other people are strongly opposed to the CON_ALLDATA
> > patches, I can either keep them private (we will never drop them from
> > our kernel) or add a config option.
> 
> We'll do that when someone comes up with a really persuasive reason why
> blockconsole shouldn't log *all* messages. And, whatever we do, I don't
> want to configure/set anything so that blockconsole logs everything - it
> should be the default.

For blockconsole I agree.  Netconsole is the interesting one, because
CON_ALLDATA could be considered a regression for it.

Jörn

--
The key to performance is elegance, not battalions of special cases.
-- Jon Bentley and Doug McIlroy

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 0/9] Add blockconsole version 1.1 (try 2)
  2013-02-28 21:39 [PATCH 0/9] Add blockconsole version 1.1 (try 2) Joern Engel
                   ` (8 preceding siblings ...)
  2013-02-28 21:40 ` [PATCH 9/9] bcon: remove version 1.0 support Joern Engel
@ 2013-03-01 17:15 ` Takashi Iwai
  2013-03-01 16:22   ` Jörn Engel
  2013-03-01 17:17   ` [PATCH 1/3] blockconsole: Fix undefined MAX_RT_PRIO Takashi Iwai
  2013-03-20 22:52 ` [PATCH 0/9] Add blockconsole version 1.1 (try 2) Borislav Petkov
  10 siblings, 2 replies; 36+ messages in thread
From: Takashi Iwai @ 2013-03-01 17:15 UTC (permalink / raw)
  To: Joern Engel; +Cc: linux-kernel, Andrew Morton, Borislav Petkov, Jeff Moyer

At Thu, 28 Feb 2013 16:39:53 -0500,
Joern Engel wrote:
> 
> Blockconsole is a console driver very roughly similar to netconsole.
> Instead of sending messages out via UDP, they are written to a block
> device.  Typically a USB stick is chosen, although in principle any
> block device will do.
> 
> In most cases blockconsole is useful where netconsole is not, i.e.
> single machines without network access or without an accessable
> netconsole capture server.  When using both blockconsole and
> netconsole, I have found netconsole to sometimes create a mess under
> high message load (sysrq-t, etc.) while blockconsole does not.
> 
> Most importantly, a number of bugs were identified and fixed that
> would have been unexplained machine reboots without blockconsole.
> 
> More highlights:
> * reasonably small and self-contained code,
> * some 100+ machine years of runtime,
> * nice tutorial with a 30-sec guide for the impatient.
> 
> Special thanks to Borislav Petkov for many improvements and kicking my
> behind to provide a proper git tree and resend patches.
> 
> A number of cleanup patches could be folded into the main patch, but I
> decided not to mess with git history and leave any further mistakes
> for the world to laugh at:
> git://git.kernel.org/pub/scm/linux/kernel/git/joern/bcon2.git

I got a build error after pulling onto the latest Linus tree.  Also I
have another couple of trivial fixes.  The patches will follow.


thanks,

Takashi

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH 1/3] blockconsole: Fix undefined MAX_RT_PRIO
  2013-03-01 17:15 ` [PATCH 0/9] Add blockconsole version 1.1 (try 2) Takashi Iwai
  2013-03-01 16:22   ` Jörn Engel
@ 2013-03-01 17:17   ` Takashi Iwai
  2013-03-01 17:17     ` [PATCH 2/3] blockconsole: Rename device_lock with bc_device_lock Takashi Iwai
  2013-03-01 17:17     ` [PATCH 3/3] blockconsole: Mark a local work struct static Takashi Iwai
  1 sibling, 2 replies; 36+ messages in thread
From: Takashi Iwai @ 2013-03-01 17:17 UTC (permalink / raw)
  To: Joern Engel; +Cc: linux-kernel, Andrew Morton, Borislav Petkov, Jeff Moyer

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 drivers/block/blockconsole.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/block/blockconsole.c b/drivers/block/blockconsole.c
index e88b8ee..c22272f 100644
--- a/drivers/block/blockconsole.c
+++ b/drivers/block/blockconsole.c
@@ -16,6 +16,7 @@
 #include <linux/string.h>
 #include <linux/workqueue.h>
 #include <linux/sched.h>
+#include <linux/sched/rt.h>
 #include <linux/ctype.h>
 
 #define BLOCKCONSOLE_MAGIC	"\nLinux blockconsole version 1.1\n"
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 2/3] blockconsole: Rename device_lock with bc_device_lock
  2013-03-01 17:17   ` [PATCH 1/3] blockconsole: Fix undefined MAX_RT_PRIO Takashi Iwai
@ 2013-03-01 17:17     ` Takashi Iwai
  2013-03-01 17:17     ` [PATCH 3/3] blockconsole: Mark a local work struct static Takashi Iwai
  1 sibling, 0 replies; 36+ messages in thread
From: Takashi Iwai @ 2013-03-01 17:17 UTC (permalink / raw)
  To: Joern Engel; +Cc: linux-kernel, Andrew Morton, Borislav Petkov, Jeff Moyer

Avoid the name conflict with device_lock() defined in linux/device.h.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 drivers/block/blockconsole.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/block/blockconsole.c b/drivers/block/blockconsole.c
index c22272f..147b8af 100644
--- a/drivers/block/blockconsole.c
+++ b/drivers/block/blockconsole.c
@@ -546,17 +546,17 @@ static void bcon_create_fuzzy(const char *name)
 	}
 }
 
-static DEFINE_SPINLOCK(device_lock);
+static DEFINE_SPINLOCK(bc_device_lock);
 static char scanned_devices[80];
 
 static void bcon_do_add(struct work_struct *work)
 {
 	char local_devices[80], *name, *remainder = local_devices;
 
-	spin_lock(&device_lock);
+	spin_lock(&bc_device_lock);
 	memcpy(local_devices, scanned_devices, sizeof(local_devices));
 	memset(scanned_devices, 0, sizeof(scanned_devices));
-	spin_unlock(&device_lock);
+	spin_unlock(&bc_device_lock);
 
 	while (remainder && remainder[0]) {
 		name = strsep(&remainder, ",");
@@ -573,11 +573,11 @@ void bcon_add(const char *name)
 	 * to go pick it up asap.  Once it is picked up, the buffer is empty
 	 * again, so hopefully it will suffice for all sane users.
 	 */
-	spin_lock(&device_lock);
+	spin_lock(&bc_device_lock);
 	if (scanned_devices[0])
 		strncat(scanned_devices, ",", sizeof(scanned_devices));
 	strncat(scanned_devices, name, sizeof(scanned_devices));
-	spin_unlock(&device_lock);
+	spin_unlock(&bc_device_lock);
 	schedule_work(&bcon_add_work);
 }
 
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 3/3] blockconsole: Mark a local work struct static
  2013-03-01 17:17   ` [PATCH 1/3] blockconsole: Fix undefined MAX_RT_PRIO Takashi Iwai
  2013-03-01 17:17     ` [PATCH 2/3] blockconsole: Rename device_lock with bc_device_lock Takashi Iwai
@ 2013-03-01 17:17     ` Takashi Iwai
  1 sibling, 0 replies; 36+ messages in thread
From: Takashi Iwai @ 2013-03-01 17:17 UTC (permalink / raw)
  To: Joern Engel; +Cc: linux-kernel, Andrew Morton, Borislav Petkov, Jeff Moyer

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 drivers/block/blockconsole.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/block/blockconsole.c b/drivers/block/blockconsole.c
index 147b8af..86744cc 100644
--- a/drivers/block/blockconsole.c
+++ b/drivers/block/blockconsole.c
@@ -564,7 +564,7 @@ static void bcon_do_add(struct work_struct *work)
 	}
 }
 
-DECLARE_WORK(bcon_add_work, bcon_do_add);
+static DECLARE_WORK(bcon_add_work, bcon_do_add);
 
 void bcon_add(const char *name)
 {
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* Re: [PATCH 5/9] blockconsole: use CON_ALLDATA
  2013-03-01 16:20     ` Jörn Engel
@ 2013-03-01 17:52       ` Borislav Petkov
  2013-03-01 16:31         ` Jörn Engel
  0 siblings, 1 reply; 36+ messages in thread
From: Borislav Petkov @ 2013-03-01 17:52 UTC (permalink / raw)
  To: Jörn Engel; +Cc: Jeff Moyer, linux-kernel, Andrew Morton

On Fri, Mar 01, 2013 at 11:20:29AM -0500, Jörn Engel wrote:
> If you and/or other people are strongly opposed to the CON_ALLDATA
> patches, I can either keep them private (we will never drop them from
> our kernel) or add a config option.

We'll do that when someone comes up with a really persuasive reason why
blockconsole shouldn't log *all* messages. And, whatever we do, I don't
want to configure/set anything so that blockconsole logs everything - it
should be the default.

-- 
Regards/Gruss,
    Boris.

Sent from a fat crate under my desk. Formatting is fine.
--

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 5/9] blockconsole: use CON_ALLDATA
  2013-03-01 16:31         ` Jörn Engel
@ 2013-03-01 17:56           ` Borislav Petkov
  0 siblings, 0 replies; 36+ messages in thread
From: Borislav Petkov @ 2013-03-01 17:56 UTC (permalink / raw)
  To: Jörn Engel; +Cc: Jeff Moyer, linux-kernel, Andrew Morton

On Fri, Mar 01, 2013 at 11:31:28AM -0500, Jörn Engel wrote:
> For blockconsole I agree.  Netconsole is the interesting one, because
> CON_ALLDATA could be considered a regression for it.

Yeah, that's why I suggested dropping 4/9 - nothing changes for
netconsole so that everyone can relax :-).

-- 
Regards/Gruss,
    Boris.

Sent from a fat crate under my desk. Formatting is fine.
--

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 0/9] Add blockconsole version 1.1 (try 2)
  2013-03-01 16:22   ` Jörn Engel
@ 2013-03-05 17:36     ` Takashi Iwai
  2013-03-06 19:49       ` Jörn Engel
  0 siblings, 1 reply; 36+ messages in thread
From: Takashi Iwai @ 2013-03-05 17:36 UTC (permalink / raw)
  To: Jörn Engel; +Cc: linux-kernel, Andrew Morton, Borislav Petkov, Jeff Moyer

At Fri, 1 Mar 2013 11:22:39 -0500,
Jörn Engel wrote:
> 
> On Fri, 1 March 2013 18:15:10 +0100, Takashi Iwai wrote:
> > 
> > I got a build error after pulling onto the latest Linus tree.  Also I
> > have another couple of trivial fixes.  The patches will follow.
> 
> Awesome, thanks!  Please give me some time for caffeine and sunshine
> to take effect before merging.  I want to s/bc_/bcon_/g one of the
> patches, otherwise they look fine.

Thanks!

Another thing I noticed is that the panic handler calls bcon_write(),
and it doesn't write to the device by itself.  Is it really supposed
to work?

Meanwhile I hacked the code to allow it being built as a module.
If anyone is interested, I'll send a patch series.  It's pretty
hackish, so likely need more brush up, though.


Takashi

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 0/9] Add blockconsole version 1.1 (try 2)
  2013-03-05 17:36     ` Takashi Iwai
@ 2013-03-06 19:49       ` Jörn Engel
  2013-03-07 18:46         ` Takashi Iwai
  0 siblings, 1 reply; 36+ messages in thread
From: Jörn Engel @ 2013-03-06 19:49 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: linux-kernel, Andrew Morton, Borislav Petkov, Jeff Moyer

On Tue, 5 March 2013 18:36:41 +0100, Takashi Iwai wrote:
> 
> Another thing I noticed is that the panic handler calls bcon_write(),
> and it doesn't write to the device by itself.  Is it really supposed
> to work?

Clearly it is supposed to work.  In reality it sometimes does and
sometimes does not.  Patches to improve the success rate are welcome.

> Meanwhile I hacked the code to allow it being built as a module.
> If anyone is interested, I'll send a patch series.  It's pretty
> hackish, so likely need more brush up, though.

I am interested.

Jörn

--
Ninety percent of everything is crap.
-- Sturgeon's Law

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 0/9] Add blockconsole version 1.1 (try 2)
  2013-03-06 19:49       ` Jörn Engel
@ 2013-03-07 18:46         ` Takashi Iwai
  2013-03-07 18:51           ` [PATCH 0/3] blockconsole: make it a module Takashi Iwai
  0 siblings, 1 reply; 36+ messages in thread
From: Takashi Iwai @ 2013-03-07 18:46 UTC (permalink / raw)
  To: Jörn Engel; +Cc: linux-kernel, Andrew Morton, Borislav Petkov, Jeff Moyer

At Wed, 6 Mar 2013 14:49:50 -0500,
Jörn Engel wrote:
> 
> On Tue, 5 March 2013 18:36:41 +0100, Takashi Iwai wrote:
> > 
> > Another thing I noticed is that the panic handler calls bcon_write(),
> > and it doesn't write to the device by itself.  Is it really supposed
> > to work?
> 
> Clearly it is supposed to work.  In reality it sometimes does and
> sometimes does not.  Patches to improve the success rate are welcome.

What I thought is to driver submit_bio in the panic handler itself
so that no scheduling is involved, like the patch below.  But I'm not
sure whether it would actually work...

> 
> > Meanwhile I hacked the code to allow it being built as a module.
> > If anyone is interested, I'll send a patch series.  It's pretty
> > hackish, so likely need more brush up, though.
> 
> I am interested.

OK, I'll send a patch series.  It'll be built on top of my previous
patches.  And I wrote it after merging to 3.9-rc1, so might be
slightly fuzzy to your tree.


thanks,

Takashi

---
diff --git a/drivers/block/blockconsole.c b/drivers/block/blockconsole.c
index 5fc192a..5042a5a 100644
--- a/drivers/block/blockconsole.c
+++ b/drivers/block/blockconsole.c
@@ -361,6 +361,16 @@ static void bcon_writesector(struct blockconsole *bc, int index)
 	submit_bio(WRITE, bio);
 }
 
+static void bcon_do_writeback(struct blockconsole *bc)
+{
+	while (bcon_write_sector(bc) != bcon_console_sector(bc)) {
+		bcon_writesector(bc, bcon_write_sector(bc));
+		bcon_advance_write_bytes(bc, SECTOR_SIZE);
+		if (bcon_write_sector(bc) == 0)
+			bcon_erase_segment(bc);
+	}
+}
+
 static int bcon_writeback(void *_bc)
 {
 	struct blockconsole *bc = _bc;
@@ -373,12 +383,7 @@ static int bcon_writeback(void *_bc)
 		schedule();
 		if (kthread_should_stop())
 			break;
-		while (bcon_write_sector(bc) != bcon_console_sector(bc)) {
-			bcon_writesector(bc, bcon_write_sector(bc));
-			bcon_advance_write_bytes(bc, SECTOR_SIZE);
-			if (bcon_write_sector(bc) == 0)
-				bcon_erase_segment(bc);
-		}
+		bcon_do_writeback(bc);
 	}
 	return 0;
 }
@@ -476,7 +481,7 @@ static int blockconsole_panic(struct notifier_block *this, unsigned long event,
 	n = SECTOR_SIZE - bcon_console_ofs(bc);
 	if (n != SECTOR_SIZE)
 		bcon_advance_console_bytes(bc, n);
-	bcon_writeback(bc);
+	bcon_do_writeback(bc);
 	return NOTIFY_DONE;
 }
 


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 0/3] blockconsole: make it a module
  2013-03-07 18:46         ` Takashi Iwai
@ 2013-03-07 18:51           ` Takashi Iwai
  2013-03-07 18:51             ` [PATCH 1/3] Export sched_setscheduler_nocheck() Takashi Iwai
                               ` (2 more replies)
  0 siblings, 3 replies; 36+ messages in thread
From: Takashi Iwai @ 2013-03-07 18:51 UTC (permalink / raw)
  To: Jörn Engel; +Cc: linux-kernel, Andrew Morton, Borislav Petkov, Jeff Moyer

Hi,

this is a patch series to allow to build the blockconsole as a module.
In a short test, it seems working somehow.  The module removal code is
a bit scary and there is much room for improvements / simplification.


thanks,

Takashi


^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH 1/3] Export sched_setscheduler_nocheck()
  2013-03-07 18:51           ` [PATCH 0/3] blockconsole: make it a module Takashi Iwai
@ 2013-03-07 18:51             ` Takashi Iwai
  2013-03-07 18:51             ` [PATCH 2/3] block/partitions: Support dynamic addition of partition checkers Takashi Iwai
  2013-03-07 18:51             ` [PATCH 3/3] blockconsole: Allow to be a module Takashi Iwai
  2 siblings, 0 replies; 36+ messages in thread
From: Takashi Iwai @ 2013-03-07 18:51 UTC (permalink / raw)
  To: Jörn Engel; +Cc: linux-kernel, Andrew Morton, Borislav Petkov, Jeff Moyer

... to be usable by modules.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 kernel/sched/core.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 7f12624..370d97d 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -3993,6 +3993,7 @@ int sched_setscheduler_nocheck(struct task_struct *p, int policy,
 {
 	return __sched_setscheduler(p, policy, param, false);
 }
+EXPORT_SYMBOL_GPL(sched_setscheduler_nocheck);
 
 static int
 do_sched_setscheduler(pid_t pid, int policy, struct sched_param __user *param)
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 2/3] block/partitions: Support dynamic addition of partition checkers
  2013-03-07 18:51           ` [PATCH 0/3] blockconsole: make it a module Takashi Iwai
  2013-03-07 18:51             ` [PATCH 1/3] Export sched_setscheduler_nocheck() Takashi Iwai
@ 2013-03-07 18:51             ` Takashi Iwai
  2013-03-07 18:51             ` [PATCH 3/3] blockconsole: Allow to be a module Takashi Iwai
  2 siblings, 0 replies; 36+ messages in thread
From: Takashi Iwai @ 2013-03-07 18:51 UTC (permalink / raw)
  To: Jörn Engel; +Cc: linux-kernel, Andrew Morton, Borislav Petkov, Jeff Moyer

Add helper functions to add / remove the partition checker function
dynamically.  This also allows to move the partition checker code into
the driver itself, e.g. the blockconsole partition checker can be in a
part of blockconsole driver (even as a module).

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 block/partitions/check.c | 35 +++++++++++++++++++++++++++++++++++
 block/partitions/check.h |  8 ++++++++
 2 files changed, 43 insertions(+)

diff --git a/block/partitions/check.c b/block/partitions/check.c
index 21786ed..d71cb02 100644
--- a/block/partitions/check.c
+++ b/block/partitions/check.c
@@ -17,6 +17,7 @@
 #include <linux/vmalloc.h>
 #include <linux/ctype.h>
 #include <linux/genhd.h>
+#include <linux/export.h>
 
 #include "check.h"
 
@@ -110,6 +111,9 @@ static int (*check_part[])(struct parsed_partitions *) = {
 	NULL
 };
 
+static DEFINE_MUTEX(check_part_mutex);
+static LIST_HEAD(check_part_list);
+
 static struct parsed_partitions *allocate_partitions(struct gendisk *hd)
 {
 	struct parsed_partitions *state;
@@ -172,6 +176,21 @@ check_partition(struct gendisk *hd, struct block_device *bdev)
 		}
 
 	}
+
+	if (res <= 0) {
+		struct partition_checker *c;
+		mutex_lock(&check_part_mutex);
+		list_for_each_entry(c, &check_part_list, list) {
+			memset(state->parts, 0, state->limit * sizeof(state->parts[0]));
+			res = c->check(state);
+			if (res < 0) {
+				err = res;
+				res = 0;
+			}
+		}
+		mutex_unlock(&check_part_mutex);
+	}
+
 	if (res > 0) {
 		printk(KERN_INFO "%s", state->pp_buf);
 
@@ -194,3 +213,19 @@ check_partition(struct gendisk *hd, struct block_device *bdev)
 	free_partitions(state);
 	return ERR_PTR(res);
 }
+
+void append_partition_checker(struct partition_checker *c)
+{
+	mutex_lock(&check_part_mutex);
+	list_add_tail(&c->list, &check_part_list);
+	mutex_unlock(&check_part_mutex);
+}
+EXPORT_SYMBOL_GPL(append_partition_checker);
+
+void remove_partition_checker(struct partition_checker *c)
+{
+	mutex_lock(&check_part_mutex);
+	list_del(&c->list);
+	mutex_unlock(&check_part_mutex);
+}
+EXPORT_SYMBOL_GPL(remove_partition_checker);
diff --git a/block/partitions/check.h b/block/partitions/check.h
index bca9624..53c8508 100644
--- a/block/partitions/check.h
+++ b/block/partitions/check.h
@@ -55,3 +55,11 @@ extern int warn_no_part;
 #ifdef CONFIG_BLOCKCONSOLE
 int blockconsole_partition(struct parsed_partitions *state);
 #endif
+
+struct partition_checker {
+	int (*check)(struct parsed_partitions *);
+	struct list_head list;
+};
+
+void append_partition_checker(struct partition_checker *c);
+void remove_partition_checker(struct partition_checker *c);
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 3/3] blockconsole: Allow to be a module
  2013-03-07 18:51           ` [PATCH 0/3] blockconsole: make it a module Takashi Iwai
  2013-03-07 18:51             ` [PATCH 1/3] Export sched_setscheduler_nocheck() Takashi Iwai
  2013-03-07 18:51             ` [PATCH 2/3] block/partitions: Support dynamic addition of partition checkers Takashi Iwai
@ 2013-03-07 18:51             ` Takashi Iwai
  2 siblings, 0 replies; 36+ messages in thread
From: Takashi Iwai @ 2013-03-07 18:51 UTC (permalink / raw)
  To: Jörn Engel; +Cc: linux-kernel, Andrew Morton, Borislav Petkov, Jeff Moyer

Move the partition checker code into blockconsole driver so that it
can be built as a module, too.  linux/blockconsole.h is removed since
all stuff is found locally in drivers/block/blockconsole.c.  Also some
functions are marked as static for the same reason.

A new linked list is added to blockconsole instance for managing the
proper unregistration at unloading the module on the fly.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 block/partitions/Makefile       |  1 -
 block/partitions/blockconsole.c | 22 -----------
 block/partitions/check.c        |  3 --
 block/partitions/check.h        |  4 --
 drivers/block/Kconfig           |  2 +-
 drivers/block/blockconsole.c    | 84 +++++++++++++++++++++++++++++++++++++++--
 include/linux/blockconsole.h    |  7 ----
 7 files changed, 81 insertions(+), 42 deletions(-)
 delete mode 100644 block/partitions/blockconsole.c
 delete mode 100644 include/linux/blockconsole.h

diff --git a/block/partitions/Makefile b/block/partitions/Makefile
index bf26d4a..03af8ea 100644
--- a/block/partitions/Makefile
+++ b/block/partitions/Makefile
@@ -18,4 +18,3 @@ obj-$(CONFIG_IBM_PARTITION) += ibm.o
 obj-$(CONFIG_EFI_PARTITION) += efi.o
 obj-$(CONFIG_KARMA_PARTITION) += karma.o
 obj-$(CONFIG_SYSV68_PARTITION) += sysv68.o
-obj-$(CONFIG_BLOCKCONSOLE) += blockconsole.o
diff --git a/block/partitions/blockconsole.c b/block/partitions/blockconsole.c
deleted file mode 100644
index 79796a8..0000000
--- a/block/partitions/blockconsole.c
+++ /dev/null
@@ -1,22 +0,0 @@
-#include <linux/blockconsole.h>
-
-#include "check.h"
-
-int blockconsole_partition(struct parsed_partitions *state)
-{
-	Sector sect;
-	void *data;
-	int err = 0;
-
-	data = read_part_sector(state, 0, &sect);
-	if (!data)
-		return -EIO;
-	if (!bcon_magic_present(data))
-		goto out;
-
-	bcon_add(state->name);
-	err = 1;
-out:
-	put_dev_sector(sect);
-	return err;
-}
diff --git a/block/partitions/check.c b/block/partitions/check.c
index d71cb02..d9e9324 100644
--- a/block/partitions/check.c
+++ b/block/partitions/check.c
@@ -43,9 +43,6 @@ static int (*check_part[])(struct parsed_partitions *) = {
 	 * Probe partition formats with tables at disk address 0
 	 * that also have an ADFS boot block at 0xdc0.
 	 */
-#ifdef CONFIG_BLOCKCONSOLE
-	blockconsole_partition,
-#endif
 #ifdef CONFIG_ACORN_PARTITION_ICS
 	adfspart_check_ICS,
 #endif
diff --git a/block/partitions/check.h b/block/partitions/check.h
index 53c8508..886ed32 100644
--- a/block/partitions/check.h
+++ b/block/partitions/check.h
@@ -52,10 +52,6 @@ put_partition(struct parsed_partitions *p, int n, sector_t from, sector_t size)
 
 extern int warn_no_part;
 
-#ifdef CONFIG_BLOCKCONSOLE
-int blockconsole_partition(struct parsed_partitions *state);
-#endif
-
 struct partition_checker {
 	int (*check)(struct parsed_partitions *);
 	struct list_head list;
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index 7da1360..2049ad4 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -542,7 +542,7 @@ config BLK_DEV_RSXX
 	  module will be called rsxx.
 
 config BLOCKCONSOLE
-	bool "Block device console logging support"
+	tristate "Block device console logging support"
 	help
 	  This enables logging to block devices.
 	  See <file:Documentation/block/blockconsole.txt> for details.
diff --git a/drivers/block/blockconsole.c b/drivers/block/blockconsole.c
index 86744cc..5fc192a 100644
--- a/drivers/block/blockconsole.c
+++ b/drivers/block/blockconsole.c
@@ -4,13 +4,13 @@
  * Copyright (C) 2012  Joern Engel <joern@logfs.org>
  */
 #include <linux/bio.h>
-#include <linux/blockconsole.h>
 #include <linux/console.h>
 #include <linux/fs.h>
 #include <linux/kref.h>
 #include <linux/kthread.h>
 #include <linux/mm.h>
 #include <linux/mount.h>
+#include <linux/module.h>
 #include <linux/random.h>
 #include <linux/slab.h>
 #include <linux/string.h>
@@ -18,6 +18,7 @@
 #include <linux/sched.h>
 #include <linux/sched/rt.h>
 #include <linux/ctype.h>
+#include "../../block/partitions/check.h"
 
 #define BLOCKCONSOLE_MAGIC	"\nLinux blockconsole version 1.1\n"
 #define BCON_UUID_OFS		(32)
@@ -68,8 +69,15 @@ struct blockconsole {
 	struct work_struct release_work;
 	struct task_struct *writeback_thread;
 	struct notifier_block panic_block;
+	struct list_head list;
 };
 
+static DEFINE_SPINLOCK(bc_device_lock);
+static LIST_HEAD(bc_list_head);
+static atomic_t bc_list_count = ATOMIC_INIT(0);
+
+static int bcon_magic_present(const void *data);
+
 static void bcon_get(struct blockconsole *bc)
 {
 	kref_get(&bc->kref);
@@ -85,6 +93,7 @@ static void __bcon_release(struct work_struct *work)
 	invalidate_mapping_pages(bc->bdev->bd_inode->i_mapping, 0, -1);
 	blkdev_put(bc->bdev, FMODE_READ|FMODE_WRITE);
 	kfree(bc);
+	atomic_dec(&bc_list_count);
 }
 
 static void bcon_release(struct kref *kref)
@@ -285,6 +294,11 @@ static void bcon_unregister(struct work_struct *work)
 	del_timer_sync(&bc->pad_timer);
 	kthread_stop(bc->writeback_thread);
 	/* No new io will be scheduled anymore now */
+
+	spin_lock(&bc_device_lock);
+	list_del_init(&bc->list);
+	spin_unlock(&bc_device_lock);
+
 	bcon_put(bc);
 }
 
@@ -515,7 +529,13 @@ static int bcon_create(const char *devname)
 	bc->panic_block.notifier_call = blockconsole_panic;
 	bc->panic_block.priority = INT_MAX;
 	atomic_notifier_chain_register(&panic_notifier_list, &bc->panic_block);
+
+	spin_lock(&bc_device_lock);
+	list_add(&bc->list, &bc_list_head);
+	spin_unlock(&bc_device_lock);
+
 	pr_info("now logging to %s at %llx\n", devname, bc->console_bytes >> 20);
+	atomic_inc(&bc_list_count);
 
 	return 0;
 
@@ -546,13 +566,13 @@ static void bcon_create_fuzzy(const char *name)
 	}
 }
 
-static DEFINE_SPINLOCK(bc_device_lock);
 static char scanned_devices[80];
 
 static void bcon_do_add(struct work_struct *work)
 {
 	char local_devices[80], *name, *remainder = local_devices;
 
+	atomic_inc(&bc_list_count);
 	spin_lock(&bc_device_lock);
 	memcpy(local_devices, scanned_devices, sizeof(local_devices));
 	memset(scanned_devices, 0, sizeof(scanned_devices));
@@ -562,11 +582,12 @@ static void bcon_do_add(struct work_struct *work)
 		name = strsep(&remainder, ",");
 		bcon_create_fuzzy(name);
 	}
+	atomic_dec(&bc_list_count);
 }
 
 static DECLARE_WORK(bcon_add_work, bcon_do_add);
 
-void bcon_add(const char *name)
+static void bcon_add(const char *name)
 {
 	/*
 	 * We add each name to a small static buffer and ask for a workqueue
@@ -602,7 +623,7 @@ static bool is_four_byte_hex(const void *data)
 	return true;
 }
 
-int bcon_magic_present(const void *data)
+static int bcon_magic_present(const void *data)
 {
 	size_t len = strlen(BLOCKCONSOLE_MAGIC);
 
@@ -616,3 +637,58 @@ int bcon_magic_present(const void *data)
 		return 0;
 	return 11;
 }
+
+static int blockconsole_partition(struct parsed_partitions *state)
+{
+	Sector sect;
+	void *data;
+	int err = 0;
+
+	data = read_part_sector(state, 0, &sect);
+	if (!data)
+		return -EIO;
+	if (!bcon_magic_present(data))
+		goto out;
+
+	bcon_add(state->name);
+	err = 1;
+out:
+	put_dev_sector(sect);
+	return err;
+}
+
+static struct partition_checker bc_part_checker = {
+	.check = blockconsole_partition
+};
+
+static int __init bcon_module_init(void)
+{
+	append_partition_checker(&bc_part_checker);
+	return 0;
+}
+
+static void __exit bcon_module_exit(void)
+{
+	remove_partition_checker(&bc_part_checker);
+	cancel_work_sync(&bcon_add_work);
+
+	/* unregister all pending consoles */
+	spin_lock(&bc_device_lock);
+	while (!list_empty(&bc_list_head)) {
+		struct blockconsole *bc;
+		bc = list_first_entry(&bc_list_head, struct blockconsole, list);
+		schedule_work(&bc->unregister_work);
+		list_del_init(&bc->list);
+	}
+	spin_unlock(&bc_device_lock);
+
+	while (atomic_read(&bc_list_count)) {
+		flush_scheduled_work();
+		schedule_timeout(1);
+	}
+}
+
+MODULE_LICENSE("GPL");
+
+module_init(bcon_module_init);
+module_exit(bcon_module_exit);
diff --git a/include/linux/blockconsole.h b/include/linux/blockconsole.h
deleted file mode 100644
index 114f7c5..0000000
--- a/include/linux/blockconsole.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef LINUX_BLOCKCONSOLE_H
-#define LINUX_BLOCKCONSOLE_H
-
-int bcon_magic_present(const void *data);
-void bcon_add(const char *name);
-
-#endif
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* Re: [PATCH 0/9] Add blockconsole version 1.1 (try 2)
  2013-02-28 21:39 [PATCH 0/9] Add blockconsole version 1.1 (try 2) Joern Engel
                   ` (9 preceding siblings ...)
  2013-03-01 17:15 ` [PATCH 0/9] Add blockconsole version 1.1 (try 2) Takashi Iwai
@ 2013-03-20 22:52 ` Borislav Petkov
  2013-03-21  6:30   ` Takashi Iwai
  10 siblings, 1 reply; 36+ messages in thread
From: Borislav Petkov @ 2013-03-20 22:52 UTC (permalink / raw)
  To: Andrew Morton; +Cc: Joern Engel, linux-kernel, Jeff Moyer, Takashi Iwai

Hi Andrew,

On Thu, Feb 28, 2013 at 04:39:53PM -0500, Joern Engel wrote:
> Blockconsole is a console driver very roughly similar to netconsole.
> Instead of sending messages out via UDP, they are written to a block
> device.  Typically a USB stick is chosen, although in principle any
> block device will do.
> 
> In most cases blockconsole is useful where netconsole is not, i.e.
> single machines without network access or without an accessable
> netconsole capture server.  When using both blockconsole and
> netconsole, I have found netconsole to sometimes create a mess under
> high message load (sysrq-t, etc.) while blockconsole does not.
> 
> Most importantly, a number of bugs were identified and fixed that
> would have been unexplained machine reboots without blockconsole.
> 
> More highlights:
> * reasonably small and self-contained code,
> * some 100+ machine years of runtime,
> * nice tutorial with a 30-sec guide for the impatient.

any thoughts on this?

Blockconsole is very useful in certain situations and a bunch of people
are using it already and it would be nice if we could get it moving
towards upstream.

So I'd appreciate it if you could take a look and maybe even pick it up
if there are no serious issues with it.

Thanks a bunch.

-- 
Regards/Gruss,
    Boris.

Sent from a fat crate under my desk. Formatting is fine.
--

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 0/9] Add blockconsole version 1.1 (try 2)
  2013-03-20 22:52 ` [PATCH 0/9] Add blockconsole version 1.1 (try 2) Borislav Petkov
@ 2013-03-21  6:30   ` Takashi Iwai
  0 siblings, 0 replies; 36+ messages in thread
From: Takashi Iwai @ 2013-03-21  6:30 UTC (permalink / raw)
  To: Borislav Petkov; +Cc: Andrew Morton, Joern Engel, linux-kernel, Jeff Moyer

At Wed, 20 Mar 2013 23:52:31 +0100,
Borislav Petkov wrote:
> 
> Hi Andrew,
> 
> On Thu, Feb 28, 2013 at 04:39:53PM -0500, Joern Engel wrote:
> > Blockconsole is a console driver very roughly similar to netconsole.
> > Instead of sending messages out via UDP, they are written to a block
> > device.  Typically a USB stick is chosen, although in principle any
> > block device will do.
> > 
> > In most cases blockconsole is useful where netconsole is not, i.e.
> > single machines without network access or without an accessable
> > netconsole capture server.  When using both blockconsole and
> > netconsole, I have found netconsole to sometimes create a mess under
> > high message load (sysrq-t, etc.) while blockconsole does not.
> > 
> > Most importantly, a number of bugs were identified and fixed that
> > would have been unexplained machine reboots without blockconsole.
> > 
> > More highlights:
> > * reasonably small and self-contained code,
> > * some 100+ machine years of runtime,
> > * nice tutorial with a 30-sec guide for the impatient.
> 
> any thoughts on this?
> 
> Blockconsole is very useful in certain situations and a bunch of people
> are using it already and it would be nice if we could get it moving
> towards upstream.
> 
> So I'd appreciate it if you could take a look and maybe even pick it up
> if there are no serious issues with it.

FYI, blockconsole was already merged in linux-next tree.


Takashi

^ permalink raw reply	[flat|nested] 36+ messages in thread

end of thread, other threads:[~2013-03-21  6:30 UTC | newest]

Thread overview: 36+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-02-28 21:39 [PATCH 0/9] Add blockconsole version 1.1 (try 2) Joern Engel
2013-02-28 21:39 ` [PATCH 1/9] do_mounts: constify name_to_dev_t parameter Joern Engel
2013-02-28 21:39 ` [PATCH 2/9] add blockconsole version 1.1 Joern Engel
2013-02-28 21:39 ` [PATCH 3/9] printk: add CON_ALLDATA console flag Joern Engel
2013-03-01 14:52   ` Jeff Moyer
2013-03-01 14:58     ` Borislav Petkov
2013-03-01 15:08       ` Jeff Moyer
2013-03-01 15:31         ` Borislav Petkov
2013-03-01 15:42           ` Jeff Moyer
2013-03-01 15:58             ` Borislav Petkov
2013-03-01 16:15         ` Jörn Engel
2013-02-28 21:39 ` [PATCH 4/9] netconsole: use CON_ALLDATA Joern Engel
2013-02-28 21:39 ` [PATCH 5/9] blockconsole: " Joern Engel
2013-03-01 16:11   ` Jeff Moyer
2013-03-01 16:20     ` Jörn Engel
2013-03-01 17:52       ` Borislav Petkov
2013-03-01 16:31         ` Jörn Engel
2013-03-01 17:56           ` Borislav Petkov
2013-02-28 21:39 ` [PATCH 6/9] bcon: add a release work struct Joern Engel
2013-02-28 21:40 ` [PATCH 7/9] bcon: check for hdparm in bcon_tail Joern Engel
2013-02-28 21:40 ` [PATCH 8/9] blockconsole: Allow to pass a device file path to bcon_tail Joern Engel
2013-02-28 21:40 ` [PATCH 9/9] bcon: remove version 1.0 support Joern Engel
2013-03-01 17:15 ` [PATCH 0/9] Add blockconsole version 1.1 (try 2) Takashi Iwai
2013-03-01 16:22   ` Jörn Engel
2013-03-05 17:36     ` Takashi Iwai
2013-03-06 19:49       ` Jörn Engel
2013-03-07 18:46         ` Takashi Iwai
2013-03-07 18:51           ` [PATCH 0/3] blockconsole: make it a module Takashi Iwai
2013-03-07 18:51             ` [PATCH 1/3] Export sched_setscheduler_nocheck() Takashi Iwai
2013-03-07 18:51             ` [PATCH 2/3] block/partitions: Support dynamic addition of partition checkers Takashi Iwai
2013-03-07 18:51             ` [PATCH 3/3] blockconsole: Allow to be a module Takashi Iwai
2013-03-01 17:17   ` [PATCH 1/3] blockconsole: Fix undefined MAX_RT_PRIO Takashi Iwai
2013-03-01 17:17     ` [PATCH 2/3] blockconsole: Rename device_lock with bc_device_lock Takashi Iwai
2013-03-01 17:17     ` [PATCH 3/3] blockconsole: Mark a local work struct static Takashi Iwai
2013-03-20 22:52 ` [PATCH 0/9] Add blockconsole version 1.1 (try 2) Borislav Petkov
2013-03-21  6:30   ` Takashi Iwai

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.