This patch introduces a bitfield to store sysdata features in the
netconsole_target struct. It also adds configfs helpers to enable
or disable the CPU_NR feature, which populates the CPU number in
sysdata.

The patch provides the necessary infrastructure to set or unset the
CPU_NR feature, but does not modify the message itself.

Signed-off-by: Breno Leitao <lei...@debian.org>
Reviewed-by: Simon Horman <ho...@kernel.org>
---
 drivers/net/netconsole.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 81 insertions(+)

diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index 
15daaba65c8827bf399f0623cc42d310626cbf68..710330ae8ee462083dbb4aa889cb0ba0cb5a7475
 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -97,6 +97,15 @@ struct netconsole_target_stats  {
        struct u64_stats_sync syncp;
 };
 
+/* Features enabled in sysdata. Contrary to userdata, this data is populated by
+ * the kernel. The fields are designed as bitwise flags, allowing multiple
+ * features to be set in sysdata_fields.
+ */
+enum sysdata_feature {
+       /* Populate the CPU that sends the message */
+       CPU_NR = BIT(0),
+};
+
 /**
  * struct netconsole_target - Represents a configured netconsole target.
  * @list:      Links this target into the target_list.
@@ -104,6 +113,7 @@ struct netconsole_target_stats  {
  * @userdata_group:    Links to the userdata configfs hierarchy
  * @extradata_complete:        Cached, formatted string of append
  * @userdata_length:   String length of usedata in extradata_complete.
+ * @sysdata_fields:    Sysdata features enabled.
  * @stats:     Packet send stats for the target. Used for debugging.
  * @enabled:   On / off knob to enable / disable target.
  *             Visible from userspace (read-write).
@@ -132,6 +142,8 @@ struct netconsole_target {
        struct config_group     userdata_group;
        char extradata_complete[MAX_EXTRADATA_ENTRY_LEN * MAX_EXTRADATA_ITEMS];
        size_t                  userdata_length;
+       /* bit-wise with sysdata_feature bits */
+       u32                     sysdata_fields;
 #endif
        struct netconsole_target_stats stats;
        bool                    enabled;
@@ -399,6 +411,19 @@ static ssize_t transmit_errors_show(struct config_item 
*item, char *buf)
        return sysfs_emit(buf, "%llu\n", xmit_drop_count + enomem_count);
 }
 
+/* configfs helper to display if cpu_nr sysdata feature is enabled */
+static ssize_t sysdata_cpu_nr_enabled_show(struct config_item *item, char *buf)
+{
+       struct netconsole_target *nt = to_target(item->ci_parent);
+       bool cpu_nr_enabled;
+
+       mutex_lock(&dynamic_netconsole_mutex);
+       cpu_nr_enabled = !!(nt->sysdata_fields & CPU_NR);
+       mutex_unlock(&dynamic_netconsole_mutex);
+
+       return sysfs_emit(buf, "%d\n", cpu_nr_enabled);
+}
+
 /*
  * This one is special -- targets created through the configfs interface
  * are not enabled (and the corresponding netpoll activated) by default.
@@ -793,7 +818,62 @@ static ssize_t userdatum_value_store(struct config_item 
*item, const char *buf,
        return ret;
 }
 
+/* disable_sysdata_feature - Disable sysdata feature and clean sysdata
+ * @nt: target that is disabling the feature
+ * @feature: feature being disabled
+ */
+static void disable_sysdata_feature(struct netconsole_target *nt,
+                                   enum sysdata_feature feature)
+{
+       nt->sysdata_fields &= ~feature;
+       nt->extradata_complete[nt->userdata_length] = 0;
+}
+
+/* configfs helper to sysdata cpu_nr feature */
+static ssize_t sysdata_cpu_nr_enabled_store(struct config_item *item,
+                                           const char *buf, size_t count)
+{
+       struct netconsole_target *nt = to_target(item->ci_parent);
+       bool cpu_nr_enabled, curr;
+       ssize_t ret;
+
+       ret = kstrtobool(buf, &cpu_nr_enabled);
+       if (ret)
+               return ret;
+
+       mutex_lock(&dynamic_netconsole_mutex);
+       curr = nt->sysdata_fields & CPU_NR;
+       if (cpu_nr_enabled == curr)
+               /* no change requested */
+               goto unlock_ok;
+
+       if (cpu_nr_enabled &&
+           count_extradata_entries(nt) >= MAX_EXTRADATA_ITEMS) {
+               /* user wants the new feature, but there is no space in the
+                * buffer.
+                */
+               ret = -ENOSPC;
+               goto unlock;
+       }
+
+       if (cpu_nr_enabled)
+               nt->sysdata_fields |= CPU_NR;
+       else
+               /* This is special because extradata_complete might have
+                * remaining data from previous sysdata, and it needs to be
+                * cleaned.
+                */
+               disable_sysdata_feature(nt, CPU_NR);
+
+unlock_ok:
+       ret = strnlen(buf, count);
+unlock:
+       mutex_unlock(&dynamic_netconsole_mutex);
+       return ret;
+}
+
 CONFIGFS_ATTR(userdatum_, value);
+CONFIGFS_ATTR(sysdata_, cpu_nr_enabled);
 
 static struct configfs_attribute *userdatum_attrs[] = {
        &userdatum_attr_value,
@@ -853,6 +933,7 @@ static void userdatum_drop(struct config_group *group, 
struct config_item *item)
 }
 
 static struct configfs_attribute *userdata_attrs[] = {
+       &sysdata_attr_cpu_nr_enabled,
        NULL,
 };
 

-- 
2.43.5


Reply via email to