brintos

brintos / linux-shallow public Read only

0
0
Text · 3.3 KiB · 781aac4 Raw
139 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/* Volume handling.3 *4 * Copyright (C) 2021 Red Hat, Inc. All Rights Reserved.5 * Written by David Howells (dhowells@redhat.com)6 */7 8#include <linux/fs.h>9#include <linux/slab.h>10#include "internal.h"11#include <trace/events/fscache.h>12 13/*14 * Allocate and set up a volume representation.  We make sure all the fanout15 * directories are created and pinned.16 */17void cachefiles_acquire_volume(struct fscache_volume *vcookie)18{19	struct cachefiles_volume *volume;20	struct cachefiles_cache *cache = vcookie->cache->cache_priv;21	const struct cred *saved_cred;22	struct dentry *vdentry, *fan;23	size_t len;24	char *name;25	bool is_new = false;26	int ret, n_accesses, i;27 28	_enter("");29 30	volume = kzalloc(sizeof(struct cachefiles_volume), GFP_KERNEL);31	if (!volume)32		return;33	volume->vcookie = vcookie;34	volume->cache = cache;35	INIT_LIST_HEAD(&volume->cache_link);36 37	cachefiles_begin_secure(cache, &saved_cred);38 39	len = vcookie->key[0];40	name = kmalloc(len + 3, GFP_NOFS);41	if (!name)42		goto error_vol;43	name[0] = 'I';44	memcpy(name + 1, vcookie->key + 1, len);45	name[len + 1] = 0;46 47retry:48	vdentry = cachefiles_get_directory(cache, cache->store, name, &is_new);49	if (IS_ERR(vdentry))50		goto error_name;51	volume->dentry = vdentry;52 53	if (is_new) {54		if (!cachefiles_set_volume_xattr(volume))55			goto error_dir;56	} else {57		ret = cachefiles_check_volume_xattr(volume);58		if (ret < 0) {59			if (ret != -ESTALE)60				goto error_dir;61			inode_lock_nested(d_inode(cache->store), I_MUTEX_PARENT);62			cachefiles_bury_object(cache, NULL, cache->store, vdentry,63					       FSCACHE_VOLUME_IS_WEIRD);64			cachefiles_put_directory(volume->dentry);65			cond_resched();66			goto retry;67		}68	}69	70	for (i = 0; i < 256; i++) {71		sprintf(name, "@%02x", i);72		fan = cachefiles_get_directory(cache, vdentry, name, NULL);73		if (IS_ERR(fan))74			goto error_fan;75		volume->fanout[i] = fan;76	}77 78	cachefiles_end_secure(cache, saved_cred);79 80	vcookie->cache_priv = volume;81	n_accesses = atomic_inc_return(&vcookie->n_accesses); /* Stop wakeups on dec-to-0 */82	trace_fscache_access_volume(vcookie->debug_id, 0,83				    refcount_read(&vcookie->ref),84				    n_accesses, fscache_access_cache_pin);85 86	spin_lock(&cache->object_list_lock);87	list_add(&volume->cache_link, &volume->cache->volumes);88	spin_unlock(&cache->object_list_lock);89 90	kfree(name);91	return;92 93error_fan:94	for (i = 0; i < 256; i++)95		cachefiles_put_directory(volume->fanout[i]);96error_dir:97	cachefiles_put_directory(volume->dentry);98error_name:99	kfree(name);100error_vol:101	kfree(volume);102	cachefiles_end_secure(cache, saved_cred);103}104 105/*106 * Release a volume representation.107 */108static void __cachefiles_free_volume(struct cachefiles_volume *volume)109{110	int i;111 112	_enter("");113 114	volume->vcookie->cache_priv = NULL;115 116	for (i = 0; i < 256; i++)117		cachefiles_put_directory(volume->fanout[i]);118	cachefiles_put_directory(volume->dentry);119	kfree(volume);120}121 122void cachefiles_free_volume(struct fscache_volume *vcookie)123{124	struct cachefiles_volume *volume = vcookie->cache_priv;125 126	if (volume) {127		spin_lock(&volume->cache->object_list_lock);128		list_del_init(&volume->cache_link);129		spin_unlock(&volume->cache->object_list_lock);130		__cachefiles_free_volume(volume);131	}132}133 134void cachefiles_withdraw_volume(struct cachefiles_volume *volume)135{136	cachefiles_set_volume_xattr(volume);137	__cachefiles_free_volume(volume);138}139