Commit 366f7e7a authored by Luck, Tony's avatar Luck, Tony Committed by Linus Torvalds

pstore: use mount option instead sysfs to tweak kmsg_bytes

/sys/fs is a somewhat strange way to tweak what could more
obviously be tuned with a mount option.
Suggested-by: default avatarChristoph Hellwig <hch@infradead.org>
Signed-off-by: default avatarTony Luck <tony.luck@intel.com>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 10effcb5
Where: /dev/pstore/... Where: /dev/pstore/...
Date: January 2011 Date: March 2011
Kernel Version: 2.6.38 Kernel Version: 2.6.39
Contact: tony.luck@intel.com Contact: tony.luck@intel.com
Description: Generic interface to platform dependent persistent storage. Description: Generic interface to platform dependent persistent storage.
...@@ -11,7 +11,7 @@ Description: Generic interface to platform dependent persistent storage. ...@@ -11,7 +11,7 @@ Description: Generic interface to platform dependent persistent storage.
of the console log is captured, but other interesting of the console log is captured, but other interesting
data can also be saved. data can also be saved.
# mount -t pstore - /dev/pstore # mount -t pstore -o kmsg_bytes=8000 - /dev/pstore
$ ls -l /dev/pstore $ ls -l /dev/pstore
total 0 total 0
...@@ -33,3 +33,9 @@ Description: Generic interface to platform dependent persistent storage. ...@@ -33,3 +33,9 @@ Description: Generic interface to platform dependent persistent storage.
will be saved elsewhere and erased from persistent store will be saved elsewhere and erased from persistent store
soon after boot to free up space ready for the next soon after boot to free up space ready for the next
catastrophe. catastrophe.
The 'kmsg_bytes' mount option changes the target amount of
data saved on each oops/panic. Pstore saves (possibly
multiple) files based on the record size of the underlying
persistent storage until at least this amount is reached.
Default is 10 Kbytes.
What: /sys/fs/pstore/kmsg_bytes
Date: January 2011
Kernel Version: 2.6.38
Contact: "Tony Luck" <tony.luck@intel.com>
Description:
Controls amount of console log that will be saved
to persistent store on oops/panic.
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <linux/string.h> #include <linux/string.h>
#include <linux/mount.h> #include <linux/mount.h>
#include <linux/ramfs.h> #include <linux/ramfs.h>
#include <linux/parser.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/magic.h> #include <linux/magic.h>
#include <linux/pstore.h> #include <linux/pstore.h>
...@@ -112,10 +113,52 @@ static struct inode *pstore_get_inode(struct super_block *sb, ...@@ -112,10 +113,52 @@ static struct inode *pstore_get_inode(struct super_block *sb,
return inode; return inode;
} }
enum {
Opt_kmsg_bytes, Opt_err
};
static const match_table_t tokens = {
{Opt_kmsg_bytes, "kmsg_bytes=%u"},
{Opt_err, NULL}
};
static void parse_options(char *options)
{
char *p;
substring_t args[MAX_OPT_ARGS];
int option;
if (!options)
return;
while ((p = strsep(&options, ",")) != NULL) {
int token;
if (!*p)
continue;
token = match_token(p, tokens, args);
switch (token) {
case Opt_kmsg_bytes:
if (!match_int(&args[0], &option))
pstore_set_kmsg_bytes(option);
break;
}
}
}
static int pstore_remount(struct super_block *sb, int *flags, char *data)
{
parse_options(data);
return 0;
}
static const struct super_operations pstore_ops = { static const struct super_operations pstore_ops = {
.statfs = simple_statfs, .statfs = simple_statfs,
.drop_inode = generic_delete_inode, .drop_inode = generic_delete_inode,
.evict_inode = pstore_evict_inode, .evict_inode = pstore_evict_inode,
.remount_fs = pstore_remount,
.show_options = generic_show_options, .show_options = generic_show_options,
}; };
...@@ -215,6 +258,8 @@ int pstore_fill_super(struct super_block *sb, void *data, int silent) ...@@ -215,6 +258,8 @@ int pstore_fill_super(struct super_block *sb, void *data, int silent)
sb->s_op = &pstore_ops; sb->s_op = &pstore_ops;
sb->s_time_gran = 1; sb->s_time_gran = 1;
parse_options(data);
inode = pstore_get_inode(sb, NULL, S_IFDIR | 0755, 0); inode = pstore_get_inode(sb, NULL, S_IFDIR | 0755, 0);
if (!inode) { if (!inode) {
err = -ENOMEM; err = -ENOMEM;
...@@ -258,28 +303,7 @@ static struct file_system_type pstore_fs_type = { ...@@ -258,28 +303,7 @@ static struct file_system_type pstore_fs_type = {
static int __init init_pstore_fs(void) static int __init init_pstore_fs(void)
{ {
int rc = 0; return register_filesystem(&pstore_fs_type);
struct kobject *pstorefs_kobj;
pstorefs_kobj = kobject_create_and_add("pstore", fs_kobj);
if (!pstorefs_kobj) {
rc = -ENOMEM;
goto done;
}
rc = sysfs_create_file(pstorefs_kobj, &pstore_kmsg_bytes_attr.attr);
if (rc)
goto done1;
rc = register_filesystem(&pstore_fs_type);
if (rc == 0)
goto done;
sysfs_remove_file(pstorefs_kobj, &pstore_kmsg_bytes_attr.attr);
done1:
kobject_put(pstorefs_kobj);
done:
return rc;
} }
module_init(init_pstore_fs) module_init(init_pstore_fs)
......
extern void pstore_set_kmsg_bytes(int);
extern void pstore_get_records(void); extern void pstore_get_records(void);
extern int pstore_mkfile(enum pstore_type_id, char *psname, u64 id, extern int pstore_mkfile(enum pstore_type_id, char *psname, u64 id,
char *data, size_t size, char *data, size_t size,
struct timespec time, int (*erase)(u64)); struct timespec time, int (*erase)(u64));
extern int pstore_is_mounted(void); extern int pstore_is_mounted(void);
extern struct kobj_attribute pstore_kmsg_bytes_attr;
...@@ -37,24 +37,14 @@ ...@@ -37,24 +37,14 @@
static DEFINE_SPINLOCK(pstore_lock); static DEFINE_SPINLOCK(pstore_lock);
static struct pstore_info *psinfo; static struct pstore_info *psinfo;
/* How much of the console log to snapshot. /sys/fs/pstore/kmsg_bytes */ /* How much of the console log to snapshot */
static unsigned long kmsg_bytes = 10240; static unsigned long kmsg_bytes = 10240;
static ssize_t b_show(struct kobject *kobj, void pstore_set_kmsg_bytes(int bytes)
struct kobj_attribute *attr, char *buf)
{ {
return snprintf(buf, PAGE_SIZE, "%lu\n", kmsg_bytes); kmsg_bytes = bytes;
} }
static ssize_t b_store(struct kobject *kobj, struct kobj_attribute *attr,
const char *buf, size_t count)
{
return (sscanf(buf, "%lu", &kmsg_bytes) > 0) ? count : 0;
}
struct kobj_attribute pstore_kmsg_bytes_attr =
__ATTR(kmsg_bytes, S_IRUGO | S_IWUSR, b_show, b_store);
/* Tag each group of saved records with a sequence number */ /* Tag each group of saved records with a sequence number */
static int oopscount; static int oopscount;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment