Line data Source code
1 : // SPDX-License-Identifier: GPL-2.0-or-later
2 : /*
3 : * Copyright (C) 2021-2023 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
23 : struct 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. */
31 : int
32 100924764 : xfblob_create(
33 : const char *description,
34 : struct xfblob **blobp)
35 : {
36 100924764 : struct xfblob *blob;
37 100924764 : struct xfile *xfile;
38 100924764 : int error;
39 :
40 100924764 : error = xfile_create(description, 0, &xfile);
41 100937817 : if (error)
42 : return error;
43 :
44 100941908 : blob = kmalloc(sizeof(struct xfblob), XCHK_GFP_FLAGS);
45 100940790 : if (!blob) {
46 0 : error = -ENOMEM;
47 0 : goto out_xfile;
48 : }
49 :
50 100940790 : blob->xfile = xfile;
51 100940790 : blob->last_offset = PAGE_SIZE;
52 :
53 100940790 : *blobp = blob;
54 100940790 : return 0;
55 :
56 : out_xfile:
57 0 : xfile_destroy(xfile);
58 0 : return error;
59 : }
60 :
61 : /* Destroy a blob storage object. */
62 : void
63 100939330 : xfblob_destroy(
64 : struct xfblob *blob)
65 : {
66 100939330 : xfile_destroy(blob->xfile);
67 100945489 : kfree(blob);
68 100946232 : }
69 :
70 : /* Retrieve a blob. */
71 : int
72 14141279 : xfblob_load(
73 : struct xfblob *blob,
74 : xfblob_cookie cookie,
75 : void *ptr,
76 : uint32_t size)
77 : {
78 14141279 : struct xb_key key;
79 14141279 : int error;
80 :
81 14141279 : error = xfile_obj_load(blob->xfile, &key, sizeof(key), cookie);
82 14142213 : if (error)
83 : return error;
84 :
85 14142213 : if (key.xb_magic != XB_KEY_MAGIC || key.xb_offset != cookie) {
86 0 : ASSERT(0);
87 0 : return -ENODATA;
88 : }
89 14142213 : if (size < key.xb_size) {
90 0 : ASSERT(0);
91 0 : return -EFBIG;
92 : }
93 :
94 14142213 : return xfile_obj_load(blob->xfile, ptr, key.xb_size,
95 14142213 : cookie + sizeof(key));
96 : }
97 :
98 : /* Store a blob. */
99 : int
100 1094095224 : xfblob_store(
101 : struct xfblob *blob,
102 : xfblob_cookie *cookie,
103 : const void *ptr,
104 : uint32_t size)
105 : {
106 1094095224 : struct xb_key key = {
107 1094095224 : .xb_offset = blob->last_offset,
108 : .xb_magic = XB_KEY_MAGIC,
109 : .xb_size = size,
110 : };
111 1094095224 : loff_t pos = blob->last_offset;
112 1094095224 : int error;
113 :
114 1094095224 : error = xfile_obj_store(blob->xfile, &key, sizeof(key), pos);
115 1094707252 : if (error)
116 : return error;
117 :
118 1094707235 : pos += sizeof(key);
119 1094707235 : error = xfile_obj_store(blob->xfile, ptr, size, pos);
120 1094736014 : if (error)
121 0 : goto out_err;
122 :
123 1094736014 : *cookie = blob->last_offset;
124 1094736014 : blob->last_offset += sizeof(key) + size;
125 1094736014 : return 0;
126 : out_err:
127 0 : xfile_discard(blob->xfile, blob->last_offset, sizeof(key));
128 0 : return error;
129 : }
130 :
131 : /* Free a blob. */
132 : int
133 2292938 : xfblob_free(
134 : struct xfblob *blob,
135 : xfblob_cookie cookie)
136 : {
137 2292938 : struct xb_key key;
138 2292938 : int error;
139 :
140 2292938 : error = xfile_obj_load(blob->xfile, &key, sizeof(key), cookie);
141 2292938 : if (error)
142 : return error;
143 :
144 2292938 : if (key.xb_magic != XB_KEY_MAGIC || key.xb_offset != cookie) {
145 0 : ASSERT(0);
146 0 : return -ENODATA;
147 : }
148 :
149 2292938 : xfile_discard(blob->xfile, cookie, sizeof(key) + key.xb_size);
150 2292938 : return 0;
151 : }
152 :
153 : /* How many bytes is this blob storage object consuming? */
154 : unsigned long long
155 3773371691 : xfblob_bytes(
156 : struct xfblob *blob)
157 : {
158 3773371691 : return xfile_bytes(blob->xfile);
159 : }
160 :
161 : /* Drop all the blobs. */
162 : void
163 89614024 : xfblob_truncate(
164 : struct xfblob *blob)
165 : {
166 89614024 : xfile_discard(blob->xfile, PAGE_SIZE, MAX_LFS_FILESIZE - PAGE_SIZE);
167 89616099 : blob->last_offset = PAGE_SIZE;
168 89616099 : }
|