]> Git Repo - linux.git/blob - fs/xfs/scrub/xfblob.c
Merge patch series "riscv: Extension parsing fixes"
[linux.git] / fs / xfs / scrub / xfblob.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) 2021-2024 Oracle.  All Rights Reserved.
4  * Author: Darrick J. Wong <[email protected]>
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 xfblob_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
56 out_xfile:
57         xfile_destroy(xfile);
58         return error;
59 }
60
61 /* Destroy a blob storage object. */
62 void
63 xfblob_destroy(
64         struct xfblob   *blob)
65 {
66         xfile_destroy(blob->xfile);
67         kfree(blob);
68 }
69
70 /* Retrieve a blob. */
71 int
72 xfblob_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. */
99 int
100 xfblob_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;
126 out_err:
127         xfile_discard(blob->xfile, blob->last_offset, sizeof(key));
128         return error;
129 }
130
131 /* Free a blob. */
132 int
133 xfblob_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? */
154 unsigned long long
155 xfblob_bytes(
156         struct xfblob           *blob)
157 {
158         return xfile_bytes(blob->xfile);
159 }
160
161 /* Drop all the blobs. */
162 void
163 xfblob_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 }
This page took 0.071746 seconds and 4 git commands to generate.