Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.9.4.
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  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 Storage
 17 * ================
 18 * Stores and retrieves blobs using an xfile.  Objects are appended to the file
 19 * and the offset is returned as a magic cookie for retrieval.
 20 */
 21
 22#define XB_KEY_MAGIC	0xABAADDAD
 23struct 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. */
 31int
 32xfblob_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. */
 62void
 63xfblob_destroy(
 64	struct xfblob	*blob)
 65{
 66	xfile_destroy(blob->xfile);
 67	kfree(blob);
 68}
 69
 70/* Retrieve a blob. */
 71int
 72xfblob_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. */
 99int
100xfblob_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. */
132int
133xfblob_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 long
155xfblob_bytes(
156	struct xfblob		*blob)
157{
158	return xfile_bytes(blob->xfile);
159}
160
161/* Drop all the blobs. */
162void
163xfblob_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}