brintos

brintos / linux-shallow public Read only

0
0
Text · 3.2 KiB · 6ef2a96 Raw
169 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Copyright (c) 2021-2024 Oracle.  All Rights Reserved.4 * Author: Darrick J. Wong <djwong@kernel.org>5 */6#include "xfs.h"7#include "xfs_fs.h"8#include "xfs_shared.h"9#include "xfs_format.h"10#include "scrub/scrub.h"11#include "scrub/xfile.h"12#include "scrub/xfarray.h"13#include "scrub/xfblob.h"14 15/*16 * XFS Blob Storage17 * ================18 * Stores and retrieves blobs using an xfile.  Objects are appended to the file19 * and the offset is returned as a magic cookie for retrieval.20 */21 22#define XB_KEY_MAGIC	0xABAADDAD23struct xb_key {24	uint32_t		xb_magic;  /* XB_KEY_MAGIC */25	uint32_t		xb_size;   /* size of the blob, in bytes */26	loff_t			xb_offset; /* byte offset of this key */27	/* blob comes after here */28} __packed;29 30/* Initialize a blob storage object. */31int32xfblob_create(33	const char		*description,34	struct xfblob		**blobp)35{36	struct xfblob		*blob;37	struct xfile		*xfile;38	int			error;39 40	error = xfile_create(description, 0, &xfile);41	if (error)42		return error;43 44	blob = kmalloc(sizeof(struct xfblob), XCHK_GFP_FLAGS);45	if (!blob) {46		error = -ENOMEM;47		goto out_xfile;48	}49 50	blob->xfile = xfile;51	blob->last_offset = PAGE_SIZE;52 53	*blobp = blob;54	return 0;55 56out_xfile:57	xfile_destroy(xfile);58	return error;59}60 61/* Destroy a blob storage object. */62void63xfblob_destroy(64	struct xfblob	*blob)65{66	xfile_destroy(blob->xfile);67	kfree(blob);68}69 70/* Retrieve a blob. */71int72xfblob_load(73	struct xfblob	*blob,74	xfblob_cookie	cookie,75	void		*ptr,76	uint32_t	size)77{78	struct xb_key	key;79	int		error;80 81	error = xfile_load(blob->xfile, &key, sizeof(key), cookie);82	if (error)83		return error;84 85	if (key.xb_magic != XB_KEY_MAGIC || key.xb_offset != cookie) {86		ASSERT(0);87		return -ENODATA;88	}89	if (size < key.xb_size) {90		ASSERT(0);91		return -EFBIG;92	}93 94	return xfile_load(blob->xfile, ptr, key.xb_size,95			cookie + sizeof(key));96}97 98/* Store a blob. */99int100xfblob_store(101	struct xfblob	*blob,102	xfblob_cookie	*cookie,103	const void	*ptr,104	uint32_t	size)105{106	struct xb_key	key = {107		.xb_offset = blob->last_offset,108		.xb_magic = XB_KEY_MAGIC,109		.xb_size = size,110	};111	loff_t		pos = blob->last_offset;112	int		error;113 114	error = xfile_store(blob->xfile, &key, sizeof(key), pos);115	if (error)116		return error;117 118	pos += sizeof(key);119	error = xfile_store(blob->xfile, ptr, size, pos);120	if (error)121		goto out_err;122 123	*cookie = blob->last_offset;124	blob->last_offset += sizeof(key) + size;125	return 0;126out_err:127	xfile_discard(blob->xfile, blob->last_offset, sizeof(key));128	return error;129}130 131/* Free a blob. */132int133xfblob_free(134	struct xfblob	*blob,135	xfblob_cookie	cookie)136{137	struct xb_key	key;138	int		error;139 140	error = xfile_load(blob->xfile, &key, sizeof(key), cookie);141	if (error)142		return error;143 144	if (key.xb_magic != XB_KEY_MAGIC || key.xb_offset != cookie) {145		ASSERT(0);146		return -ENODATA;147	}148 149	xfile_discard(blob->xfile, cookie, sizeof(key) + key.xb_size);150	return 0;151}152 153/* How many bytes is this blob storage object consuming? */154unsigned long long155xfblob_bytes(156	struct xfblob		*blob)157{158	return xfile_bytes(blob->xfile);159}160 161/* Drop all the blobs. */162void163xfblob_truncate(164	struct xfblob	*blob)165{166	xfile_discard(blob->xfile, PAGE_SIZE, MAX_LFS_FILESIZE - PAGE_SIZE);167	blob->last_offset = PAGE_SIZE;168}169