Loading kernel/trace/ipc_logging.c +39 −11 Original line number Diff line number Diff line Loading @@ -549,6 +549,7 @@ int ipc_log_extract(void *ctxt, char *buff, int size) struct decode_context *dctxt); struct ipc_log_context *ilctxt = (struct ipc_log_context *)ctxt; unsigned long flags; int ret; if (size < MAX_MSG_DECODED_SIZE) return -EINVAL; Loading @@ -558,6 +559,11 @@ int ipc_log_extract(void *ctxt, char *buff, int size) dctxt.size = size; read_lock_irqsave(&context_list_lock_lha1, flags); spin_lock(&ilctxt->context_lock_lhb1); if (ilctxt->destroyed) { ret = -EIO; goto done; } while (dctxt.size >= MAX_MSG_DECODED_SIZE && !is_nd_read_empty(ilctxt)) { msg_read(ilctxt, &ectxt); Loading @@ -573,11 +579,17 @@ int ipc_log_extract(void *ctxt, char *buff, int size) read_lock_irqsave(&context_list_lock_lha1, flags); spin_lock(&ilctxt->context_lock_lhb1); } if ((size - dctxt.size) == 0) ret = size - dctxt.size; if (ret == 0) { if (!ilctxt->destroyed) reinit_completion(&ilctxt->read_avail); else ret = -EIO; } done: spin_unlock(&ilctxt->context_lock_lhb1); read_unlock_irqrestore(&context_list_lock_lha1, flags); return size - dctxt.size; return ret; } EXPORT_SYMBOL(ipc_log_extract); Loading Loading @@ -835,6 +847,8 @@ void *ipc_log_context_create(int max_num_pages, ctxt->nd_read_page = ctxt->first_page; ctxt->write_avail = max_num_pages * LOG_PAGE_DATA_SIZE; ctxt->header_size = sizeof(struct ipc_log_page_header); kref_init(&ctxt->refcount); ctxt->destroyed = false; create_ctx_debugfs(ctxt, mod_name); /* set magic last to signal context init is complete */ Loading @@ -857,6 +871,21 @@ void *ipc_log_context_create(int max_num_pages, } EXPORT_SYMBOL(ipc_log_context_create); void ipc_log_context_free(struct kref *kref) { struct ipc_log_context *ilctxt = container_of(kref, struct ipc_log_context, refcount); struct ipc_log_page *pg = NULL; while (!list_empty(&ilctxt->page_list)) { pg = get_first_page(ilctxt); list_del(&pg->hdr.list); kfree(pg); } kfree(ilctxt); } /* * Destroy debug log context * Loading @@ -865,25 +894,24 @@ EXPORT_SYMBOL(ipc_log_context_create); int ipc_log_context_destroy(void *ctxt) { struct ipc_log_context *ilctxt = (struct ipc_log_context *)ctxt; struct ipc_log_page *pg = NULL; unsigned long flags; if (!ilctxt) return 0; while (!list_empty(&ilctxt->page_list)) { pg = get_first_page(ctxt); list_del(&pg->hdr.list); kfree(pg); } debugfs_remove_recursive(ilctxt->dent); spin_lock(&ilctxt->context_lock_lhb1); ilctxt->destroyed = true; complete_all(&ilctxt->read_avail); spin_unlock(&ilctxt->context_lock_lhb1); write_lock_irqsave(&context_list_lock_lha1, flags); list_del(&ilctxt->list); write_unlock_irqrestore(&context_list_lock_lha1, flags); debugfs_remove_recursive(ilctxt->dent); ipc_log_context_put(ilctxt); kfree(ilctxt); return 0; } EXPORT_SYMBOL(ipc_log_context_destroy); Loading kernel/trace/ipc_logging_debug.c +25 −6 Original line number Diff line number Diff line /* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. /* Copyright (c) 2012-2015, 2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -74,23 +74,42 @@ static int debug_log(struct ipc_log_context *ilctxt, static ssize_t debug_read_helper(struct file *file, char __user *buff, size_t count, loff_t *ppos, int cont) { struct ipc_log_context *ilctxt = file->private_data; struct ipc_log_context *ilctxt; struct dentry *d = file->f_path.dentry; char *buffer; int bsize; int srcu_idx; int r; r = debugfs_use_file_start(d, &srcu_idx); if (!r) { ilctxt = file->private_data; r = kref_get_unless_zero(&ilctxt->refcount) ? 0 : -EIO; } debugfs_use_file_finish(srcu_idx); if (r) return r; buffer = kmalloc(count, GFP_KERNEL); if (!buffer) return -ENOMEM; if (!buffer) { bsize = -ENOMEM; goto done; } bsize = debug_log(ilctxt, buffer, count, cont); if (bsize > 0) { if (copy_to_user(buff, buffer, bsize)) { bsize = -EFAULT; kfree(buffer); return -EFAULT; goto done; } *ppos += bsize; } kfree(buffer); done: ipc_log_context_put(ilctxt); return bsize; } Loading Loading @@ -127,7 +146,7 @@ static void debug_create(const char *name, mode_t mode, struct ipc_log_context *ilctxt, const struct file_operations *fops) { debugfs_create_file(name, mode, dent, ilctxt, fops); debugfs_create_file_unsafe(name, mode, dent, ilctxt, fops); } static void dfunc_string(struct encode_context *ectxt, Loading kernel/trace/ipc_logging_private.h +10 −1 Original line number Diff line number Diff line /* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -119,6 +119,8 @@ struct ipc_log_context { struct list_head dfunc_info_list; spinlock_t context_lock_lhb1; struct completion read_avail; struct kref refcount; bool destroyed; }; struct dfunc_info { Loading Loading @@ -147,6 +149,13 @@ enum { ((x) < TSV_TYPE_MSG_END)) #define MAX_MSG_DECODED_SIZE (MAX_MSG_SIZE*4) void ipc_log_context_free(struct kref *kref); static inline void ipc_log_context_put(struct ipc_log_context *ilctxt) { kref_put(&ilctxt->refcount, ipc_log_context_free); } #if (defined(CONFIG_DEBUG_FS)) void check_and_create_debugfs(void); Loading Loading
kernel/trace/ipc_logging.c +39 −11 Original line number Diff line number Diff line Loading @@ -549,6 +549,7 @@ int ipc_log_extract(void *ctxt, char *buff, int size) struct decode_context *dctxt); struct ipc_log_context *ilctxt = (struct ipc_log_context *)ctxt; unsigned long flags; int ret; if (size < MAX_MSG_DECODED_SIZE) return -EINVAL; Loading @@ -558,6 +559,11 @@ int ipc_log_extract(void *ctxt, char *buff, int size) dctxt.size = size; read_lock_irqsave(&context_list_lock_lha1, flags); spin_lock(&ilctxt->context_lock_lhb1); if (ilctxt->destroyed) { ret = -EIO; goto done; } while (dctxt.size >= MAX_MSG_DECODED_SIZE && !is_nd_read_empty(ilctxt)) { msg_read(ilctxt, &ectxt); Loading @@ -573,11 +579,17 @@ int ipc_log_extract(void *ctxt, char *buff, int size) read_lock_irqsave(&context_list_lock_lha1, flags); spin_lock(&ilctxt->context_lock_lhb1); } if ((size - dctxt.size) == 0) ret = size - dctxt.size; if (ret == 0) { if (!ilctxt->destroyed) reinit_completion(&ilctxt->read_avail); else ret = -EIO; } done: spin_unlock(&ilctxt->context_lock_lhb1); read_unlock_irqrestore(&context_list_lock_lha1, flags); return size - dctxt.size; return ret; } EXPORT_SYMBOL(ipc_log_extract); Loading Loading @@ -835,6 +847,8 @@ void *ipc_log_context_create(int max_num_pages, ctxt->nd_read_page = ctxt->first_page; ctxt->write_avail = max_num_pages * LOG_PAGE_DATA_SIZE; ctxt->header_size = sizeof(struct ipc_log_page_header); kref_init(&ctxt->refcount); ctxt->destroyed = false; create_ctx_debugfs(ctxt, mod_name); /* set magic last to signal context init is complete */ Loading @@ -857,6 +871,21 @@ void *ipc_log_context_create(int max_num_pages, } EXPORT_SYMBOL(ipc_log_context_create); void ipc_log_context_free(struct kref *kref) { struct ipc_log_context *ilctxt = container_of(kref, struct ipc_log_context, refcount); struct ipc_log_page *pg = NULL; while (!list_empty(&ilctxt->page_list)) { pg = get_first_page(ilctxt); list_del(&pg->hdr.list); kfree(pg); } kfree(ilctxt); } /* * Destroy debug log context * Loading @@ -865,25 +894,24 @@ EXPORT_SYMBOL(ipc_log_context_create); int ipc_log_context_destroy(void *ctxt) { struct ipc_log_context *ilctxt = (struct ipc_log_context *)ctxt; struct ipc_log_page *pg = NULL; unsigned long flags; if (!ilctxt) return 0; while (!list_empty(&ilctxt->page_list)) { pg = get_first_page(ctxt); list_del(&pg->hdr.list); kfree(pg); } debugfs_remove_recursive(ilctxt->dent); spin_lock(&ilctxt->context_lock_lhb1); ilctxt->destroyed = true; complete_all(&ilctxt->read_avail); spin_unlock(&ilctxt->context_lock_lhb1); write_lock_irqsave(&context_list_lock_lha1, flags); list_del(&ilctxt->list); write_unlock_irqrestore(&context_list_lock_lha1, flags); debugfs_remove_recursive(ilctxt->dent); ipc_log_context_put(ilctxt); kfree(ilctxt); return 0; } EXPORT_SYMBOL(ipc_log_context_destroy); Loading
kernel/trace/ipc_logging_debug.c +25 −6 Original line number Diff line number Diff line /* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. /* Copyright (c) 2012-2015, 2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -74,23 +74,42 @@ static int debug_log(struct ipc_log_context *ilctxt, static ssize_t debug_read_helper(struct file *file, char __user *buff, size_t count, loff_t *ppos, int cont) { struct ipc_log_context *ilctxt = file->private_data; struct ipc_log_context *ilctxt; struct dentry *d = file->f_path.dentry; char *buffer; int bsize; int srcu_idx; int r; r = debugfs_use_file_start(d, &srcu_idx); if (!r) { ilctxt = file->private_data; r = kref_get_unless_zero(&ilctxt->refcount) ? 0 : -EIO; } debugfs_use_file_finish(srcu_idx); if (r) return r; buffer = kmalloc(count, GFP_KERNEL); if (!buffer) return -ENOMEM; if (!buffer) { bsize = -ENOMEM; goto done; } bsize = debug_log(ilctxt, buffer, count, cont); if (bsize > 0) { if (copy_to_user(buff, buffer, bsize)) { bsize = -EFAULT; kfree(buffer); return -EFAULT; goto done; } *ppos += bsize; } kfree(buffer); done: ipc_log_context_put(ilctxt); return bsize; } Loading Loading @@ -127,7 +146,7 @@ static void debug_create(const char *name, mode_t mode, struct ipc_log_context *ilctxt, const struct file_operations *fops) { debugfs_create_file(name, mode, dent, ilctxt, fops); debugfs_create_file_unsafe(name, mode, dent, ilctxt, fops); } static void dfunc_string(struct encode_context *ectxt, Loading
kernel/trace/ipc_logging_private.h +10 −1 Original line number Diff line number Diff line /* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -119,6 +119,8 @@ struct ipc_log_context { struct list_head dfunc_info_list; spinlock_t context_lock_lhb1; struct completion read_avail; struct kref refcount; bool destroyed; }; struct dfunc_info { Loading Loading @@ -147,6 +149,13 @@ enum { ((x) < TSV_TYPE_MSG_END)) #define MAX_MSG_DECODED_SIZE (MAX_MSG_SIZE*4) void ipc_log_context_free(struct kref *kref); static inline void ipc_log_context_put(struct ipc_log_context *ilctxt) { kref_put(&ilctxt->refcount, ipc_log_context_free); } #if (defined(CONFIG_DEBUG_FS)) void check_and_create_debugfs(void); Loading