fs/netfs/fscache_cache.c

Source file repositories/reference/linux-study-clean/fs/netfs/fscache_cache.c

File Facts

System
Linux kernel
Corpus path
fs/netfs/fscache_cache.c
Extension
.c
Size
12429 bytes
Lines
430
Domain
Core OS
Bucket
VFS And Filesystem Core
Inferred role
Core OS: exported/initcall integration point
Status
integration 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 (name) {
			cache->name = kstrdup(name, GFP_KERNEL);
			if (!cache->name) {
				kfree(cache);
				return NULL;
			}
		}
		refcount_set(&cache->ref, 1);
		INIT_LIST_HEAD(&cache->cache_link);
		cache->debug_id = atomic_inc_return(&fscache_cache_debug_id);
	}
	return cache;
}

static bool fscache_get_cache_maybe(struct fscache_cache *cache,
				    enum fscache_cache_trace where)
{
	bool success;
	int ref;

	success = __refcount_inc_not_zero(&cache->ref, &ref);
	if (success)
		trace_fscache_cache(cache->debug_id, ref + 1, where);
	return success;
}

/*
 * Look up a cache cookie.
 */
struct fscache_cache *fscache_lookup_cache(const char *name, bool is_cache)
{
	struct fscache_cache *candidate, *cache, *unnamed = NULL;

	/* firstly check for the existence of the cache under read lock */
	down_read(&fscache_addremove_sem);

	list_for_each_entry(cache, &fscache_caches, cache_link) {
		if (cache->name && name && strcmp(cache->name, name) == 0 &&
		    fscache_get_cache_maybe(cache, fscache_cache_get_acquire))
			goto got_cache_r;
		if (!cache->name && !name &&
		    fscache_get_cache_maybe(cache, fscache_cache_get_acquire))
			goto got_cache_r;
	}

	if (!name) {
		list_for_each_entry(cache, &fscache_caches, cache_link) {
			if (cache->name &&
			    fscache_get_cache_maybe(cache, fscache_cache_get_acquire))
				goto got_cache_r;
		}
	}

	up_read(&fscache_addremove_sem);

	/* the cache does not exist - create a candidate */
	candidate = fscache_alloc_cache(name);
	if (!candidate)
		return ERR_PTR(-ENOMEM);

	/* write lock, search again and add if still not present */
	down_write(&fscache_addremove_sem);

	list_for_each_entry(cache, &fscache_caches, cache_link) {
		if (cache->name && name && strcmp(cache->name, name) == 0 &&
		    fscache_get_cache_maybe(cache, fscache_cache_get_acquire))
			goto got_cache_w;
		if (!cache->name) {
			unnamed = cache;
			if (!name &&
			    fscache_get_cache_maybe(cache, fscache_cache_get_acquire))
				goto got_cache_w;
		}
	}

	if (unnamed && is_cache &&
	    fscache_get_cache_maybe(unnamed, fscache_cache_get_acquire))
		goto use_unnamed_cache;

	if (!name) {
		list_for_each_entry(cache, &fscache_caches, cache_link) {
			if (cache->name &&
			    fscache_get_cache_maybe(cache, fscache_cache_get_acquire))
				goto got_cache_w;
		}
	}

	list_add_tail(&candidate->cache_link, &fscache_caches);
	trace_fscache_cache(candidate->debug_id,
			    refcount_read(&candidate->ref),

Annotation

Implementation Notes