[Skiboot] [PATCH V7 08/12] errorlog: Introduce get and put elog routine and reference count field in elog structure

Mukesh Ojha mukesh02 at linux.vnet.ibm.com
Wed Sep 7 20:21:22 AEST 2016


Our aim is to send the error log to both BMC and PowerNV host. To meet this
purpose we can have a way where we can keep a separate buffer for BMC and
PowerNV host. But with this way we have a overhead of again memory creation,
copy and freeing it buffer separately.

So, better to use existing allocation and deallocation from the pool of
error log object technique with the introduction of reference count
variable in the error log structure. Reference count variable is to
track the number of users using the error log buffer.

The reason of introducing reference count variable is while we send
error log buffer to both BMC and PowerNV host, one of them does not
free the buffer once they are done sending, while the other is using
it.

'get_elog' and 'put_elog' routine to increment/decrement the reference count
variable. Error log buffer object is returned to the pool on zero value of
reference count.

Signed-off-by: Mukesh Ojha <mukesh02 at linux.vnet.ibm.com>
---
Changes in V7:
 - Patch description changed.
 - Subject tag changed from opal/errorlog to errorlog.

Changes in V6:
 - Rebased on master.

Changes in V5:
 - Added more description

Changes in V4:
 - Changes are rebased on master.

Changes in V3:
 - Change in the description.
 - Improves the error message as per review comment.

Changes in V2:
 - Separates it from patch 3/3 from V1.

 core/errorlog.c    | 34 +++++++++++++++++++++++++++++++---
 include/errorlog.h |  3 +++
 2 files changed, 34 insertions(+), 3 deletions(-)

diff --git a/core/errorlog.c b/core/errorlog.c
index da01b58..e778eae 100644
--- a/core/errorlog.c
+++ b/core/errorlog.c
@@ -40,6 +40,7 @@ static uint32_t sapphire_elog_id = 0xB0000000;
 /* Pool to allocate elog messages from */
 static struct pool elog_pool;
 static struct lock elog_lock = LOCK_UNLOCKED;
+static struct lock elog_buf_ref_lock = LOCK_UNLOCKED;
 
 static bool elog_available = false;
 static bool elog_enabled = false;
@@ -55,6 +56,32 @@ static struct lock elog_write_to_host_lock = LOCK_UNLOCKED;
 /* Manipulate this only with write_lock held */
 static enum elog_head_state elog_write_to_host_head_state = ELOG_STATE_NONE;
 
+static void put_elog(struct errorlog *elog_buf)
+{
+	lock(&elog_buf_ref_lock);
+	if (!elog_buf->ref_count) {
+		prerror("put_elog has been called with ref_count 0\n");
+		unlock(&elog_buf_ref_lock);
+		return;
+	}
+
+	elog_buf->ref_count--;
+	unlock(&elog_buf_ref_lock);
+
+        if (!elog_buf->ref_count) {
+                lock(&elog_lock);
+                pool_free_object(&elog_pool, elog_buf);
+                unlock(&elog_lock);
+        }
+}
+
+void get_elog(struct errorlog *elog_buf)
+{
+	lock(&elog_buf_ref_lock);
+	elog_buf->ref_count++;
+	unlock(&elog_buf_ref_lock);
+}
+
 static struct errorlog *get_write_buffer(int opal_event_severity)
 {
 	struct errorlog *buf;
@@ -130,9 +157,7 @@ void opal_elog_complete(struct errorlog *buf, bool success)
 	if (!success)
 		printf("Unable to log error\n");
 
-	lock(&elog_lock);
-	pool_free_object(&elog_pool, buf);
-	unlock(&elog_lock);
+	put_elog(buf);
 }
 
 void log_commit(struct errorlog *elog)
@@ -142,6 +167,9 @@ void log_commit(struct errorlog *elog)
 	if (!elog)
 		return;
 
+	/* Increments the number of users using error log buffer */
+	get_elog(elog);
+
 	if (platform.elog_commit) {
 		rc = platform.elog_commit(elog);
 		if (rc)
diff --git a/include/errorlog.h b/include/errorlog.h
index 3225e49..fa9d4a1 100644
--- a/include/errorlog.h
+++ b/include/errorlog.h
@@ -137,6 +137,7 @@ struct __attribute__((__packed__)) errorlog {
 	uint32_t plid;
 	uint32_t log_size;
 	uint64_t elog_timeout;
+	uint32_t ref_count;
 
 	char user_data_dump[OPAL_LOG_MAX_DUMP];
 	struct list_node link;
@@ -377,4 +378,6 @@ void opal_elog_init(void);
 int elog_init(void);
 void elog_append_write_to_host(struct errorlog *buf);
 void elog_set_head_state(bool opal_logs, enum elog_head_state state);
+
+void get_elog(struct errorlog *elog_buf);
 #endif /* __ERRORLOG_H */
-- 
2.7.4



More information about the Skiboot mailing list