xfblob.c 3.2 KB

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