All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 1/4] ipmi: msghandler: Add a limit for the number of users
       [not found] <20220329161242.76457-1-chen.chenchacha@foxmail.com>
@ 2022-03-29 16:12 ` Chen Guanqiao
  2022-03-29 16:12 ` [PATCH v2 2/4] ipmi: msghandler: Add a limit for the number of messages Chen Guanqiao
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 4+ messages in thread
From: Chen Guanqiao @ 2022-03-29 16:12 UTC (permalink / raw)
  To: minyard, openipmi-developer, linux-kernel; +Cc: Chen Guanqiao

The administrator sets the limit for the number of users by modifying
/sys/module/ipmi_msghandler/parameters/default_max_users.

Signed-off-by: Chen Guanqiao <chen.chenchacha@foxmail.com>
---
 drivers/char/ipmi/ipmi_msghandler.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index c59265146e9c..7886c8337368 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -145,6 +145,12 @@ module_param(default_max_retries, uint, 0644);
 MODULE_PARM_DESC(default_max_retries,
 		 "The time (milliseconds) between retry sends in maintenance mode");

+/* The default maximum number of users per intf */
+static unsigned int default_max_users = 50;
+module_param(default_max_users, uint, 0644);
+MODULE_PARM_DESC(default_max_users,
+		 "The maximum number of users per interface");
+
 /* Call every ~1000 ms. */
 #define IPMI_TIMEOUT_TIME	1000

@@ -579,6 +585,9 @@ struct ipmi_smi {

 	atomic_t stats[IPMI_NUM_STATS];

+	/* The number of user in this interface */
+	atomic_t user_count;
+
 	/*
 	 * run_to_completion duplicate of smb_info, smi_info
 	 * and ipmi_serial_info structures. Used to decrease numbers of
@@ -1182,9 +1191,11 @@ static void free_user_work(struct work_struct *work)
 {
 	struct ipmi_user *user = container_of(work, struct ipmi_user,
 					      remove_work);
+	struct ipmi_smi *intf = user->intf;

 	cleanup_srcu_struct(&user->release_barrier);
 	vfree(user);
+	atomic_dec(&intf->user_count);
 }

 int ipmi_create_user(unsigned int          if_num,
@@ -1230,6 +1241,12 @@ int ipmi_create_user(unsigned int          if_num,
 	goto out_kfree;

  found:
+	if (atomic_inc_return(&intf->user_count) > default_max_users) {
+		atomic_dec(&intf->user_count);
+		rv = -EBUSY;
+		goto out_kfree;
+	}
+
 	INIT_WORK(&new_user->remove_work, free_user_work);

 	rv = init_srcu_struct(&new_user->release_barrier);
@@ -3548,6 +3565,7 @@ int ipmi_add_smi(struct module         *owner,
 	spin_lock_init(&intf->events_lock);
 	spin_lock_init(&intf->watch_lock);
 	atomic_set(&intf->event_waiters, 0);
+	atomic_set(&intf->user_count, 0);
 	intf->ticks_to_req_ev = IPMI_REQUEST_EV_TIME;
 	INIT_LIST_HEAD(&intf->waiting_events);
 	intf->waiting_events_count = 0;
--
2.25.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH v2 2/4] ipmi: msghandler: Add a limit for the number of messages
       [not found] <20220329161242.76457-1-chen.chenchacha@foxmail.com>
  2022-03-29 16:12 ` [PATCH v2 1/4] ipmi: msghandler: Add a limit for the number of users Chen Guanqiao
@ 2022-03-29 16:12 ` Chen Guanqiao
  2022-03-29 16:12 ` [PATCH v2 3/4] ipmi: msghandler: Get the number of users and messages through sysfs Chen Guanqiao
  2022-03-29 16:12 ` [PATCH v2 4/4] ipmi: msghandler: Add a interface to clean message queue in sysfs Chen Guanqiao
  3 siblings, 0 replies; 4+ messages in thread
From: Chen Guanqiao @ 2022-03-29 16:12 UTC (permalink / raw)
  To: minyard, openipmi-developer, linux-kernel; +Cc: Chen Guanqiao

The administrator sets the limit for the number of messages by modifying
/sys/module/ipmi_msghandler/parameters/default_max_msgs.

Before create a message, count the number of outstanding messages, if
the number reaches the limit, it will return a busy.

Signed-off-by: Chen Guanqiao <chen.chenchacha@foxmail.com>
---
 drivers/char/ipmi/ipmi_msghandler.c | 37 +++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)

diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index 7886c8337368..80ab88702c5f 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -151,6 +151,12 @@ module_param(default_max_users, uint, 0644);
 MODULE_PARM_DESC(default_max_users,
 		 "The maximum number of users per interface");

+/* The default maximum number of outstanding messages per intf */
+static unsigned int default_max_messages = 100;
+module_param(default_max_messages, uint, 0644);
+MODULE_PARM_DESC(default_max_messages,
+		 "The maximum number of outstanding messages per interface");
+
 /* Call every ~1000 ms. */
 #define IPMI_TIMEOUT_TIME	1000

@@ -916,6 +922,30 @@ unsigned int ipmi_addr_length(int addr_type)
 }
 EXPORT_SYMBOL(ipmi_addr_length);

+static void intf_msg_count(struct ipmi_smi *intf,
+			   unsigned int *hp_count, unsigned int *count)
+{
+	struct ipmi_smi_msg *msg;
+	unsigned long flags;
+	int hp_msg_count = 0, msg_count = 0;
+	int run_to_completion = intf->run_to_completion;
+
+	if (!run_to_completion)
+		spin_lock_irqsave(&intf->xmit_msgs_lock, flags);
+	if (!intf->in_shutdown) {
+		list_for_each_entry(msg, &intf->hp_xmit_msgs, link)
+			hp_msg_count++;
+
+		list_for_each_entry(msg, &intf->xmit_msgs, link)
+			msg_count++;
+	}
+	if (!run_to_completion)
+		spin_unlock_irqrestore(&intf->xmit_msgs_lock, flags);
+
+	*hp_count = hp_msg_count;
+	*count = msg_count;
+}
+
 static int deliver_response(struct ipmi_smi *intf, struct ipmi_recv_msg *msg)
 {
 	int rv = 0;
@@ -2299,6 +2329,7 @@ static int i_ipmi_request(struct ipmi_user     *user,
 {
 	struct ipmi_smi_msg *smi_msg;
 	struct ipmi_recv_msg *recv_msg;
+	unsigned hp_msg_count, msg_count;
 	int rv = 0;

 	if (supplied_recv)
@@ -2330,6 +2361,12 @@ static int i_ipmi_request(struct ipmi_user     *user,
 		goto out_err;
 	}

+	intf_msg_count(intf, &hp_msg_count, &msg_count);
+	if ((hp_msg_count + msg_count) > default_max_messages) {
+		rv = -EBUSY;
+		goto out_err;
+	}
+
 	recv_msg->user = user;
 	if (user)
 		/* The put happens when the message is freed. */
--
2.25.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH v2 3/4] ipmi: msghandler: Get the number of users and messages through sysfs
       [not found] <20220329161242.76457-1-chen.chenchacha@foxmail.com>
  2022-03-29 16:12 ` [PATCH v2 1/4] ipmi: msghandler: Add a limit for the number of users Chen Guanqiao
  2022-03-29 16:12 ` [PATCH v2 2/4] ipmi: msghandler: Add a limit for the number of messages Chen Guanqiao
@ 2022-03-29 16:12 ` Chen Guanqiao
  2022-03-29 16:12 ` [PATCH v2 4/4] ipmi: msghandler: Add a interface to clean message queue in sysfs Chen Guanqiao
  3 siblings, 0 replies; 4+ messages in thread
From: Chen Guanqiao @ 2022-03-29 16:12 UTC (permalink / raw)
  To: minyard, openipmi-developer, linux-kernel; +Cc: Chen Guanqiao

The administrator reads the user_count and msg_count file
corresponding the ipmi device, ipmi traverse all intf, and count
the number of users and messages.

Signed-off-by: Chen Guanqiao <chen.chenchacha@foxmail.com>
---
 drivers/char/ipmi/ipmi_msghandler.c | 71 +++++++++++++++++++++++++++++
 1 file changed, 71 insertions(+)

diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index 80ab88702c5f..a188dc7e7135 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -922,6 +922,19 @@ unsigned int ipmi_addr_length(int addr_type)
 }
 EXPORT_SYMBOL(ipmi_addr_length);

+static unsigned int intf_user_count(struct ipmi_smi *intf)
+{
+	struct ipmi_user *user;
+	int index, count = 0;
+
+	index = srcu_read_lock(&intf->users_srcu);
+	list_for_each_entry_rcu(user, &intf->users, link)
+		count++;
+	srcu_read_unlock(&intf->users_srcu, index);
+
+	return count;
+}
+
 static void intf_msg_count(struct ipmi_smi *intf,
 			   unsigned int *hp_count, unsigned int *count)
 {
@@ -2760,6 +2773,42 @@ static int bmc_get_device_id(struct ipmi_smi *intf, struct bmc_device *bmc,
 	return __bmc_get_device_id(intf, bmc, id, guid_set, guid, -1);
 }

+static unsigned int get_user_count(void)
+{
+	struct ipmi_smi *intf;
+	int index;
+	unsigned int count = 0;
+
+	index = srcu_read_lock(&ipmi_interfaces_srcu);
+	list_for_each_entry_rcu(intf, &ipmi_interfaces, link)
+		count += intf_user_count(intf);
+	srcu_read_unlock(&ipmi_interfaces_srcu, index);
+
+	return count;
+}
+
+static void get_msg_count(unsigned int *hp_count, unsigned int *count)
+{
+	struct ipmi_smi *intf;
+	int index;
+
+	*hp_count = 0;
+	*count = 0;
+
+	index = srcu_read_lock(&ipmi_interfaces_srcu);
+	list_for_each_entry_rcu(intf, &ipmi_interfaces, link) {
+		int hp_msg_count = 0, msg_count = 0;
+
+		rcu_read_lock();
+		intf_msg_count(intf, &hp_msg_count, &msg_count);
+		rcu_read_unlock();
+
+		*hp_count += hp_msg_count;
+		*count += msg_count;
+	}
+	srcu_read_unlock(&ipmi_interfaces_srcu, index);
+}
+
 static ssize_t device_id_show(struct device *dev,
 			      struct device_attribute *attr,
 			      char *buf)
@@ -2929,6 +2978,26 @@ static ssize_t guid_show(struct device *dev, struct device_attribute *attr,
 }
 static DEVICE_ATTR_RO(guid);

+static ssize_t user_count_show(struct device *dev, struct device_attribute *attr,
+			       char *buf)
+{
+	unsigned int user_count = get_user_count();
+
+	return snprintf(buf, 20, "%u\n", user_count);
+}
+static DEVICE_ATTR_ADMIN_RO(user_count);
+
+static ssize_t msg_count_show(struct device *dev, struct device_attribute *attr,
+			      char *buf)
+{
+	unsigned int hp_count, count;
+
+	get_msg_count(&hp_count, &count);
+
+	return snprintf(buf, 40, "hp msg:%u, msg:%u\n", hp_count, count);
+}
+static DEVICE_ATTR_ADMIN_RO(msg_count);
+
 static struct attribute *bmc_dev_attrs[] = {
 	&dev_attr_device_id.attr,
 	&dev_attr_provides_device_sdrs.attr,
@@ -2940,6 +3009,8 @@ static struct attribute *bmc_dev_attrs[] = {
 	&dev_attr_product_id.attr,
 	&dev_attr_aux_firmware_revision.attr,
 	&dev_attr_guid.attr,
+	&dev_attr_user_count.attr,
+	&dev_attr_msg_count.attr,
 	NULL
 };

--
2.25.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH v2 4/4] ipmi: msghandler: Add a interface to clean message queue in sysfs
       [not found] <20220329161242.76457-1-chen.chenchacha@foxmail.com>
                   ` (2 preceding siblings ...)
  2022-03-29 16:12 ` [PATCH v2 3/4] ipmi: msghandler: Get the number of users and messages through sysfs Chen Guanqiao
@ 2022-03-29 16:12 ` Chen Guanqiao
  3 siblings, 0 replies; 4+ messages in thread
From: Chen Guanqiao @ 2022-03-29 16:12 UTC (permalink / raw)
  To: minyard, openipmi-developer, linux-kernel; +Cc: Chen Guanqiao

The further approach, add a cleanup interface in sysfs. The administrator write
'1' to clean_msg, and ipmi clear the entire message queue.

Signed-off-by: Chen Guanqiao <chen.chenchacha@foxmail.com>
---
 drivers/char/ipmi/ipmi_msghandler.c | 81 +++++++++++++++++++++++++++++
 1 file changed, 81 insertions(+)

diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index a188dc7e7135..58f3e17ee6b2 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -46,6 +46,9 @@ static void handle_new_recv_msgs(struct ipmi_smi *intf);
 static void need_waiter(struct ipmi_smi *intf);
 static int handle_one_recv_msg(struct ipmi_smi *intf,
 			       struct ipmi_smi_msg *msg);
+static void deliver_smi_err_response(struct ipmi_smi *intf,
+				     struct ipmi_smi_msg *msg,
+				     unsigned char err);

 static bool initialized;
 static bool drvregistered;
@@ -2809,6 +2812,70 @@ static void get_msg_count(unsigned int *hp_count, unsigned int *count)
 	srcu_read_unlock(&ipmi_interfaces_srcu, index);
 }

+static void __cleanup_msgs_queue(struct ipmi_smi *intf)
+{
+	int i;
+	unsigned long flags;
+	int run_to_completion = intf->run_to_completion;
+
+	rcu_read_lock();
+	if (!run_to_completion)
+		spin_lock_irqsave(&intf->xmit_msgs_lock, flags);
+	if (!intf->in_shutdown) {
+		struct ipmi_smi_msg *msg;
+		struct list_head *entry = NULL;
+
+		while (!list_empty(&intf->xmit_msgs)) {
+			if (!list_empty(&intf->hp_xmit_msgs))
+				entry = intf->hp_xmit_msgs.next;
+			else if (!list_empty(&intf->xmit_msgs))
+				entry = intf->xmit_msgs.next;
+
+			if (!entry)
+				continue;
+
+			list_del(entry);
+			msg = list_entry(entry, struct ipmi_smi_msg, link);
+			deliver_smi_err_response(intf, msg,
+						 IPMI_ERR_UNSPECIFIED);
+		}
+	}
+	if (!run_to_completion)
+		spin_unlock_irqrestore(&intf->xmit_msgs_lock, flags);
+	rcu_read_unlock();
+
+	spin_lock_irqsave(&intf->seq_lock, flags);
+	for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++) {
+		struct seq_table *ent = &intf->seq_table[i];
+		if (!ent->inuse)
+			continue;
+		deliver_err_response(intf, ent->recv_msg, IPMI_ERR_UNSPECIFIED);
+	}
+	spin_unlock_irqrestore(&intf->seq_lock, flags);
+}
+
+static void cleanup_msgs_queue(void)
+{
+	struct ipmi_smi *intf;
+	int index;
+
+	index = srcu_read_lock(&ipmi_interfaces_srcu);
+	list_for_each_entry_rcu(intf, &ipmi_interfaces, link) {
+		struct bmc_device *bmc = intf->bmc;
+
+		kref_get(&intf->refcount);
+		mutex_lock(&intf->bmc_reg_mutex);
+		mutex_lock(&bmc->dyn_mutex);
+
+		__cleanup_msgs_queue(intf);
+
+		mutex_unlock(&bmc->dyn_mutex);
+		mutex_unlock(&intf->bmc_reg_mutex);
+		kref_put(&intf->refcount, intf_free);
+	}
+	srcu_read_unlock(&ipmi_interfaces_srcu, index);
+}
+
 static ssize_t device_id_show(struct device *dev,
 			      struct device_attribute *attr,
 			      char *buf)
@@ -2998,6 +3065,19 @@ static ssize_t msg_count_show(struct device *dev, struct device_attribute *attr,
 }
 static DEVICE_ATTR_ADMIN_RO(msg_count);

+static ssize_t clean_msgs_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	if (!sysfs_streq(buf, "1"))
+		return -EINVAL;
+
+	cleanup_msgs_queue();
+
+	return count;
+}
+static DEVICE_ATTR_WO(clean_msgs);
+
 static struct attribute *bmc_dev_attrs[] = {
 	&dev_attr_device_id.attr,
 	&dev_attr_provides_device_sdrs.attr,
@@ -3011,6 +3091,7 @@ static struct attribute *bmc_dev_attrs[] = {
 	&dev_attr_guid.attr,
 	&dev_attr_user_count.attr,
 	&dev_attr_msg_count.attr,
+	&dev_attr_clean_msgs.attr,
 	NULL
 };

--
2.25.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2022-03-29 16:13 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <20220329161242.76457-1-chen.chenchacha@foxmail.com>
2022-03-29 16:12 ` [PATCH v2 1/4] ipmi: msghandler: Add a limit for the number of users Chen Guanqiao
2022-03-29 16:12 ` [PATCH v2 2/4] ipmi: msghandler: Add a limit for the number of messages Chen Guanqiao
2022-03-29 16:12 ` [PATCH v2 3/4] ipmi: msghandler: Get the number of users and messages through sysfs Chen Guanqiao
2022-03-29 16:12 ` [PATCH v2 4/4] ipmi: msghandler: Add a interface to clean message queue in sysfs Chen Guanqiao

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.