fs/afs/volume.c

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

File Facts

System
Linux kernel
Corpus path
fs/afs/volume.c
Extension
.c
Size
12110 bytes
Lines
473
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 (p->vid < volume->vid) {
			pp = &(*pp)->rb_left;
		} else if (p->vid > volume->vid) {
			pp = &(*pp)->rb_right;
		} else {
			if (afs_try_get_volume(p, afs_volume_trace_get_cell_insert)) {
				volume = p;
				goto found;
			}

			set_bit(AFS_VOLUME_RM_TREE, &volume->flags);
			rb_replace_node_rcu(&p->cell_node, &volume->cell_node, &cell->volumes);
		}
	}

	rb_link_node_rcu(&volume->cell_node, parent, pp);
	rb_insert_color(&volume->cell_node, &cell->volumes);
	hlist_add_head_rcu(&volume->proc_link, &cell->proc_volumes);

found:
	write_sequnlock(&cell->volume_lock);
	return volume;

}

static void afs_remove_volume_from_cell(struct afs_volume *volume)
{
	struct afs_cell *cell = volume->cell;

	if (!hlist_unhashed(&volume->proc_link)) {
		trace_afs_volume(volume->debug_id, volume->vid, refcount_read(&volume->ref),
				 afs_volume_trace_remove);
		write_seqlock(&cell->volume_lock);
		hlist_del_rcu(&volume->proc_link);
		if (!test_and_set_bit(AFS_VOLUME_RM_TREE, &volume->flags))
			rb_erase(&volume->cell_node, &cell->volumes);
		write_sequnlock(&cell->volume_lock);
	}
}

/*
 * Allocate a volume record and load it up from a vldb record.
 */
static struct afs_volume *afs_alloc_volume(struct afs_fs_context *params,
					   struct afs_vldb_entry *vldb,
					   struct afs_server_list **_slist)
{
	struct afs_server_list *slist;
	struct afs_volume *volume;
	int ret = -ENOMEM, i;

	volume = kzalloc_obj(struct afs_volume);
	if (!volume)
		goto error_0;

	volume->debug_id	= atomic_inc_return(&afs_volume_debug_id);
	volume->vid		= vldb->vid[params->type];
	volume->update_at	= ktime_get_real_seconds() + afs_volume_record_life;
	volume->cell		= afs_get_cell(params->cell, afs_cell_trace_get_vol);
	volume->type		= params->type;
	volume->type_force	= params->force;
	volume->name_len	= vldb->name_len;
	volume->creation_time	= TIME64_MIN;
	volume->update_time	= TIME64_MIN;

	refcount_set(&volume->ref, 1);
	INIT_HLIST_NODE(&volume->proc_link);
	INIT_WORK(&volume->destructor, afs_destroy_volume);
	rwlock_init(&volume->servers_lock);
	mutex_init(&volume->volsync_lock);
	mutex_init(&volume->cb_check_lock);
	rwlock_init(&volume->cb_v_break_lock);
	INIT_LIST_HEAD(&volume->open_mmaps);
	init_rwsem(&volume->open_mmaps_lock);
	memcpy(volume->name, vldb->name, vldb->name_len + 1);

	for (i = 0; i < AFS_MAXTYPES; i++)
		volume->vids[i] = vldb->vid[i];

	slist = afs_alloc_server_list(volume, params->key, vldb);
	if (IS_ERR(slist)) {
		ret = PTR_ERR(slist);
		goto error_1;
	}

	*_slist = slist;
	rcu_assign_pointer(volume->servers, slist);
	trace_afs_volume(volume->debug_id, volume->vid, 1, afs_volume_trace_alloc);
	return volume;

Annotation

Implementation Notes