fs/afs/cell.c

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

File Facts

System
Linux kernel
Corpus path
fs/afs/cell.c
Extension
.c
Size
23244 bytes
Lines
925
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 (IS_ERR(vllist)) {
			ret = PTR_ERR(vllist);
			vllist = NULL;
			goto parse_failed;
		}

		vllist->source = DNS_RECORD_FROM_CONFIG;
		vllist->status = DNS_LOOKUP_NOT_DONE;
		cell->dns_expiry = TIME64_MAX;
	} else {
		ret = -ENOMEM;
		vllist = afs_alloc_vlserver_list(0);
		if (!vllist)
			goto error;
		vllist->source = DNS_RECORD_UNAVAILABLE;
		vllist->status = DNS_LOOKUP_NOT_DONE;
		cell->dns_expiry = ktime_get_real_seconds();
	}

	rcu_assign_pointer(cell->vl_servers, vllist);

	cell->dns_source = vllist->source;
	cell->dns_status = vllist->status;
	smp_store_release(&cell->dns_lookup_count, 1); /* vs source/status */
	atomic_inc(&net->cells_outstanding);
	ret = idr_alloc_cyclic(&net->cells_dyn_ino, cell,
			       2, INT_MAX / 2, GFP_KERNEL);
	if (ret < 0)
		goto error;
	cell->dynroot_ino = ret;
	cell->debug_id = atomic_inc_return(&cell_debug_id);

	trace_afs_cell(cell->debug_id, 1, 0, afs_cell_trace_alloc);

	_leave(" = %p", cell);
	return cell;

parse_failed:
	if (ret == -EINVAL)
		printk(KERN_ERR "kAFS: bad VL server IP address\n");
error:
	afs_put_vlserverlist(cell->net, vllist);
	kfree(cell->name - 1);
	kfree(cell);
	_leave(" = %d", ret);
	return ERR_PTR(ret);
}

/*
 * afs_lookup_cell - Look up or create a cell record.
 * @net:	The network namespace
 * @name:	The name of the cell.
 * @namesz:	The strlen of the cell name.
 * @vllist:	A colon/comma separated list of numeric IP addresses or NULL.
 * @reason:	The reason we're doing the lookup
 * @trace:	The reason to be logged if the lookup is successful.
 *
 * Look up a cell record by name and query the DNS for VL server addresses if
 * needed.  Note that that actual DNS query is punted off to the manager thread
 * so that this function can return immediately if interrupted whilst allowing
 * cell records to be shared even if not yet fully constructed.
 */
struct afs_cell *afs_lookup_cell(struct afs_net *net,
				 const char *name, unsigned int namesz,
				 const char *vllist,
				 enum afs_lookup_cell_for reason,
				 enum afs_cell_trace trace)
{
	struct afs_cell *cell, *candidate, *cursor;
	struct rb_node *parent, **pp;
	enum afs_cell_state state;
	int ret, n;

	_enter("%s,%s,%u", name, vllist, reason);

	if (reason != AFS_LOOKUP_CELL_PRELOAD) {
		cell = afs_find_cell(net, name, namesz, trace);
		if (!IS_ERR(cell)) {
			if (reason == AFS_LOOKUP_CELL_DYNROOT)
				goto no_wait;
			if (cell->state == AFS_CELL_SETTING_UP ||
			    cell->state == AFS_CELL_UNLOOKED)
				goto lookup_cell;
			goto wait_for_cell;
		}
	}

	/* Assume we're probably going to create a cell and preallocate and
	 * mostly set up a candidate record.  We can then use this to stash the
	 * name, the net namespace and VL server addresses.

Annotation

Implementation Notes