fs/erofs/zutil.c

Source file repositories/reference/linux-study-clean/fs/erofs/zutil.c

File Facts

System
Linux kernel
Corpus path
fs/erofs/zutil.c
Extension
.c
Size
7660 bytes
Lines
317
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

struct z_erofs_gbuf {
	spinlock_t lock;
	void *ptr;
	struct page **pages;
	unsigned int nrpages;
};

static struct z_erofs_gbuf *z_erofs_gbufpool, *z_erofs_rsvbuf;
static unsigned int z_erofs_gbuf_count, z_erofs_gbuf_nrpages,
		z_erofs_rsv_nrpages;

module_param_named(global_buffers, z_erofs_gbuf_count, uint, 0444);
module_param_named(reserved_pages, z_erofs_rsv_nrpages, uint, 0444);

atomic_long_t erofs_global_shrink_cnt;	/* for all mounted instances */

/* protects `erofs_sb_list_lock` and the mounted `erofs_sb_list` */
static DEFINE_SPINLOCK(erofs_sb_list_lock);
static LIST_HEAD(erofs_sb_list);
static unsigned int shrinker_run_no;
static struct shrinker *erofs_shrinker_info;

static unsigned int z_erofs_gbuf_id(void)
{
	return raw_smp_processor_id() % z_erofs_gbuf_count;
}

void *z_erofs_get_gbuf(unsigned int requiredpages)
	__acquires(gbuf->lock)
{
	struct z_erofs_gbuf *gbuf;

	migrate_disable();
	gbuf = &z_erofs_gbufpool[z_erofs_gbuf_id()];
	spin_lock(&gbuf->lock);
	/* check if the buffer is too small */
	if (requiredpages > gbuf->nrpages) {
		spin_unlock(&gbuf->lock);
		migrate_enable();
		/* (for sparse checker) pretend gbuf->lock is still taken */
		__acquire(gbuf->lock);
		return NULL;
	}
	return gbuf->ptr;
}

void z_erofs_put_gbuf(void *ptr) __releases(gbuf->lock)
{
	struct z_erofs_gbuf *gbuf;

	gbuf = &z_erofs_gbufpool[z_erofs_gbuf_id()];
	DBG_BUGON(gbuf->ptr != ptr);
	spin_unlock(&gbuf->lock);
	migrate_enable();
}

int z_erofs_gbuf_growsize(unsigned int nrpages)
{
	static DEFINE_MUTEX(gbuf_resize_mutex);
	struct page **tmp_pages = NULL;
	struct z_erofs_gbuf *gbuf;
	void *ptr, *old_ptr;
	int last, i, j;

	mutex_lock(&gbuf_resize_mutex);
	/* avoid shrinking gbufs, since no idea how many fses rely on */
	if (nrpages <= z_erofs_gbuf_nrpages) {
		mutex_unlock(&gbuf_resize_mutex);
		return 0;
	}

	for (i = 0; i < z_erofs_gbuf_count; ++i) {
		gbuf = &z_erofs_gbufpool[i];
		tmp_pages = kzalloc_objs(*tmp_pages, nrpages);
		if (!tmp_pages)
			goto out;

		for (j = 0; j < gbuf->nrpages; ++j)
			tmp_pages[j] = gbuf->pages[j];
		do {
			last = j;
			j = alloc_pages_bulk(GFP_KERNEL, nrpages,
					     tmp_pages);
			if (last == j)
				goto out;
		} while (j != nrpages);

		ptr = vmap(tmp_pages, nrpages, VM_MAP, PAGE_KERNEL);
		if (!ptr)
			goto out;

Annotation

Implementation Notes