drivers/net/bonding/bond_sysfs.c

Source file repositories/reference/linux-study-clean/drivers/net/bonding/bond_sysfs.c

File Facts

System
Linux kernel
Corpus path
drivers/net/bonding/bond_sysfs.c
Extension
.c
Size
24216 bytes
Lines
865
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (res > (PAGE_SIZE - IFNAMSIZ)) {
			/* not enough space for another interface name */
			if ((PAGE_SIZE - res) > 10)
				res = PAGE_SIZE - 10;
			res += sysfs_emit_at(buf, res, "++more++ ");
			break;
		}
		res += sysfs_emit_at(buf, res, "%s ", bond->dev->name);
	}
	if (res)
		buf[res-1] = '\n'; /* eat the leftover space */

	rcu_read_unlock();
	return res;
}

static struct net_device *bond_get_by_name(const struct bond_net *bn, const char *ifname)
{
	struct bonding *bond;

	list_for_each_entry(bond, &bn->dev_list, bond_list) {
		if (strncmp(bond->dev->name, ifname, IFNAMSIZ) == 0)
			return bond->dev;
	}
	return NULL;
}

/* "store" function for the bond_masters attribute.  This is what
 * creates and deletes entire bonds.
 *
 * The class parameter is ignored.
 */
static ssize_t bonding_store_bonds(const struct class *cls,
				   const struct class_attribute *attr,
				   const char *buffer, size_t count)
{
	const struct bond_net *bn =
		container_of_const(attr, struct bond_net, class_attr_bonding_masters);
	char command[IFNAMSIZ + 1] = {0, };
	char *ifname;
	int rv, res = count;

	sscanf(buffer, "%16s", command); /* IFNAMSIZ*/
	ifname = command + 1;
	if ((strlen(command) <= 1) ||
	    !dev_valid_name(ifname))
		goto err_no_cmd;

	if (command[0] == '+') {
		pr_info("%s is being created...\n", ifname);
		rv = bond_create(bn->net, ifname);
		if (rv) {
			if (rv == -EEXIST)
				pr_info("%s already exists\n", ifname);
			else
				pr_info("%s creation failed\n", ifname);
			res = rv;
		}
	} else if (command[0] == '-') {
		struct net_device *bond_dev;

		rtnl_lock();
		bond_dev = bond_get_by_name(bn, ifname);
		if (bond_dev) {
			pr_info("%s is being deleted...\n", ifname);
			unregister_netdevice(bond_dev);
		} else {
			pr_err("unable to delete non-existent %s\n", ifname);
			res = -ENODEV;
		}
		rtnl_unlock();
	} else
		goto err_no_cmd;

	/* Always return either count or an error.  If you return 0, you'll
	 * get called forever, which is bad.
	 */
	return res;

err_no_cmd:
	pr_err("no command found in bonding_masters - use +ifname or -ifname\n");
	return -EPERM;
}

/* class attribute for bond_masters file.  This ends up in /sys/class/net */
static const struct class_attribute class_attr_bonding_masters = {
	.attr = {
		.name = "bonding_masters",
		.mode = 0644,
	},

Annotation

Implementation Notes