struct-funcs.c 3.9 KB

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