platform.c (b3b515bbd689ba3937cac2dd3fc55057f8c50329) | platform.c (b0aad7a99c1df90c23ff4bac76eea9cf25049e9e) |
---|---|
1/* 2 * Persistent Storage - platform driver interface parts. 3 * 4 * Copyright (C) 2007-2008 Google, Inc. 5 * Copyright (C) 2010 Intel Corporation <tony.luck@intel.com> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as --- 12 unchanged lines hidden (view full) --- 21#include <linux/atomic.h> 22#include <linux/types.h> 23#include <linux/errno.h> 24#include <linux/init.h> 25#include <linux/kmsg_dump.h> 26#include <linux/console.h> 27#include <linux/module.h> 28#include <linux/pstore.h> | 1/* 2 * Persistent Storage - platform driver interface parts. 3 * 4 * Copyright (C) 2007-2008 Google, Inc. 5 * Copyright (C) 2010 Intel Corporation <tony.luck@intel.com> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as --- 12 unchanged lines hidden (view full) --- 21#include <linux/atomic.h> 22#include <linux/types.h> 23#include <linux/errno.h> 24#include <linux/init.h> 25#include <linux/kmsg_dump.h> 26#include <linux/console.h> 27#include <linux/module.h> 28#include <linux/pstore.h> |
29#include <linux/zlib.h> |
|
29#include <linux/string.h> 30#include <linux/timer.h> 31#include <linux/slab.h> 32#include <linux/uaccess.h> 33#include <linux/hardirq.h> 34#include <linux/jiffies.h> 35#include <linux/workqueue.h> 36 --- 23 unchanged lines hidden (view full) --- 60 * pstore_lock just protects "psinfo" during 61 * calls to pstore_register() 62 */ 63static DEFINE_SPINLOCK(pstore_lock); 64struct pstore_info *psinfo; 65 66static char *backend; 67 | 30#include <linux/string.h> 31#include <linux/timer.h> 32#include <linux/slab.h> 33#include <linux/uaccess.h> 34#include <linux/hardirq.h> 35#include <linux/jiffies.h> 36#include <linux/workqueue.h> 37 --- 23 unchanged lines hidden (view full) --- 61 * pstore_lock just protects "psinfo" during 62 * calls to pstore_register() 63 */ 64static DEFINE_SPINLOCK(pstore_lock); 65struct pstore_info *psinfo; 66 67static char *backend; 68 |
69/* Compression parameters */ 70#define COMPR_LEVEL 6 71#define WINDOW_BITS 12 72#define MEM_LEVEL 4 73static struct z_stream_s stream; 74 75static char *big_oops_buf; 76static size_t big_oops_buf_sz; 77 |
|
68/* How much of the console log to snapshot */ 69static unsigned long kmsg_bytes = 10240; 70 71void pstore_set_kmsg_bytes(int bytes) 72{ 73 kmsg_bytes = bytes; 74} 75 --- 36 unchanged lines hidden (view full) --- 112 case KMSG_DUMP_EMERG: 113 return true; 114 default: 115 return false; 116 } 117} 118EXPORT_SYMBOL_GPL(pstore_cannot_block_path); 119 | 78/* How much of the console log to snapshot */ 79static unsigned long kmsg_bytes = 10240; 80 81void pstore_set_kmsg_bytes(int bytes) 82{ 83 kmsg_bytes = bytes; 84} 85 --- 36 unchanged lines hidden (view full) --- 122 case KMSG_DUMP_EMERG: 123 return true; 124 default: 125 return false; 126 } 127} 128EXPORT_SYMBOL_GPL(pstore_cannot_block_path); 129 |
130/* Derived from logfs_compress() */ 131static int pstore_compress(const void *in, void *out, size_t inlen, 132 size_t outlen) 133{ 134 int err, ret; 135 136 ret = -EIO; 137 err = zlib_deflateInit2(&stream, COMPR_LEVEL, Z_DEFLATED, WINDOW_BITS, 138 MEM_LEVEL, Z_DEFAULT_STRATEGY); 139 if (err != Z_OK) 140 goto error; 141 142 stream.next_in = in; 143 stream.avail_in = inlen; 144 stream.total_in = 0; 145 stream.next_out = out; 146 stream.avail_out = outlen; 147 stream.total_out = 0; 148 149 err = zlib_deflate(&stream, Z_FINISH); 150 if (err != Z_STREAM_END) 151 goto error; 152 153 err = zlib_deflateEnd(&stream); 154 if (err != Z_OK) 155 goto error; 156 157 if (stream.total_out >= stream.total_in) 158 goto error; 159 160 ret = stream.total_out; 161error: 162 return ret; 163} 164 165static void allocate_buf_for_compression(void) 166{ 167 size_t size; 168 169 big_oops_buf_sz = (psinfo->bufsize * 100) / 45; 170 big_oops_buf = kmalloc(big_oops_buf_sz, GFP_KERNEL); 171 if (big_oops_buf) { 172 size = max(zlib_deflate_workspacesize(WINDOW_BITS, MEM_LEVEL), 173 zlib_inflate_workspacesize()); 174 stream.workspace = kmalloc(size, GFP_KERNEL); 175 if (!stream.workspace) { 176 pr_err("pstore: No memory for compression workspace; " 177 "skipping compression\n"); 178 kfree(big_oops_buf); 179 big_oops_buf = NULL; 180 } 181 } else { 182 pr_err("No memory for uncompressed data; " 183 "skipping compression\n"); 184 stream.workspace = NULL; 185 } 186 187} 188 |
|
120/* | 189/* |
190 * Called when compression fails, since the printk buffer 191 * would be fetched for compression calling it again when 192 * compression fails would have moved the iterator of 193 * printk buffer which results in fetching old contents. 194 * Copy the recent messages from big_oops_buf to psinfo->buf 195 */ 196static size_t copy_kmsg_to_buffer(int hsize, size_t len) 197{ 198 size_t total_len; 199 size_t diff; 200 201 total_len = hsize + len; 202 203 if (total_len > psinfo->bufsize) { 204 diff = total_len - psinfo->bufsize + hsize; 205 memcpy(psinfo->buf, big_oops_buf, hsize); 206 memcpy(psinfo->buf + hsize, big_oops_buf + diff, 207 psinfo->bufsize - hsize); 208 total_len = psinfo->bufsize; 209 } else 210 memcpy(psinfo->buf, big_oops_buf, total_len); 211 212 return total_len; 213} 214 215/* |
|
121 * callback from kmsg_dump. (s2,l2) has the most recently 122 * written bytes, older bytes are in (s1,l1). Save as much 123 * as we can from the end of the buffer. 124 */ 125static void pstore_dump(struct kmsg_dumper *dumper, 126 enum kmsg_dump_reason reason) 127{ 128 unsigned long total = 0; --- 14 unchanged lines hidden (view full) --- 143 } 144 } else 145 spin_lock_irqsave(&psinfo->buf_lock, flags); 146 oopscount++; 147 while (total < kmsg_bytes) { 148 char *dst; 149 unsigned long size; 150 int hsize; | 216 * callback from kmsg_dump. (s2,l2) has the most recently 217 * written bytes, older bytes are in (s1,l1). Save as much 218 * as we can from the end of the buffer. 219 */ 220static void pstore_dump(struct kmsg_dumper *dumper, 221 enum kmsg_dump_reason reason) 222{ 223 unsigned long total = 0; --- 14 unchanged lines hidden (view full) --- 238 } 239 } else 240 spin_lock_irqsave(&psinfo->buf_lock, flags); 241 oopscount++; 242 while (total < kmsg_bytes) { 243 char *dst; 244 unsigned long size; 245 int hsize; |
246 int zipped_len = -1; |
|
151 size_t len; | 247 size_t len; |
152 bool compressed = false; | 248 bool compressed; 249 size_t total_len; |
153 | 250 |
154 dst = psinfo->buf; 155 hsize = sprintf(dst, "%s#%d Part%d\n", why, oopscount, part); 156 size = psinfo->bufsize - hsize; 157 dst += hsize; | 251 if (big_oops_buf) { 252 dst = big_oops_buf; 253 hsize = sprintf(dst, "%s#%d Part%d\n", why, 254 oopscount, part); 255 size = big_oops_buf_sz - hsize; |
158 | 256 |
159 if (!kmsg_dump_get_buffer(dumper, true, dst, size, &len)) 160 break; | 257 if (!kmsg_dump_get_buffer(dumper, true, dst + hsize, 258 size, &len)) 259 break; |
161 | 260 |
261 zipped_len = pstore_compress(dst, psinfo->buf, 262 hsize + len, psinfo->bufsize); 263 264 if (zipped_len > 0) { 265 compressed = true; 266 total_len = zipped_len; 267 } else { 268 pr_err("pstore: compression failed for Part %d" 269 " returned %d\n", part, zipped_len); 270 pr_err("pstore: Capture uncompressed" 271 " oops/panic report of Part %d\n", part); 272 compressed = false; 273 total_len = copy_kmsg_to_buffer(hsize, len); 274 } 275 } else { 276 dst = psinfo->buf; 277 hsize = sprintf(dst, "%s#%d Part%d\n", why, oopscount, 278 part); 279 size = psinfo->bufsize - hsize; 280 dst += hsize; 281 282 if (!kmsg_dump_get_buffer(dumper, true, dst, 283 size, &len)) 284 break; 285 286 compressed = false; 287 total_len = hsize + len; 288 } 289 |
|
162 ret = psinfo->write(PSTORE_TYPE_DMESG, reason, &id, part, | 290 ret = psinfo->write(PSTORE_TYPE_DMESG, reason, &id, part, |
163 oopscount, compressed, hsize + len, psinfo); | 291 oopscount, compressed, total_len, psinfo); |
164 if (ret == 0 && reason == KMSG_DUMP_OOPS && pstore_is_mounted()) 165 pstore_new_entry = 1; 166 | 292 if (ret == 0 && reason == KMSG_DUMP_OOPS && pstore_is_mounted()) 293 pstore_new_entry = 1; 294 |
167 total += hsize + len; | 295 total += total_len; |
168 part++; 169 } 170 if (pstore_cannot_block_path(reason)) { 171 if (is_locked) 172 spin_unlock_irqrestore(&psinfo->buf_lock, flags); 173 } else 174 spin_unlock_irqrestore(&psinfo->buf_lock, flags); 175} --- 81 unchanged lines hidden (view full) --- 257 mutex_init(&psinfo->read_mutex); 258 spin_unlock(&pstore_lock); 259 260 if (owner && !try_module_get(owner)) { 261 psinfo = NULL; 262 return -EINVAL; 263 } 264 | 296 part++; 297 } 298 if (pstore_cannot_block_path(reason)) { 299 if (is_locked) 300 spin_unlock_irqrestore(&psinfo->buf_lock, flags); 301 } else 302 spin_unlock_irqrestore(&psinfo->buf_lock, flags); 303} --- 81 unchanged lines hidden (view full) --- 385 mutex_init(&psinfo->read_mutex); 386 spin_unlock(&pstore_lock); 387 388 if (owner && !try_module_get(owner)) { 389 psinfo = NULL; 390 return -EINVAL; 391 } 392 |
393 allocate_buf_for_compression(); 394 |
|
265 if (pstore_is_mounted()) 266 pstore_get_records(0); 267 268 kmsg_dump_register(&pstore_dumper); 269 pstore_register_console(); 270 pstore_register_ftrace(); 271 272 if (pstore_update_ms >= 0) { --- 71 unchanged lines hidden --- | 395 if (pstore_is_mounted()) 396 pstore_get_records(0); 397 398 kmsg_dump_register(&pstore_dumper); 399 pstore_register_console(); 400 pstore_register_ftrace(); 401 402 if (pstore_update_ms >= 0) { --- 71 unchanged lines hidden --- |