diff options
| -rw-r--r-- | Documentation/ABI/testing/pstore | 12 | ||||
| -rw-r--r-- | Documentation/ABI/testing/sysfs-fs-pstore | 7 | ||||
| -rw-r--r-- | fs/pstore/inode.c | 68 | ||||
| -rw-r--r-- | fs/pstore/internal.h | 3 | ||||
| -rw-r--r-- | fs/pstore/platform.c | 16 |
5 files changed, 59 insertions, 47 deletions
diff --git a/Documentation/ABI/testing/pstore b/Documentation/ABI/testing/pstore index f1fb2a004264..ddf451ee2a08 100644 --- a/Documentation/ABI/testing/pstore +++ b/Documentation/ABI/testing/pstore | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | Where: /dev/pstore/... | 1 | Where: /dev/pstore/... |
| 2 | Date: January 2011 | 2 | Date: March 2011 |
| 3 | Kernel Version: 2.6.38 | 3 | Kernel Version: 2.6.39 |
| 4 | Contact: tony.luck@intel.com | 4 | Contact: tony.luck@intel.com |
| 5 | Description: Generic interface to platform dependent persistent storage. | 5 | Description: Generic interface to platform dependent persistent storage. |
| 6 | 6 | ||
| @@ -11,7 +11,7 @@ Description: Generic interface to platform dependent persistent storage. | |||
| 11 | of the console log is captured, but other interesting | 11 | of the console log is captured, but other interesting |
| 12 | data can also be saved. | 12 | data can also be saved. |
| 13 | 13 | ||
| 14 | # mount -t pstore - /dev/pstore | 14 | # mount -t pstore -o kmsg_bytes=8000 - /dev/pstore |
| 15 | 15 | ||
| 16 | $ ls -l /dev/pstore | 16 | $ ls -l /dev/pstore |
| 17 | total 0 | 17 | total 0 |
| @@ -33,3 +33,9 @@ Description: Generic interface to platform dependent persistent storage. | |||
| 33 | will be saved elsewhere and erased from persistent store | 33 | will be saved elsewhere and erased from persistent store |
| 34 | soon after boot to free up space ready for the next | 34 | soon after boot to free up space ready for the next |
| 35 | catastrophe. | 35 | catastrophe. |
| 36 | |||
| 37 | The 'kmsg_bytes' mount option changes the target amount of | ||
| 38 | data saved on each oops/panic. Pstore saves (possibly | ||
| 39 | multiple) files based on the record size of the underlying | ||
| 40 | persistent storage until at least this amount is reached. | ||
| 41 | Default is 10 Kbytes. | ||
diff --git a/Documentation/ABI/testing/sysfs-fs-pstore b/Documentation/ABI/testing/sysfs-fs-pstore deleted file mode 100644 index 8e659d854805..000000000000 --- a/Documentation/ABI/testing/sysfs-fs-pstore +++ /dev/null | |||
| @@ -1,7 +0,0 @@ | |||
| 1 | What: /sys/fs/pstore/kmsg_bytes | ||
| 2 | Date: January 2011 | ||
| 3 | Kernel Version: 2.6.38 | ||
| 4 | Contact: "Tony Luck" <tony.luck@intel.com> | ||
| 5 | Description: | ||
| 6 | Controls amount of console log that will be saved | ||
| 7 | to persistent store on oops/panic. | ||
diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c index f777f2902c49..977ed2723845 100644 --- a/fs/pstore/inode.c +++ b/fs/pstore/inode.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #include <linux/string.h> | 27 | #include <linux/string.h> |
| 28 | #include <linux/mount.h> | 28 | #include <linux/mount.h> |
| 29 | #include <linux/ramfs.h> | 29 | #include <linux/ramfs.h> |
| 30 | #include <linux/parser.h> | ||
| 30 | #include <linux/sched.h> | 31 | #include <linux/sched.h> |
| 31 | #include <linux/magic.h> | 32 | #include <linux/magic.h> |
| 32 | #include <linux/pstore.h> | 33 | #include <linux/pstore.h> |
| @@ -112,10 +113,52 @@ static struct inode *pstore_get_inode(struct super_block *sb, | |||
| 112 | return inode; | 113 | return inode; |
| 113 | } | 114 | } |
| 114 | 115 | ||
| 116 | enum { | ||
| 117 | Opt_kmsg_bytes, Opt_err | ||
| 118 | }; | ||
| 119 | |||
| 120 | static const match_table_t tokens = { | ||
| 121 | {Opt_kmsg_bytes, "kmsg_bytes=%u"}, | ||
| 122 | {Opt_err, NULL} | ||
| 123 | }; | ||
| 124 | |||
| 125 | static void parse_options(char *options) | ||
| 126 | { | ||
| 127 | char *p; | ||
| 128 | substring_t args[MAX_OPT_ARGS]; | ||
| 129 | int option; | ||
| 130 | |||
| 131 | if (!options) | ||
| 132 | return; | ||
| 133 | |||
| 134 | while ((p = strsep(&options, ",")) != NULL) { | ||
| 135 | int token; | ||
| 136 | |||
| 137 | if (!*p) | ||
| 138 | continue; | ||
| 139 | |||
| 140 | token = match_token(p, tokens, args); | ||
| 141 | switch (token) { | ||
| 142 | case Opt_kmsg_bytes: | ||
| 143 | if (!match_int(&args[0], &option)) | ||
| 144 | pstore_set_kmsg_bytes(option); | ||
| 145 | break; | ||
| 146 | } | ||
| 147 | } | ||
| 148 | } | ||
| 149 | |||
| 150 | static int pstore_remount(struct super_block *sb, int *flags, char *data) | ||
| 151 | { | ||
| 152 | parse_options(data); | ||
| 153 | |||
| 154 | return 0; | ||
| 155 | } | ||
| 156 | |||
| 115 | static const struct super_operations pstore_ops = { | 157 | static const struct super_operations pstore_ops = { |
| 116 | .statfs = simple_statfs, | 158 | .statfs = simple_statfs, |
| 117 | .drop_inode = generic_delete_inode, | 159 | .drop_inode = generic_delete_inode, |
| 118 | .evict_inode = pstore_evict_inode, | 160 | .evict_inode = pstore_evict_inode, |
| 161 | .remount_fs = pstore_remount, | ||
| 119 | .show_options = generic_show_options, | 162 | .show_options = generic_show_options, |
| 120 | }; | 163 | }; |
| 121 | 164 | ||
| @@ -215,6 +258,8 @@ int pstore_fill_super(struct super_block *sb, void *data, int silent) | |||
| 215 | sb->s_op = &pstore_ops; | 258 | sb->s_op = &pstore_ops; |
| 216 | sb->s_time_gran = 1; | 259 | sb->s_time_gran = 1; |
| 217 | 260 | ||
| 261 | parse_options(data); | ||
| 262 | |||
| 218 | inode = pstore_get_inode(sb, NULL, S_IFDIR | 0755, 0); | 263 | inode = pstore_get_inode(sb, NULL, S_IFDIR | 0755, 0); |
| 219 | if (!inode) { | 264 | if (!inode) { |
| 220 | err = -ENOMEM; | 265 | err = -ENOMEM; |
| @@ -258,28 +303,7 @@ static struct file_system_type pstore_fs_type = { | |||
| 258 | 303 | ||
| 259 | static int __init init_pstore_fs(void) | 304 | static int __init init_pstore_fs(void) |
| 260 | { | 305 | { |
| 261 | int rc = 0; | 306 | return register_filesystem(&pstore_fs_type); |
| 262 | struct kobject *pstorefs_kobj; | ||
| 263 | |||
| 264 | pstorefs_kobj = kobject_create_and_add("pstore", fs_kobj); | ||
| 265 | if (!pstorefs_kobj) { | ||
| 266 | rc = -ENOMEM; | ||
| 267 | goto done; | ||
| 268 | } | ||
| 269 | |||
| 270 | rc = sysfs_create_file(pstorefs_kobj, &pstore_kmsg_bytes_attr.attr); | ||
| 271 | if (rc) | ||
| 272 | goto done1; | ||
| 273 | |||
| 274 | rc = register_filesystem(&pstore_fs_type); | ||
| 275 | if (rc == 0) | ||
| 276 | goto done; | ||
| 277 | |||
| 278 | sysfs_remove_file(pstorefs_kobj, &pstore_kmsg_bytes_attr.attr); | ||
| 279 | done1: | ||
| 280 | kobject_put(pstorefs_kobj); | ||
| 281 | done: | ||
| 282 | return rc; | ||
| 283 | } | 307 | } |
| 284 | module_init(init_pstore_fs) | 308 | module_init(init_pstore_fs) |
| 285 | 309 | ||
diff --git a/fs/pstore/internal.h b/fs/pstore/internal.h index 76c26d2fab29..8c9f23eb1645 100644 --- a/fs/pstore/internal.h +++ b/fs/pstore/internal.h | |||
| @@ -1,7 +1,6 @@ | |||
| 1 | extern void pstore_set_kmsg_bytes(int); | ||
| 1 | extern void pstore_get_records(void); | 2 | extern void pstore_get_records(void); |
| 2 | extern int pstore_mkfile(enum pstore_type_id, char *psname, u64 id, | 3 | extern int pstore_mkfile(enum pstore_type_id, char *psname, u64 id, |
| 3 | char *data, size_t size, | 4 | char *data, size_t size, |
| 4 | struct timespec time, int (*erase)(u64)); | 5 | struct timespec time, int (*erase)(u64)); |
| 5 | extern int pstore_is_mounted(void); | 6 | extern int pstore_is_mounted(void); |
| 6 | |||
| 7 | extern struct kobj_attribute pstore_kmsg_bytes_attr; | ||
diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c index 705fdf8abf6e..ce9ad84d5dd9 100644 --- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c | |||
| @@ -37,24 +37,14 @@ | |||
| 37 | static DEFINE_SPINLOCK(pstore_lock); | 37 | static DEFINE_SPINLOCK(pstore_lock); |
| 38 | static struct pstore_info *psinfo; | 38 | static struct pstore_info *psinfo; |
| 39 | 39 | ||
| 40 | /* How much of the console log to snapshot. /sys/fs/pstore/kmsg_bytes */ | 40 | /* How much of the console log to snapshot */ |
| 41 | static unsigned long kmsg_bytes = 10240; | 41 | static unsigned long kmsg_bytes = 10240; |
| 42 | 42 | ||
| 43 | static ssize_t b_show(struct kobject *kobj, | 43 | void pstore_set_kmsg_bytes(int bytes) |
| 44 | struct kobj_attribute *attr, char *buf) | ||
| 45 | { | 44 | { |
| 46 | return snprintf(buf, PAGE_SIZE, "%lu\n", kmsg_bytes); | 45 | kmsg_bytes = bytes; |
| 47 | } | 46 | } |
| 48 | 47 | ||
| 49 | static ssize_t b_store(struct kobject *kobj, struct kobj_attribute *attr, | ||
| 50 | const char *buf, size_t count) | ||
| 51 | { | ||
| 52 | return (sscanf(buf, "%lu", &kmsg_bytes) > 0) ? count : 0; | ||
| 53 | } | ||
| 54 | |||
| 55 | struct kobj_attribute pstore_kmsg_bytes_attr = | ||
| 56 | __ATTR(kmsg_bytes, S_IRUGO | S_IWUSR, b_show, b_store); | ||
| 57 | |||
| 58 | /* Tag each group of saved records with a sequence number */ | 48 | /* Tag each group of saved records with a sequence number */ |
| 59 | static int oopscount; | 49 | static int oopscount; |
| 60 | 50 | ||
