struct-funcs.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. /*
  2. * Copyright (C) 2007 Oracle. All rights reserved.
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public
  6. * License v2 as published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. * General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public
  14. * License along with this program; if not, write to the
  15. * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  16. * Boston, MA 021110-1307, USA.
  17. */
  18. #include <linux/highmem.h>
  19. /* this is some deeply nasty code. ctree.h has a different
  20. * definition for this BTRFS_SETGET_FUNCS macro, behind a #ifndef
  21. *
  22. * The end result is that anyone who #includes ctree.h gets a
  23. * declaration for the btrfs_set_foo functions and btrfs_foo functions
  24. *
  25. * This file declares the macros and then #includes ctree.h, which results
  26. * in cpp creating the function here based on the template below.
  27. *
  28. * These setget functions do all the extent_buffer related mapping
  29. * required to efficiently read and write specific fields in the extent
  30. * buffers. Every pointer to metadata items in btrfs is really just
  31. * an unsigned long offset into the extent buffer which has been
  32. * cast to a specific type. This gives us all the gcc type checking.
  33. *
  34. * The extent buffer api is used to do all the kmapping and page
  35. * spanning work required to get extent buffers in highmem and have
  36. * a metadata blocksize different from the page size.
  37. *
  38. * The macro starts with a simple function prototype declaration so that
  39. * sparse won't complain about it being static.
  40. */
  41. #define BTRFS_SETGET_FUNCS(name, type, member, bits) \
  42. u##bits btrfs_##name(struct extent_buffer *eb, type *s); \
  43. void btrfs_set_##name(struct extent_buffer *eb, type *s, u##bits val); \
  44. void btrfs_set_token_##name(struct extent_buffer *eb, type *s, u##bits val, struct btrfs_map_token *token); \
  45. u##bits btrfs_token_##name(struct extent_buffer *eb, \
  46. type *s, struct btrfs_map_token *token) \
  47. { \
  48. unsigned long part_offset = (unsigned long)s; \
  49. unsigned long offset = part_offset + offsetof(type, member); \
  50. type *p; \
  51. int err; \
  52. char *kaddr; \
  53. unsigned long map_start; \
  54. unsigned long map_len; \
  55. unsigned long mem_len = sizeof(((type *)0)->member); \
  56. u##bits res; \
  57. if (token && token->kaddr && token->offset <= offset && \
  58. token->eb == eb && \
  59. (token->offset + PAGE_CACHE_SIZE >= offset + mem_len)) { \
  60. kaddr = token->kaddr; \
  61. p = (type *)(kaddr + part_offset - token->offset); \
  62. res = le##bits##_to_cpu(p->member); \
  63. return res; \
  64. } \
  65. err = map_private_extent_buffer(eb, offset, \
  66. mem_len, \
  67. &kaddr, &map_start, &map_len); \
  68. if (err) { \
  69. __le##bits leres; \
  70. read_eb_member(eb, s, type, member, &leres); \
  71. return le##bits##_to_cpu(leres); \
  72. } \
  73. p = (type *)(kaddr + part_offset - map_start); \
  74. res = le##bits##_to_cpu(p->member); \
  75. if (token) { \
  76. token->kaddr = kaddr; \
  77. token->offset = map_start; \
  78. token->eb = eb; \
  79. } \
  80. return res; \
  81. } \
  82. void btrfs_set_token_##name(struct extent_buffer *eb, \
  83. type *s, u##bits val, struct btrfs_map_token *token) \
  84. { \
  85. unsigned long part_offset = (unsigned long)s; \
  86. unsigned long offset = part_offset + offsetof(type, member); \
  87. type *p; \
  88. int err; \
  89. char *kaddr; \
  90. unsigned long map_start; \
  91. unsigned long map_len; \
  92. unsigned long mem_len = sizeof(((type *)0)->member); \
  93. if (token && token->kaddr && token->offset <= offset && \
  94. token->eb == eb && \
  95. (token->offset + PAGE_CACHE_SIZE >= offset + mem_len)) { \
  96. kaddr = token->kaddr; \
  97. p = (type *)(kaddr + part_offset - token->offset); \
  98. p->member = cpu_to_le##bits(val); \
  99. return; \
  100. } \
  101. err = map_private_extent_buffer(eb, offset, \
  102. mem_len, \
  103. &kaddr, &map_start, &map_len); \
  104. if (err) { \
  105. __le##bits val2; \
  106. val2 = cpu_to_le##bits(val); \
  107. write_eb_member(eb, s, type, member, &val2); \
  108. return; \
  109. } \
  110. p = (type *)(kaddr + part_offset - map_start); \
  111. p->member = cpu_to_le##bits(val); \
  112. if (token) { \
  113. token->kaddr = kaddr; \
  114. token->offset = map_start; \
  115. token->eb = eb; \
  116. } \
  117. } \
  118. void btrfs_set_##name(struct extent_buffer *eb, \
  119. type *s, u##bits val) \
  120. { \
  121. btrfs_set_token_##name(eb, s, val, NULL); \
  122. } \
  123. u##bits btrfs_##name(struct extent_buffer *eb, \
  124. type *s) \
  125. { \
  126. return btrfs_token_##name(eb, s, NULL); \
  127. } \
  128. #include "ctree.h"
  129. void btrfs_node_key(struct extent_buffer *eb,
  130. struct btrfs_disk_key *disk_key, int nr)
  131. {
  132. unsigned long ptr = btrfs_node_key_ptr_offset(nr);
  133. read_eb_member(eb, (struct btrfs_key_ptr *)ptr,
  134. struct btrfs_key_ptr, key, disk_key);
  135. }