/* General filesystem caching interface * * Copyright (C) 2004-2007 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * * NOTE!!! See: * * Documentation/filesystems/caching/netfs-api.txt * * for a description of the network filesystem interface declared here. */ #ifndef _LINUX_FSCACHE_H #define _LINUX_FSCACHE_H #include #include #include #include #if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE) #define fscache_available() (1) #define fscache_cookie_valid(cookie) (cookie) #else #define fscache_available() (0) #define fscache_cookie_valid(cookie) (0) #endif /* * overload PG_private_2 to give us PG_fscache - this is used to indicate that * a page is currently backed by a local disk cache */ #define PageFsCache(page) PagePrivate2((page)) #define SetPageFsCache(page) SetPagePrivate2((page)) #define ClearPageFsCache(page) ClearPagePrivate2((page)) #define TestSetPageFsCache(page) TestSetPagePrivate2((page)) #define TestClearPageFsCache(page) TestClearPagePrivate2((page)) /* pattern used to fill dead space in an index entry */ #define FSCACHE_INDEX_DEADFILL_PATTERN 0x79 struct pagevec; struct fscache_cache_tag; struct fscache_cookie; struct fscache_netfs; typedef void (*fscache_rw_complete_t)(struct page *page, void *context, int error); /* result of index entry consultation */ enum fscache_checkaux { FSCACHE_CHECKAUX_OKAY, /* entry okay as is */ FSCACHE_CHECKAUX_NEEDS_UPDATE, /* entry requires update */ FSCACHE_CHECKAUX_OBSOLETE, /* entry requires deletion */ }; /* * fscache cookie definition */ struct fscache_cookie_def { /* name of cookie type */ char name[16]; /* cookie type */ uint8_t type; #define FSCACHE_COOKIE_TYPE_INDEX 0 #define FSCACHE_COOKIE_TYPE_DATAFILE 1 /* select the cache into which to insert an entry in this index * - optional * - should return a cache identifier or NULL to cause the cache to be * inherited from the parent if possible or the first cache picked * for a non-index file if not */ struct fscache_cache_tag *(*select_cache)( const void *parent_netfs_data, const void *cookie_netfs_data); /* get an index key * - should store the key data in the buffer * - should return the amount of data stored * - not permitted to return an error * - the netfs data from the cookie being used as the source is * presented */ uint16_t (*get_key)(const void *cookie_netfs_data, void *buffer, uint16_t bufmax); /* get certain file attributes from the netfs data * - this function can be absent for an index * - not permitted to return an error * - the netfs data from the cookie being used as the source is * presented */ void (*get_attr)(const void *cookie_netfs_data, uint64_t *size); /* get the auxiliary data from netfs data * - this function can be absent if the index carries no state data * - should store the auxiliary data in the buffer * - should return the amount of amount stored * - not permitted to return an error * - the netfs data from the cookie being used as the source is * presented */ uint16_t (*get_aux)(const void *cookie_netfs_data, void *buffer, uint16_t bufmax); /* consult the netfs about the state of an object * - this function can be absent if the index carries no state data * - the netfs data from the cookie being used as the target is * presented, as is the auxiliary data */ enum fscache_checkaux (*check_aux)(void *cookie_netfs_data, const void *data, uint16_t datalen); /* get an extra reference on a read context * - this function can be absent if the completion function doesn't * require a context */ void (*get_context)(void *cookie_netfs_data, void *context); /* release an extra reference on a read context * - this function can be absent if the completion function doesn't * require a context */ void (*put_context)(void *cookie_netfs_data, void *context); /* indicate page that now have cache metadata retained * - this function should mark the specified page as now being cached * - the page will have been marked with PG_fscache before this is * called, so this is optional */ void (*mark_page_cached)(void *cookie_netfs_data, struct address_space *mapping, struct page *page); /* indicate the cookie is no longer cached * - this function is called when the backing store currently caching * a cookie is removed * - the netfs should use this to clean up any markers indicating * cached pages * - this is mandatory for any object that may have data */ void (*now_uncached)(void *cookie_netfs_data); }; /* * fscache cached network filesystem type * - name, version and ops must be filled in before registration * - all other fields will be set during registration */ struct fscache_netfs { uint32_t version; /* indexing version */ const char *name; /* filesystem name */ struct fscache_cookie *primary_index; struct list_head link; /* internal link */ }; /* * data file or index object cookie * - a file will only appear in one cache * - a request to cache a file may or may not be honoured, subject to * constraints such as disk space * - indices are created on disk just-in-time */ struct fscache_cookie { atomic_t usage; /* number of users of this cookie */ atomic_t n_children; /* number of children of this cookie */ atomic_t n_active; /* number of active users of netfs ptrs */ spinlock_t lock; spinlock_t stores_lock; /* lock on page store tree */ struct hlist_head backing_objects; /* object(s) backing this file/index */ const struct fscache_cookie_def *def; /* definition */ struct fscache_cookie *parent; /* parent of this entry */ void *netfs_data; /* back pointer to netfs */ struct radix_tree_root stores; /* pages to be stored on this cookie */ #define FSCACHE_COOKIE_PENDING_TAG 0 /* pages tag: pending write to cache */ #define FSCACHE_COOKIE_STORING_TAG 1 /* pages tag: writing to cache */ unsigned long flags; #define FSCACHE_COOKIE_LOOKING_UP 0 /* T if non-index cookie being looked up still */ #define FSCACHE_COOKIE_NO_DATA_YET 1 /* T if
/*
// Copyright (c) 2010-2017 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
*/

#include <stdio.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

#include "prox_args.h"
#include "file_utils.h"

static char file_error_string[128] = {0};

const char *file_get_error(void)
{
	return file_error_string;
}

__attribute__((format(printf, 1 ,2))) static void file_set_error(const char *fmt, ...)
{
	va_list ap;

	va_start(ap, fmt);
	vsnprintf(file_error_string, sizeof(file_error_string), fmt, ap);
	va_end(ap);
}

static void resolve_path_cfg_dir(char *file_name, size_t len, const char *path)
{
	if (path[0] != '/')
		snprintf(file_name, len, "%s/%s", get_cfg_dir(), path);
	else
		strncpy(file_name, path, len);
}

long file_get_size(const char *path)
{
	char file_name[PATH_MAX];
	struct stat s;

	resolve_path_cfg_dir(file_name, sizeof(file_name), path);

	if (stat(file_name, &s)) {
		file_set_error("Stat failed on '%s': %s", path, strerror(errno));
		return -1;
	}

	if ((s.st_mode & S_IFMT) != S_IFREG) {
		snprintf(file_error_string, sizeof(file_error_string), "'%s' is not a file", path);
		return -1;
	}

	return s.st_size;
}

int file_read_content(const char *path, uint8_t *mem, size_t beg, size_t len)
{
	char file_name[PATH_MAX];
	FILE *f;

	resolve_path_cfg_dir(file_name, sizeof(file_name), path);
	f = fopen(file_name, "r");
	if (!f) {
		file_set_error("Failed to read '%s': %s", path, strerror(errno));
		return -1;
	}

	fseek(f, beg, SEEK_SET);

	size_t ret = fread(mem, 1, len, f);
	if ((uint32_t)ret !=  len) {
		file_set_error("Failed to read '%s:%zu' for %zu bytes: got %zu\n", file_name, beg, len, ret);
		return -1;
	}

	fclose(f);
	return 0;
}
_cookie *cookie, bool invalidate) { if (fscache_cookie_valid(cookie) && fscache_cookie_enabled(cookie)) __fscache_disable_cookie(cookie, invalidate); } /** * fscache_enable_cookie - Reenable a cookie * @cookie: The cookie representing the cache object * @can_enable: A function to permit enablement once lock is held * @data: Data for can_enable() * * Reenable a previously disabled cookie, allowing it to accept further alloc, * read, write, invalidate, update or acquire operations. An attempt will be * made to immediately reattach the cookie to a backing object. * * The can_enable() function is called (if not NULL) once the enablement lock * is held to rule on whether enablement is still permitted to go ahead. */ static inline void fscache_enable_cookie(struct fscache_cookie *cookie, bool (*can_enable)(void *data), void *data) { if (fscache_cookie_valid(cookie) && !fscache_cookie_enabled(cookie)) __fscache_enable_cookie(cookie, can_enable, data); } #endif /* _LINUX_FSCACHE_H */