struct-funcs.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2007 Oracle. All rights reserved.
  4. */
  5. #include <asm/unaligned.h>
  6. #include "ctree.h"
  7. static inline u8 get_unaligned_le8(const void *p)
  8. {
  9. return *(u8 *)p;
  10. }
  11. static inline void put_unaligned_le8(u8 val, void *p)
  12. {
  13. *(u8 *)p = val;
  14. }
  15. /*
  16. * this is some deeply nasty code.
  17. *
  18. * The end result is that anyone who #includes ctree.h gets a
  19. * declaration for the btrfs_set_foo functions and btrfs_foo functions,
  20. * which are wrappers of btrfs_set_token_#bits functions and
  21. * btrfs_get_token_#bits functions, which are defined in this file.
  22. *
  23. * These setget functions do all the extent_buffer related mapping
  24. * required to efficiently read and write specific fields in the extent
  25. * buffers. Every pointer to metadata items in btrfs is really just
  26. * an unsigned long offset into the extent buffer which has been
  27. * cast to a specific type. This gives us all the gcc type checking.
  28. *
  29. * The extent buffer api is used to do the page spanning work required to
  30. * have a metadata blocksize different from the page size.
  31. */
  32. #define DEFINE_BTRFS_SETGET_BITS(bits) \
  33. u##bits btrfs_get_token_##bits(const struct extent_buffer *eb, \
  34. const void *ptr, unsigned long off, \
  35. struct btrfs_map_token *token) \
  36. { \
  37. unsigned long part_offset = (unsigned long)ptr; \
  38. unsigned long offset = part_offset + off; \
  39. void *p; \
  40. int err; \
  41. char *kaddr; \
  42. unsigned long map_start; \
  43. unsigned long map_len; \
  44. int size = sizeof(u##bits); \
  45. u##bits res; \
  46. \
  47. if (token && token->kaddr && token->offset <= offset && \
  48. token->eb == eb && \
  49. (token->offset + PAGE_SIZE >= offset + size)) { \
  50. kaddr = token->kaddr; \
  51. p = kaddr + part_offset - token->offset; \
  52. res = get_unaligned_le##bits(p + off); \
  53. return res; \
  54. } \
  55. err = map_private_extent_buffer(eb, offset, size, \
  56. &kaddr, &map_start, &map_len); \
  57. if (err) { \
  58. __le##bits leres; \
  59. \
  60. read_extent_buffer(eb, &leres, offset, size); \
  61. return le##bits##_to_cpu(leres); \
  62. } \
  63. p = kaddr + part_offset - map_start; \
  64. res = get_unaligned_le##bits(p + off); \
  65. if (token) { \
  66. token->kaddr = kaddr; \
  67. token->offset = map_start; \
  68. token->eb = eb; \
  69. } \
  70. return res; \
  71. } \
  72. void btrfs_set_token_##bits(struct extent_buffer *eb, \
  73. const void *ptr, unsigned long off, \
  74. u##bits val, \
  75. struct btrfs_map_token *token) \
  76. { \
  77. unsigned long part_offset = (unsigned long)ptr; \
  78. unsigned long offset = part_offset + off; \
  79. void *p; \
  80. int err; \
  81. char *kaddr; \
  82. unsigned long map_start; \
  83. unsigned long map_len; \
  84. int size = sizeof(u##bits); \
  85. \
  86. if (token && token->kaddr && token->offset <= offset && \
  87. token->eb == eb && \
  88. (token->offset + PAGE_SIZE >= offset + size)) { \
  89. kaddr = token->kaddr; \
  90. p = kaddr + part_offset - token->offset; \
  91. put_unaligned_le##bits(val, p + off); \
  92. return; \
  93. } \
  94. err = map_private_extent_buffer(eb, offset, size, \
  95. &kaddr, &map_start, &map_len); \
  96. if (err) { \
  97. __le##bits val2; \
  98. \
  99. val2 = cpu_to_le##bits(val); \
  100. write_extent_buffer(eb, &val2, offset, size); \
  101. return; \
  102. } \
  103. p = kaddr + part_offset - map_start; \
  104. put_unaligned_le##bits(val, p + off); \
  105. if (token) { \
  106. token->kaddr = kaddr; \
  107. token->offset = map_start; \
  108. token->eb = eb; \
  109. } \
  110. }
  111. DEFINE_BTRFS_SETGET_BITS(8)
  112. DEFINE_BTRFS_SETGET_BITS(16)
  113. DEFINE_BTRFS_SETGET_BITS(32)
  114. DEFINE_BTRFS_SETGET_BITS(64)
  115. void btrfs_node_key(const struct extent_buffer *eb,
  116. struct btrfs_disk_key *disk_key, int nr)
  117. {
  118. unsigned long ptr = btrfs_node_key_ptr_offset(nr);
  119. read_eb_member(eb, (struct btrfs_key_ptr *)ptr,
  120. struct btrfs_key_ptr, key, disk_key);
  121. }