root/fs/btrfs/struct-funcs.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. get_unaligned_le8
  2. put_unaligned_le8
  3. DEFINE_BTRFS_SETGET_BITS

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Copyright (C) 2007 Oracle.  All rights reserved.
   4  */
   5 
   6 #include <asm/unaligned.h>
   7 
   8 #include "ctree.h"
   9 
  10 static inline u8 get_unaligned_le8(const void *p)
  11 {
  12        return *(u8 *)p;
  13 }
  14 
  15 static inline void put_unaligned_le8(u8 val, void *p)
  16 {
  17        *(u8 *)p = val;
  18 }
  19 
  20 /*
  21  * this is some deeply nasty code.
  22  *
  23  * The end result is that anyone who #includes ctree.h gets a
  24  * declaration for the btrfs_set_foo functions and btrfs_foo functions,
  25  * which are wrappers of btrfs_set_token_#bits functions and
  26  * btrfs_get_token_#bits functions, which are defined in this file.
  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 the page spanning work required to
  35  * have a metadata blocksize different from the page size.
  36  *
  37  * There are 2 variants defined, one with a token pointer and one without.
  38  */
  39 
  40 #define DEFINE_BTRFS_SETGET_BITS(bits)                                  \
  41 u##bits btrfs_get_token_##bits(const struct extent_buffer *eb,          \
  42                                const void *ptr, unsigned long off,      \
  43                                struct btrfs_map_token *token)           \
  44 {                                                                       \
  45         unsigned long part_offset = (unsigned long)ptr;                 \
  46         unsigned long offset = part_offset + off;                       \
  47         void *p;                                                        \
  48         int err;                                                        \
  49         char *kaddr;                                                    \
  50         unsigned long map_start;                                        \
  51         unsigned long map_len;                                          \
  52         int size = sizeof(u##bits);                                     \
  53         u##bits res;                                                    \
  54                                                                         \
  55         ASSERT(token);                                                  \
  56         ASSERT(token->eb == eb);                                        \
  57                                                                         \
  58         if (token->kaddr && token->offset <= offset &&                  \
  59            (token->offset + PAGE_SIZE >= offset + size)) {      \
  60                 kaddr = token->kaddr;                                   \
  61                 p = kaddr + part_offset - token->offset;                \
  62                 res = get_unaligned_le##bits(p + off);                  \
  63                 return res;                                             \
  64         }                                                               \
  65         err = map_private_extent_buffer(eb, offset, size,               \
  66                                         &kaddr, &map_start, &map_len);  \
  67         if (err) {                                                      \
  68                 __le##bits leres;                                       \
  69                                                                         \
  70                 read_extent_buffer(eb, &leres, offset, size);           \
  71                 return le##bits##_to_cpu(leres);                        \
  72         }                                                               \
  73         p = kaddr + part_offset - map_start;                            \
  74         res = get_unaligned_le##bits(p + off);                          \
  75         token->kaddr = kaddr;                                           \
  76         token->offset = map_start;                                      \
  77         return res;                                                     \
  78 }                                                                       \
  79 u##bits btrfs_get_##bits(const struct extent_buffer *eb,                \
  80                          const void *ptr, unsigned long off)            \
  81 {                                                                       \
  82         unsigned long part_offset = (unsigned long)ptr;                 \
  83         unsigned long offset = part_offset + off;                       \
  84         void *p;                                                        \
  85         int err;                                                        \
  86         char *kaddr;                                                    \
  87         unsigned long map_start;                                        \
  88         unsigned long map_len;                                          \
  89         int size = sizeof(u##bits);                                     \
  90         u##bits res;                                                    \
  91                                                                         \
  92         err = map_private_extent_buffer(eb, offset, size,               \
  93                                         &kaddr, &map_start, &map_len);  \
  94         if (err) {                                                      \
  95                 __le##bits leres;                                       \
  96                                                                         \
  97                 read_extent_buffer(eb, &leres, offset, size);           \
  98                 return le##bits##_to_cpu(leres);                        \
  99         }                                                               \
 100         p = kaddr + part_offset - map_start;                            \
 101         res = get_unaligned_le##bits(p + off);                          \
 102         return res;                                                     \
 103 }                                                                       \
 104 void btrfs_set_token_##bits(struct extent_buffer *eb,                   \
 105                             const void *ptr, unsigned long off,         \
 106                             u##bits val,                                \
 107                             struct btrfs_map_token *token)              \
 108 {                                                                       \
 109         unsigned long part_offset = (unsigned long)ptr;                 \
 110         unsigned long offset = part_offset + off;                       \
 111         void *p;                                                        \
 112         int err;                                                        \
 113         char *kaddr;                                                    \
 114         unsigned long map_start;                                        \
 115         unsigned long map_len;                                          \
 116         int size = sizeof(u##bits);                                     \
 117                                                                         \
 118         ASSERT(token);                                                  \
 119         ASSERT(token->eb == eb);                                        \
 120                                                                         \
 121         if (token->kaddr && token->offset <= offset &&                  \
 122            (token->offset + PAGE_SIZE >= offset + size)) {      \
 123                 kaddr = token->kaddr;                                   \
 124                 p = kaddr + part_offset - token->offset;                \
 125                 put_unaligned_le##bits(val, p + off);                   \
 126                 return;                                                 \
 127         }                                                               \
 128         err = map_private_extent_buffer(eb, offset, size,               \
 129                         &kaddr, &map_start, &map_len);                  \
 130         if (err) {                                                      \
 131                 __le##bits val2;                                        \
 132                                                                         \
 133                 val2 = cpu_to_le##bits(val);                            \
 134                 write_extent_buffer(eb, &val2, offset, size);           \
 135                 return;                                                 \
 136         }                                                               \
 137         p = kaddr + part_offset - map_start;                            \
 138         put_unaligned_le##bits(val, p + off);                           \
 139         token->kaddr = kaddr;                                           \
 140         token->offset = map_start;                                      \
 141 }                                                                       \
 142 void btrfs_set_##bits(struct extent_buffer *eb, void *ptr,              \
 143                       unsigned long off, u##bits val)                   \
 144 {                                                                       \
 145         unsigned long part_offset = (unsigned long)ptr;                 \
 146         unsigned long offset = part_offset + off;                       \
 147         void *p;                                                        \
 148         int err;                                                        \
 149         char *kaddr;                                                    \
 150         unsigned long map_start;                                        \
 151         unsigned long map_len;                                          \
 152         int size = sizeof(u##bits);                                     \
 153                                                                         \
 154         err = map_private_extent_buffer(eb, offset, size,               \
 155                         &kaddr, &map_start, &map_len);                  \
 156         if (err) {                                                      \
 157                 __le##bits val2;                                        \
 158                                                                         \
 159                 val2 = cpu_to_le##bits(val);                            \
 160                 write_extent_buffer(eb, &val2, offset, size);           \
 161                 return;                                                 \
 162         }                                                               \
 163         p = kaddr + part_offset - map_start;                            \
 164         put_unaligned_le##bits(val, p + off);                           \
 165 }
 166 
 167 DEFINE_BTRFS_SETGET_BITS(8)
 168 DEFINE_BTRFS_SETGET_BITS(16)
 169 DEFINE_BTRFS_SETGET_BITS(32)
 170 DEFINE_BTRFS_SETGET_BITS(64)
 171 
 172 void btrfs_node_key(const struct extent_buffer *eb,
 173                     struct btrfs_disk_key *disk_key, int nr)
 174 {
 175         unsigned long ptr = btrfs_node_key_ptr_offset(nr);
 176         read_eb_member(eb, (struct btrfs_key_ptr *)ptr,
 177                        struct btrfs_key_ptr, key, disk_key);
 178 }

/* [<][>][^][v][top][bottom][index][help] */