Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 15b8d65f authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "trace: ipc_logging: Release the debugfs SRCU when reading"

parents abb28e66 802d738a
Loading
Loading
Loading
Loading
+39 −11
Original line number Diff line number Diff line
@@ -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;
@@ -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);
@@ -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);

@@ -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 */
@@ -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
 *
@@ -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);
+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
@@ -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;
}

@@ -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,
+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
@@ -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 {
@@ -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);