LCOV - code coverage report
Current view: top level - fs/xfs/scrub - xfblob.c (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc4-xfsa @ Mon Jul 31 20:08:27 PDT 2023 Lines: 52 65 80.0 %
Date: 2023-07-31 20:08:27 Functions: 7 7 100.0 %

          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 : }

Generated by: LCOV version 1.14