enum {
EXTENT_BUFFER_UPTODATE,
EXTENT_BUFFER_DIRTY,
EXTENT_BUFFER_TREE_REF,
EXTENT_BUFFER_STALE,
EXTENT_BUFFER_WRITEBACK,
EXTENT_BUFFER_UNMAPPED, /* write IO error */
EXTENT_BUFFER_WRITE_ERR, /* Indicate the extent buffer is written zeroed out (for zoned) */
EXTENT_BUFFER_ZONED_ZEROOUT, /* Indicate that extent buffer pages a being read */
EXTENT_BUFFER_READING,
};
/* these are flags for __process_pages_contig */ enum {
ENUM_BIT(PAGE_UNLOCK), /* Page starts writeback, clear dirty bit and set writeback bit */
ENUM_BIT(PAGE_START_WRITEBACK),
ENUM_BIT(PAGE_END_WRITEBACK),
ENUM_BIT(PAGE_SET_ORDERED),
};
/* * Folio private values. Every page that is controlled by the extent map has * folio private set to this value.
*/ #define EXTENT_FOLIO_PRIVATE 1
/* * The extent buffer bitmap operations are done with byte granularity instead of * word granularity for two reasons: * 1. The bitmaps must be little-endian on disk. * 2. Bitmap items are not guaranteed to be aligned to a word and therefore a * single word in a bitmap may straddle two pages in the extent buffer.
*/ #define BIT_BYTE(nr) ((nr) / BITS_PER_BYTE) #define BYTE_MASK ((1U << BITS_PER_BYTE) - 1) #define BITMAP_FIRST_BYTE_MASK(start) \
((BYTE_MASK << ((start) & (BITS_PER_BYTE - 1))) & BYTE_MASK) #define BITMAP_LAST_BYTE_MASK(nbits) \
(BYTE_MASK >> (-(nbits) & (BITS_PER_BYTE - 1)))
int __init extent_buffer_init_cachep(void); void __cold extent_buffer_free_cachep(void);
/* * The address where the eb can be accessed without any cross-page handling. * This can be NULL if not possible.
*/ void *addr;
spinlock_t refs_lock;
refcount_t refs; int read_mirror; /* >= 0 if eb belongs to a log tree, -1 otherwise */
s8 log_index;
u8 folio_shift; struct rcu_head rcu_head;
struct rw_semaphore lock;
/* * Pointers to all the folios of the extent buffer. * * For now the folio is always order 0 (aka, a single page).
*/ struct folio *folios[INLINE_EXTENT_BUFFER_PAGES]; #ifdef CONFIG_BTRFS_DEBUG struct list_head leak_list;
pid_t lock_owner; #endif
};
struct btrfs_eb_write_context { struct writeback_control *wbc; struct extent_buffer *eb; /* Block group @eb resides in. Only used for zoned mode. */ struct btrfs_block_group *zoned_bg;
};
/* * Get the correct offset inside the page of extent buffer. * * @eb: target extent buffer * @start: offset inside the extent buffer * * Will handle both sectorsize == PAGE_SIZE and sectorsize < PAGE_SIZE cases.
*/ staticinline size_t get_eb_offset_in_folio(conststruct extent_buffer *eb, unsignedlong offset)
{ /* * 1) sectorsize == PAGE_SIZE and nodesize >= PAGE_SIZE case * 1.1) One large folio covering the whole eb * The eb->start is aligned to folio size, thus adding it * won't cause any difference. * 1.2) Several page sized folios * The eb->start is aligned to folio (page) size, thus * adding it won't cause any difference. * * 2) sectorsize < PAGE_SIZE and nodesize < PAGE_SIZE case * In this case there would only be one page sized folio, and there * may be several different extent buffers in the page/folio. * We need to add eb->start to properly access the offset inside * that eb.
*/ return offset_in_folio(eb->folios[0], offset + eb->start);
}
staticinlineunsignedlong get_eb_folio_index(conststruct extent_buffer *eb, unsignedlong offset)
{ /* * 1) sectorsize == PAGE_SIZE and nodesize >= PAGE_SIZE case * 1.1) One large folio covering the whole eb. * the folio_shift would be large enough to always make us * return 0 as index. * 1.2) Several page sized folios * The folio_shift would be PAGE_SHIFT, giving us the correct * index. * * 2) sectorsize < PAGE_SIZE and nodesize < PAGE_SIZE case * The folio would only be page sized, and always give us 0 as index.
*/ return offset >> eb->folio_shift;
}
/* * Structure to record how many bytes and which ranges are set/cleared
*/ struct extent_changeset { /* How many bytes are set/cleared in this operation */
u64 bytes_changed;
void btrfs_readahead_tree_block(struct btrfs_fs_info *fs_info,
u64 bytenr, u64 owner_root, u64 gen, int level); void btrfs_readahead_node_child(struct extent_buffer *node, int slot);
/* Note: this can be used in for loops without caching the value in a variable. */ staticinlineint __pure num_extent_pages(conststruct extent_buffer *eb)
{ /* * For sectorsize == PAGE_SIZE case, since nodesize is always aligned to * sectorsize, it's just eb->len >> PAGE_SHIFT. * * For sectorsize < PAGE_SIZE case, we could have nodesize < PAGE_SIZE, * thus have to ensure we get at least one page.
*/ return (eb->len >> PAGE_SHIFT) ?: 1;
}
/* * This can only be determined at runtime by checking eb::folios[0]. * * As we can have either one large folio covering the whole eb * (either nodesize <= PAGE_SIZE, or high order folio), or multiple * single-paged folios. * * Note: this can be used in for loops without caching the value in a variable.
*/ staticinlineint __pure num_extent_folios(conststruct extent_buffer *eb)
{ if (!eb->folios[0]) return 0; if (folio_order(eb->folios[0])) return 1; return num_extent_pages(eb);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.