// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright ( c ) 2021 - 2024 Oracle . All Rights Reserved .
* Author : Darrick J . Wong < djwong @ kernel . org >
*/
#include "xfs.h"
#include "xfs_fs.h"
#include "xfs_shared.h"
#include "xfs_format.h"
#include "scrub/scrub.h"
#include "scrub/xfile.h"
#include "scrub/xfarray.h"
#include "scrub/xfblob.h"
/*
* XFS Blob Storage
* = = = = = = = = = = = = = = = =
* Stores and retrieves blobs using an xfile . Objects are appended to the file
* and the offset is returned as a magic cookie for retrieval .
*/
#define XB_KEY_MAGIC 0 xABAADDAD
struct xb_key {
uint32_t xb_magic; /* XB_KEY_MAGIC */
uint32_t xb_size; /* size of the blob, in bytes */
loff_t xb_offset; /* byte offset of this key */
/* blob comes after here */
} __packed;
/* Initialize a blob storage object. */
int
xfblob_create(
const char *description,
struct xfblob **blobp)
{
struct xfblob *blob;
struct xfile *xfile;
int error;
error = xfile_create(description, 0 , &xfile);
if (error)
return error;
blob = kmalloc(sizeof (struct xfblob), XCHK_GFP_FLAGS);
if (!blob) {
error = -ENOMEM;
goto out_xfile;
}
blob->xfile = xfile;
blob->last_offset = PAGE_SIZE;
*blobp = blob;
return 0 ;
out_xfile:
xfile_destroy(xfile);
return error;
}
/* Destroy a blob storage object. */
void
xfblob_destroy(
struct xfblob *blob)
{
xfile_destroy(blob->xfile);
kfree(blob);
}
/* Retrieve a blob. */
int
xfblob_load(
struct xfblob *blob,
xfblob_cookie cookie,
void *ptr,
uint32_t size)
{
struct xb_key key;
int error;
error = xfile_load(blob->xfile, &key, sizeof (key), cookie);
if (error)
return error;
if (key.xb_magic != XB_KEY_MAGIC || key.xb_offset != cookie) {
ASSERT(0 );
return -ENODATA;
}
if (size < key.xb_size) {
ASSERT(0 );
return -EFBIG;
}
return xfile_load(blob->xfile, ptr, key.xb_size,
cookie + sizeof (key));
}
/* Store a blob. */
int
xfblob_store(
struct xfblob *blob,
xfblob_cookie *cookie,
const void *ptr,
uint32_t size)
{
struct xb_key key = {
.xb_offset = blob->last_offset,
.xb_magic = XB_KEY_MAGIC,
.xb_size = size,
};
loff_t pos = blob->last_offset;
int error;
error = xfile_store(blob->xfile, &key, sizeof (key), pos);
if (error)
return error;
pos += sizeof (key);
error = xfile_store(blob->xfile, ptr, size, pos);
if (error)
goto out_err;
*cookie = blob->last_offset;
blob->last_offset += sizeof (key) + size;
return 0 ;
out_err:
xfile_discard(blob->xfile, blob->last_offset, sizeof (key));
return error;
}
/* Free a blob. */
int
xfblob_free(
struct xfblob *blob,
xfblob_cookie cookie)
{
struct xb_key key;
int error;
error = xfile_load(blob->xfile, &key, sizeof (key), cookie);
if (error)
return error;
if (key.xb_magic != XB_KEY_MAGIC || key.xb_offset != cookie) {
ASSERT(0 );
return -ENODATA;
}
xfile_discard(blob->xfile, cookie, sizeof (key) + key.xb_size);
return 0 ;
}
/* How many bytes is this blob storage object consuming? */
unsigned long long
xfblob_bytes(
struct xfblob *blob)
{
return xfile_bytes(blob->xfile);
}
/* Drop all the blobs. */
void
xfblob_truncate(
struct xfblob *blob)
{
xfile_discard(blob->xfile, PAGE_SIZE, MAX_LFS_FILESIZE - PAGE_SIZE);
blob->last_offset = PAGE_SIZE;
}
Messung V0.5 in Prozent C=92 H=94 G=92
¤ Dauer der Verarbeitung: 0.9 Sekunden
(vorverarbeitet am 2026-09-30)
¤
*© Formatika GbR, Deutschland