mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-10-31 08:44:41 +00:00 
			
		
		
		
	 053c095a82
			
		
	
	
		053c095a82
		
	
	
	
	
		
			
			Contrary to common expectations for an "int" return, these functions
return only a positive value -- if used correctly they cannot even
return 0 because the message header will necessarily be in the skb.
This makes the very common pattern of
  if (genlmsg_end(...) < 0) { ... }
be a whole bunch of dead code. Many places also simply do
  return nlmsg_end(...);
and the caller is expected to deal with it.
This also commonly (at least for me) causes errors, because it is very
common to write
  if (my_function(...))
    /* error condition */
and if my_function() does "return nlmsg_end()" this is of course wrong.
Additionally, there's not a single place in the kernel that actually
needs the message length returned, and if anyone needs it later then
it'll be very easy to just use skb->len there.
Remove this, and make the functions void. This removes a bunch of dead
code as described above. The patch adds lines because I did
-	return nlmsg_end(...);
+	nlmsg_end(...);
+	return 0;
I could have preserved all the function's return values by returning
skb->len, but instead I've audited all the places calling the affected
functions and found that none cared. A few places actually compared
the return value with <= 0 in dump functionality, but that could just
be changed to < 0 with no change in behaviour, so I opted for the more
efficient version.
One instance of the error I've made numerous times now is also present
in net/phonet/pn_netlink.c in the route_dumpit() function - it didn't
check for <0 or <=0 and thus broke out of the loop every single time.
I've preserved this since it will (I think) have caused the messages to
userspace to be formatted differently with just a single message for
every SKB returned to userspace. It's possible that this isn't needed
for the tools that actually use this, but I don't even know what they
are so couldn't test that changing this behaviour would be acceptable.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
		
	
			
		
			
				
	
	
		
			183 lines
		
	
	
	
		
			4.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			183 lines
		
	
	
	
		
			4.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * event.c - exporting ACPI events via procfs
 | |
|  *
 | |
|  *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
 | |
|  *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
 | |
|  *
 | |
|  */
 | |
| 
 | |
| #include <linux/spinlock.h>
 | |
| #include <linux/export.h>
 | |
| #include <linux/proc_fs.h>
 | |
| #include <linux/init.h>
 | |
| #include <linux/poll.h>
 | |
| #include <linux/gfp.h>
 | |
| #include <linux/acpi.h>
 | |
| #include <net/netlink.h>
 | |
| #include <net/genetlink.h>
 | |
| 
 | |
| #include "internal.h"
 | |
| 
 | |
| #define _COMPONENT		ACPI_SYSTEM_COMPONENT
 | |
| ACPI_MODULE_NAME("event");
 | |
| 
 | |
| /* ACPI notifier chain */
 | |
| static BLOCKING_NOTIFIER_HEAD(acpi_chain_head);
 | |
| 
 | |
| int acpi_notifier_call_chain(struct acpi_device *dev, u32 type, u32 data)
 | |
| {
 | |
| 	struct acpi_bus_event event;
 | |
| 
 | |
| 	strcpy(event.device_class, dev->pnp.device_class);
 | |
| 	strcpy(event.bus_id, dev->pnp.bus_id);
 | |
| 	event.type = type;
 | |
| 	event.data = data;
 | |
| 	return (blocking_notifier_call_chain(&acpi_chain_head, 0, (void *)&event)
 | |
|                         == NOTIFY_BAD) ? -EINVAL : 0;
 | |
| }
 | |
| EXPORT_SYMBOL(acpi_notifier_call_chain);
 | |
| 
 | |
| int register_acpi_notifier(struct notifier_block *nb)
 | |
| {
 | |
| 	return blocking_notifier_chain_register(&acpi_chain_head, nb);
 | |
| }
 | |
| EXPORT_SYMBOL(register_acpi_notifier);
 | |
| 
 | |
| int unregister_acpi_notifier(struct notifier_block *nb)
 | |
| {
 | |
| 	return blocking_notifier_chain_unregister(&acpi_chain_head, nb);
 | |
| }
 | |
| EXPORT_SYMBOL(unregister_acpi_notifier);
 | |
| 
 | |
| #ifdef CONFIG_NET
 | |
| static unsigned int acpi_event_seqnum;
 | |
| struct acpi_genl_event {
 | |
| 	acpi_device_class device_class;
 | |
| 	char bus_id[15];
 | |
| 	u32 type;
 | |
| 	u32 data;
 | |
| };
 | |
| 
 | |
| /* attributes of acpi_genl_family */
 | |
| enum {
 | |
| 	ACPI_GENL_ATTR_UNSPEC,
 | |
| 	ACPI_GENL_ATTR_EVENT,	/* ACPI event info needed by user space */
 | |
| 	__ACPI_GENL_ATTR_MAX,
 | |
| };
 | |
| #define ACPI_GENL_ATTR_MAX (__ACPI_GENL_ATTR_MAX - 1)
 | |
| 
 | |
| /* commands supported by the acpi_genl_family */
 | |
| enum {
 | |
| 	ACPI_GENL_CMD_UNSPEC,
 | |
| 	ACPI_GENL_CMD_EVENT,	/* kernel->user notifications for ACPI events */
 | |
| 	__ACPI_GENL_CMD_MAX,
 | |
| };
 | |
| #define ACPI_GENL_CMD_MAX (__ACPI_GENL_CMD_MAX - 1)
 | |
| 
 | |
| #define ACPI_GENL_FAMILY_NAME		"acpi_event"
 | |
| #define ACPI_GENL_VERSION		0x01
 | |
| #define ACPI_GENL_MCAST_GROUP_NAME 	"acpi_mc_group"
 | |
| 
 | |
| static const struct genl_multicast_group acpi_event_mcgrps[] = {
 | |
| 	{ .name = ACPI_GENL_MCAST_GROUP_NAME, },
 | |
| };
 | |
| 
 | |
| static struct genl_family acpi_event_genl_family = {
 | |
| 	.id = GENL_ID_GENERATE,
 | |
| 	.name = ACPI_GENL_FAMILY_NAME,
 | |
| 	.version = ACPI_GENL_VERSION,
 | |
| 	.maxattr = ACPI_GENL_ATTR_MAX,
 | |
| 	.mcgrps = acpi_event_mcgrps,
 | |
| 	.n_mcgrps = ARRAY_SIZE(acpi_event_mcgrps),
 | |
| };
 | |
| 
 | |
| int acpi_bus_generate_netlink_event(const char *device_class,
 | |
| 				      const char *bus_id,
 | |
| 				      u8 type, int data)
 | |
| {
 | |
| 	struct sk_buff *skb;
 | |
| 	struct nlattr *attr;
 | |
| 	struct acpi_genl_event *event;
 | |
| 	void *msg_header;
 | |
| 	int size;
 | |
| 
 | |
| 	/* allocate memory */
 | |
| 	size = nla_total_size(sizeof(struct acpi_genl_event)) +
 | |
| 	    nla_total_size(0);
 | |
| 
 | |
| 	skb = genlmsg_new(size, GFP_ATOMIC);
 | |
| 	if (!skb)
 | |
| 		return -ENOMEM;
 | |
| 
 | |
| 	/* add the genetlink message header */
 | |
| 	msg_header = genlmsg_put(skb, 0, acpi_event_seqnum++,
 | |
| 				 &acpi_event_genl_family, 0,
 | |
| 				 ACPI_GENL_CMD_EVENT);
 | |
| 	if (!msg_header) {
 | |
| 		nlmsg_free(skb);
 | |
| 		return -ENOMEM;
 | |
| 	}
 | |
| 
 | |
| 	/* fill the data */
 | |
| 	attr =
 | |
| 	    nla_reserve(skb, ACPI_GENL_ATTR_EVENT,
 | |
| 			sizeof(struct acpi_genl_event));
 | |
| 	if (!attr) {
 | |
| 		nlmsg_free(skb);
 | |
| 		return -EINVAL;
 | |
| 	}
 | |
| 
 | |
| 	event = nla_data(attr);
 | |
| 	memset(event, 0, sizeof(struct acpi_genl_event));
 | |
| 
 | |
| 	strcpy(event->device_class, device_class);
 | |
| 	strcpy(event->bus_id, bus_id);
 | |
| 	event->type = type;
 | |
| 	event->data = data;
 | |
| 
 | |
| 	/* send multicast genetlink message */
 | |
| 	genlmsg_end(skb, msg_header);
 | |
| 
 | |
| 	genlmsg_multicast(&acpi_event_genl_family, skb, 0, 0, GFP_ATOMIC);
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| EXPORT_SYMBOL(acpi_bus_generate_netlink_event);
 | |
| 
 | |
| static int acpi_event_genetlink_init(void)
 | |
| {
 | |
| 	return genl_register_family(&acpi_event_genl_family);
 | |
| }
 | |
| 
 | |
| #else
 | |
| int acpi_bus_generate_netlink_event(const char *device_class,
 | |
| 				      const char *bus_id,
 | |
| 				      u8 type, int data)
 | |
| {
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| EXPORT_SYMBOL(acpi_bus_generate_netlink_event);
 | |
| 
 | |
| static int acpi_event_genetlink_init(void)
 | |
| {
 | |
| 	return -ENODEV;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| static int __init acpi_event_init(void)
 | |
| {
 | |
| 	int error = 0;
 | |
| 
 | |
| 	if (acpi_disabled)
 | |
| 		return 0;
 | |
| 
 | |
| 	/* create genetlink for acpi event */
 | |
| 	error = acpi_event_genetlink_init();
 | |
| 	if (error)
 | |
| 		printk(KERN_WARNING PREFIX
 | |
| 		       "Failed to create genetlink family for ACPI event\n");
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| fs_initcall(acpi_event_init);
 |