diff options
Diffstat (limited to 'fs/pstore/platform.c')
-rw-r--r-- | fs/pstore/platform.c | 53 |
1 files changed, 46 insertions, 7 deletions
diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c index 16ecca5b72d8..14984d902a99 100644 --- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c @@ -623,6 +623,40 @@ static int pstore_write_compat(enum pstore_type_id type, size, psi); } +static int pstore_write_buf_user_compat(enum pstore_type_id type, + enum kmsg_dump_reason reason, + u64 *id, unsigned int part, + const char __user *buf, + bool compressed, size_t size, + struct pstore_info *psi) +{ + unsigned long flags = 0; + size_t i, bufsize = size; + long ret = 0; + + if (unlikely(!access_ok(VERIFY_READ, buf, size))) + return -EFAULT; + if (bufsize > psinfo->bufsize) + bufsize = psinfo->bufsize; + spin_lock_irqsave(&psinfo->buf_lock, flags); + for (i = 0; i < size; ) { + size_t c = min(size - i, bufsize); + + ret = __copy_from_user(psinfo->buf, buf + i, c); + if (unlikely(ret != 0)) { + ret = -EFAULT; + break; + } + ret = psi->write_buf(type, reason, id, part, psinfo->buf, + compressed, c, psi); + if (unlikely(ret < 0)) + break; + i += c; + } + spin_unlock_irqrestore(&psinfo->buf_lock, flags); + return unlikely(ret < 0) ? ret : size; +} + /* * platform specific persistent storage driver registers with * us here. If pstore is already mounted, call the platform @@ -645,6 +679,8 @@ int pstore_register(struct pstore_info *psi) if (!psi->write) psi->write = pstore_write_compat; + if (!psi->write_buf_user) + psi->write_buf_user = pstore_write_buf_user_compat; psinfo = psi; mutex_init(&psinfo->read_mutex); spin_unlock(&pstore_lock); @@ -659,13 +695,14 @@ int pstore_register(struct pstore_info *psi) if (pstore_is_mounted()) pstore_get_records(0); - pstore_register_kmsg(); - - if ((psi->flags & PSTORE_FLAGS_FRAGILE) == 0) { + if (psi->flags & PSTORE_FLAGS_DMESG) + pstore_register_kmsg(); + if (psi->flags & PSTORE_FLAGS_CONSOLE) pstore_register_console(); + if (psi->flags & PSTORE_FLAGS_FTRACE) pstore_register_ftrace(); + if (psi->flags & PSTORE_FLAGS_PMSG) pstore_register_pmsg(); - } if (pstore_update_ms >= 0) { pstore_timer.expires = jiffies + @@ -689,12 +726,14 @@ EXPORT_SYMBOL_GPL(pstore_register); void pstore_unregister(struct pstore_info *psi) { - if ((psi->flags & PSTORE_FLAGS_FRAGILE) == 0) { + if (psi->flags & PSTORE_FLAGS_PMSG) pstore_unregister_pmsg(); + if (psi->flags & PSTORE_FLAGS_FTRACE) pstore_unregister_ftrace(); + if (psi->flags & PSTORE_FLAGS_CONSOLE) pstore_unregister_console(); - } - pstore_unregister_kmsg(); + if (psi->flags & PSTORE_FLAGS_DMESG) + pstore_unregister_kmsg(); free_buf_for_compression(); |