fs/afs/vl_list.c

Source file repositories/reference/linux-study-clean/fs/afs/vl_list.c

File Facts

System
Linux kernel
Corpus path
fs/afs/vl_list.c
Extension
.c
Size
8480 bytes
Lines
337
Domain
Core OS
Bucket
VFS And Filesystem Core
Inferred role
Core OS: implementation source
Status
source implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

if (refcount_dec_and_test(&vllist->ref)) {
			int i;

			for (i = 0; i < vllist->nr_servers; i++) {
				afs_put_vlserver(net, vllist->servers[i].server);
			}
			kfree_rcu(vllist, rcu);
		}
	}
}

static u16 afs_extract_le16(const u8 **_b)
{
	u16 val;

	val  = (u16)*(*_b)++ << 0;
	val |= (u16)*(*_b)++ << 8;
	return val;
}

/*
 * Build a VL server address list from a DNS queried server list.
 */
static struct afs_addr_list *afs_extract_vl_addrs(struct afs_net *net,
						  const u8 **_b, const u8 *end,
						  u8 nr_addrs, u16 port)
{
	struct afs_addr_list *alist;
	const u8 *b = *_b;
	int ret = -EINVAL;

	alist = afs_alloc_addrlist(nr_addrs);
	if (!alist)
		return ERR_PTR(-ENOMEM);
	if (nr_addrs == 0)
		return alist;

	for (; nr_addrs > 0 && end - b >= nr_addrs; nr_addrs--) {
		struct dns_server_list_v1_address hdr;
		__be32 x[4];

		hdr.address_type = *b++;

		switch (hdr.address_type) {
		case DNS_ADDRESS_IS_IPV4:
			if (end - b < 4) {
				_leave(" = -EINVAL [short inet]");
				goto error;
			}
			memcpy(x, b, 4);
			ret = afs_merge_fs_addr4(net, alist, x[0], port);
			if (ret < 0)
				goto error;
			b += 4;
			break;

		case DNS_ADDRESS_IS_IPV6:
			if (end - b < 16) {
				_leave(" = -EINVAL [short inet6]");
				goto error;
			}
			memcpy(x, b, 16);
			ret = afs_merge_fs_addr6(net, alist, x, port);
			if (ret < 0)
				goto error;
			b += 16;
			break;

		default:
			_leave(" = -EADDRNOTAVAIL [unknown af %u]",
			       hdr.address_type);
			ret = -EADDRNOTAVAIL;
			goto error;
		}
	}

	/* Start with IPv6 if available. */
	if (alist->nr_ipv4 < alist->nr_addrs)
		alist->preferred = alist->nr_ipv4;

	*_b = b;
	return alist;

error:
	*_b = b;
	afs_put_addrlist(alist, afs_alist_trace_put_parse_error);
	return ERR_PTR(ret);
}

/*

Annotation

Implementation Notes