fs/afs/vl_rotate.c

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

File Facts

System
Linux kernel
Corpus path
fs/afs/vl_rotate.c
Extension
.c
Size
11015 bytes
Lines
400
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 (cell->dns_source == DNS_RECORD_UNAVAILABLE) {
			if (wait_var_event_interruptible(
				    &cell->dns_lookup_count,
				    smp_load_acquire(&cell->dns_lookup_count)
				    != dns_lookup_count) < 0) {
				vc->cumul_error.error = -ERESTARTSYS;
				return false;
			}
		}

		/* Status load is ordered after lookup counter load */
		if (cell->dns_status == DNS_LOOKUP_GOT_NOT_FOUND) {
			pr_warn("No record of cell %s\n", cell->name);
			vc->cumul_error.error = -ENOENT;
			return false;
		}

		if (cell->dns_source == DNS_RECORD_UNAVAILABLE) {
			vc->cumul_error.error = -EDESTADDRREQ;
			return false;
		}
	}

	read_lock(&cell->vl_servers_lock);
	vc->server_list = afs_get_vlserverlist(
		rcu_dereference_protected(cell->vl_servers,
					  lockdep_is_held(&cell->vl_servers_lock)));
	read_unlock(&cell->vl_servers_lock);
	if (!vc->server_list->nr_servers)
		return false;

	vc->untried_servers = (1UL << vc->server_list->nr_servers) - 1;
	vc->server_index = -1;
	return true;
}

/*
 * Select the vlserver to use.  May be called multiple times to rotate
 * through the vlservers.
 */
bool afs_select_vlserver(struct afs_vl_cursor *vc)
{
	struct afs_addr_list *alist = vc->alist;
	struct afs_vlserver *vlserver;
	unsigned long set, failed;
	unsigned int rtt;
	s32 abort_code = vc->call_abort_code;
	int error = vc->call_error, i;

	vc->nr_iterations++;

	_enter("VC=%x+%x,%d{%lx},%d{%lx},%d,%d",
	       vc->debug_id, vc->nr_iterations, vc->server_index, vc->untried_servers,
	       vc->addr_index, vc->addr_tried,
	       error, abort_code);

	if (vc->flags & AFS_VL_CURSOR_STOP) {
		_leave(" = f [stopped]");
		return false;
	}

	if (vc->nr_iterations == 0)
		goto start;

	WRITE_ONCE(alist->addrs[vc->addr_index].last_error, error);

	/* Evaluate the result of the previous operation, if there was one. */
	switch (error) {
	default:
	case 0:
		/* Success or local failure.  Stop. */
		vc->cumul_error.error = error;
		vc->flags |= AFS_VL_CURSOR_STOP;
		_leave(" = f [okay/local %d]", vc->cumul_error.error);
		return false;

	case -ECONNABORTED:
		/* The far side rejected the operation on some grounds.  This
		 * might involve the server being busy or the volume having been moved.
		 */
		switch (abort_code) {
		case AFSVL_IO:
		case AFSVL_BADVOLOPER:
		case AFSVL_NOMEM:
			/* The server went weird. */
			afs_prioritise_error(&vc->cumul_error, -EREMOTEIO, abort_code);
			//write_lock(&vc->cell->vl_servers_lock);
			//vc->server_list->weird_mask |= 1 << vc->server_index;
			//write_unlock(&vc->cell->vl_servers_lock);
			goto next_server;

Annotation

Implementation Notes