Skip to content

Commit

Permalink
pstore/blk: Export a method to implemente panic_write()
Browse files Browse the repository at this point in the history
The panic_write() is necessary to write the pstore frontend message
to blk devices when panic. Here is a way to register panic_write when
we use "best_effort" way to register the pstore blk-backend.

Usage:

    xx_register_pstore_panic_write(pstore_blk_notifier_type type,
	    struct pstore_device_info *pdi)
    {
	switch (type) {
	case PSTORE_BLK_BACKEND_REGISTER:
	case PSTORE_BLK_BACKEND_PANIC_DRV_REGISTER:
	    ...

	    pid->zone.panic_write = xxx;

	    ...
	    break;
	case PSTORE_BLK_BACKEND_UNREGISTER:
	case PSTORE_BLK_BACKEND_PANIC_DRV_UNREGISTER:
	    ...

	    pdi->zone.panic_write = NULL;

	    ...
	    break;
	default:
	    break;
	}

    }

    static struct pstore_blk_notifier pbn = {
	.notitifer_call = xx_register_pstore_panic_write;
    }

    use {un,}register_pstore_blk_panic_notifier() to register/unregister
    pstore_blk_notifier

Signed-off-by: Victor Hassan <victor@allwinnertech.com>
  • Loading branch information
allwinner-zh authored and intel-lab-lkp committed Feb 3, 2023
1 parent 88603b6 commit 368e42b
Show file tree
Hide file tree
Showing 2 changed files with 116 additions and 4 deletions.
101 changes: 97 additions & 4 deletions fs/pstore/blk.c
Expand Up @@ -18,6 +18,7 @@
#include <linux/file.h>
#include <linux/init_syscalls.h>
#include <linux/mount.h>
#include <linux/notifier.h>

static long kmsg_size = CONFIG_PSTORE_BLK_KMSG_SIZE;
module_param(kmsg_size, long, 0400);
Expand Down Expand Up @@ -72,6 +73,14 @@ static DEFINE_MUTEX(pstore_blk_lock);
static struct file *psblk_file;
static struct pstore_device_info *pstore_device_info;

static struct {
struct raw_notifier_head chain;
struct pstore_blk_notifier *pbn;
bool notifier;
} pstore_blk_panic_notifier = {
.chain = RAW_NOTIFIER_INIT(pstore_blk_panic_notifier.chain),
};

#define check_size(name, alignsize) ({ \
long _##name_ = (name); \
_##name_ = _##name_ <= 0 ? 0 : (_##name_ * 1024); \
Expand All @@ -94,6 +103,82 @@ static struct pstore_device_info *pstore_device_info;
dev->zone.name = _##name_; \
}

static int pstore_blk_panic_notifier_call(struct notifier_block *nb,
unsigned long action, void *data)
{
int ret = 0;
struct pstore_blk_notifier *pbn =
container_of(nb, struct pstore_blk_notifier, nb);

if (pbn)
ret = pbn->notifier_call(action, data);

return ret;
}

int register_pstore_blk_panic_notifier(struct pstore_blk_notifier *pbn)
{
int err = 0;
struct notifier_block *nb;

mutex_lock(&pstore_blk_lock);

if (pstore_blk_panic_notifier.notifier) {
pr_info("had register panic\n");
goto unlock;
}

nb = &pbn->nb;
nb->notifier_call = pstore_blk_panic_notifier_call;

err = raw_notifier_chain_register(&pstore_blk_panic_notifier.chain, nb);
if (err)
goto unlock;

if (pstore_device_info)
err = nb->notifier_call(nb, PSTORE_BLK_BACKEND_PANIC_DRV_REGISTER,
pstore_device_info);

if (!err)
pstore_blk_panic_notifier.notifier = true;

unlock:
mutex_unlock(&pstore_blk_lock);

return err;
}
EXPORT_SYMBOL_GPL(register_pstore_blk_panic_notifier);

void unregister_pstore_blk_panic_notifier(struct pstore_blk_notifier *pbn)
{
struct notifier_block *nb = &pbn->nb;

mutex_lock(&pstore_blk_lock);

raw_notifier_chain_unregister(&pstore_blk_panic_notifier.chain, nb);

if (pstore_device_info)
nb->notifier_call(nb, PSTORE_BLK_BACKEND_PANIC_DRV_UNREGISTER,
pstore_device_info);

pstore_blk_panic_notifier.notifier = false;

mutex_unlock(&pstore_blk_lock);
}
EXPORT_SYMBOL_GPL(unregister_pstore_blk_panic_notifier);

static int pstore_blk_panic_notifier_init_call(struct pstore_device_info *pdi)
{
return raw_notifier_call_chain(&pstore_blk_panic_notifier.chain,
PSTORE_BLK_BACKEND_REGISTER, pdi);
}

static int pstore_blk_panic_notifier_exit_call(struct pstore_device_info *pdi)
{
return raw_notifier_call_chain(&pstore_blk_panic_notifier.chain,
PSTORE_BLK_BACKEND_UNREGISTER, pdi);
}

static int __register_pstore_device(struct pstore_device_info *dev)
{
int ret;
Expand Down Expand Up @@ -301,16 +386,22 @@ static int __init __best_effort_init(void)
if (!best_effort_dev)
return -ENOMEM;

strcpy(best_effort_dev->path, blkdev);
best_effort_dev->zone.read = psblk_generic_blk_read;
best_effort_dev->zone.write = psblk_generic_blk_write;

ret = __register_pstore_blk(best_effort_dev,
early_boot_devpath(blkdev));
if (ret)
if (ret) {
kfree(best_effort_dev);
else
pr_info("attached %s (%lu) (no dedicated panic_write!)\n",
blkdev, best_effort_dev->zone.total_size);
} else {
if (pstore_blk_panic_notifier_init_call(best_effort_dev) == NOTIFY_OK)
pr_info("attached %s (%lu) (dedicated panic_write!)\n",
blkdev, best_effort_dev->zone.total_size);
else
pr_info("attached %s (%lu) (no dedicated panic_write!)\n",
blkdev, best_effort_dev->zone.total_size);
}

return ret;
}
Expand All @@ -326,6 +417,8 @@ static void __exit __best_effort_exit(void)
if (psblk_file) {
struct pstore_device_info *dev = pstore_device_info;

pstore_blk_panic_notifier_exit_call(dev);

__unregister_pstore_device(dev);
kfree(dev);
fput(psblk_file);
Expand Down
19 changes: 19 additions & 0 deletions include/linux/pstore_blk.h
Expand Up @@ -17,13 +17,32 @@
*
*/
struct pstore_device_info {
char path[80];
unsigned int flags;
struct pstore_zone_info zone;
};

enum pstore_blk_notifier_type {
PSTORE_BLK_BACKEND_REGISTER = 1,
PSTORE_BLK_BACKEND_PANIC_DRV_REGISTER,
PSTORE_BLK_BACKEND_UNREGISTER,
PSTORE_BLK_BACKEND_PANIC_DRV_UNREGISTER,
};

typedef int (*pstore_blk_notifier_fn_t)(pstore_blk_notifier_type type,
struct pstore_device_info *dev);

struct pstore_blk_notifier {
struct notifier_block nb;
pstore_blk_notifier_fn_t notifier_call;
};

int register_pstore_device(struct pstore_device_info *dev);
void unregister_pstore_device(struct pstore_device_info *dev);

int register_pstore_blk_panic_notifier(struct pstore_blk_notifier *pbn);
void unregister_pstore_blk_panic_notifier(struct pstore_blk_notifier *nb);

/**
* struct pstore_blk_config - the pstore_blk backend configuration
*
Expand Down

0 comments on commit 368e42b

Please sign in to comment.