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