^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /* SPDX-License-Identifier: GPL-2.0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) 2014 Facebook. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #ifndef BTRFS_QGROUP_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #define BTRFS_QGROUP_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/rbtree.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/kobject.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include "ulist.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "delayed-ref.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * Btrfs qgroup overview
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * Btrfs qgroup splits into 3 main part:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * 1) Reserve
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * Reserve metadata/data space for incoming operations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * Affect how qgroup limit works
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * 2) Trace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * Tell btrfs qgroup to trace dirty extents.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * Dirty extents including:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * - Newly allocated extents
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * - Extents going to be deleted (in this trans)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * - Extents whose owner is going to be modified
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * This is the main part affects whether qgroup numbers will stay
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * consistent.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * Btrfs qgroup can trace clean extents and won't cause any problem,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * but it will consume extra CPU time, it should be avoided if possible.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * 3) Account
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * Btrfs qgroup will updates its numbers, based on dirty extents traced
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * in previous step.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * Normally at qgroup rescan and transaction commit time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * Special performance optimization for balance.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * For balance, we need to swap subtree of subvolume and reloc trees.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * In theory, we need to trace all subtree blocks of both subvolume and reloc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * trees, since their owner has changed during such swap.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * However since balance has ensured that both subtrees are containing the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * same contents and have the same tree structures, such swap won't cause
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * qgroup number change.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * But there is a race window between subtree swap and transaction commit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * during that window, if we increase/decrease tree level or merge/split tree
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * blocks, we still need to trace the original subtrees.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * So for balance, we use a delayed subtree tracing, whose workflow is:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * 1) Record the subtree root block get swapped.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * During subtree swap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * O = Old tree blocks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) * N = New tree blocks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) * reloc tree subvolume tree X
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * Root Root
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * / \ / \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * NA OB OA OB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * / | | \ / | | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * NC ND OE OF OC OD OE OF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * In this case, NA and OA are going to be swapped, record (NA, OA) into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * subvolume tree X.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * 2) After subtree swap.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) * reloc tree subvolume tree X
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) * Root Root
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * / \ / \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * OA OB NA OB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * / | | \ / | | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) * OC OD OE OF NC ND OE OF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) * 3a) COW happens for OB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) * If we are going to COW tree block OB, we check OB's bytenr against
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * tree X's swapped_blocks structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) * If it doesn't fit any, nothing will happen.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) * 3b) COW happens for NA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) * Check NA's bytenr against tree X's swapped_blocks, and get a hit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) * Then we do subtree scan on both subtrees OA and NA.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) * Resulting 6 tree blocks to be scanned (OA, OC, OD, NA, NC, ND).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) * Then no matter what we do to subvolume tree X, qgroup numbers will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) * still be correct.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * Then NA's record gets removed from X's swapped_blocks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * 4) Transaction commit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * Any record in X's swapped_blocks gets removed, since there is no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * modification to the swapped subtrees, no need to trigger heavy qgroup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * subtree rescan for them.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) * Record a dirty extent, and info qgroup to update quota on it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) * TODO: Use kmem cache to alloc it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) struct btrfs_qgroup_extent_record {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) struct rb_node node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) u64 bytenr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) u64 num_bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) * For qgroup reserved data space freeing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) * @data_rsv_refroot and @data_rsv will be recorded after
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) * BTRFS_ADD_DELAYED_EXTENT is called.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) * And will be used to free reserved qgroup space at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) * transaction commit time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) u32 data_rsv; /* reserved data space needs to be freed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) u64 data_rsv_refroot; /* which root the reserved data belongs to */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) struct ulist *old_roots;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) struct btrfs_qgroup_swapped_block {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) struct rb_node node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) int level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) bool trace_leaf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) /* bytenr/generation of the tree block in subvolume tree after swap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) u64 subvol_bytenr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) u64 subvol_generation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) /* bytenr/generation of the tree block in reloc tree after swap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) u64 reloc_bytenr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) u64 reloc_generation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) u64 last_snapshot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) struct btrfs_key first_key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) * Qgroup reservation types:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) * DATA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) * space reserved for data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) * META_PERTRANS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) * Space reserved for metadata (per-transaction)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) * Due to the fact that qgroup data is only updated at transaction commit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) * time, reserved space for metadata must be kept until transaction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) * commits.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) * Any metadata reserved that are used in btrfs_start_transaction() should
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) * be of this type.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) * META_PREALLOC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) * There are cases where metadata space is reserved before starting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) * transaction, and then btrfs_join_transaction() to get a trans handle.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) * Any metadata reserved for such usage should be of this type.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) * And after join_transaction() part (or all) of such reservation should
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) * be converted into META_PERTRANS.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) enum btrfs_qgroup_rsv_type {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) BTRFS_QGROUP_RSV_DATA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) BTRFS_QGROUP_RSV_META_PERTRANS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) BTRFS_QGROUP_RSV_META_PREALLOC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) BTRFS_QGROUP_RSV_LAST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) * Represents how many bytes we have reserved for this qgroup.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) * Each type should have different reservation behavior.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) * E.g, data follows its io_tree flag modification, while
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) * *currently* meta is just reserve-and-clear during transaction.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) * TODO: Add new type for reservation which can survive transaction commit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) * Current metadata reservation behavior is not suitable for such case.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) struct btrfs_qgroup_rsv {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) u64 values[BTRFS_QGROUP_RSV_LAST];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) * one struct for each qgroup, organized in fs_info->qgroup_tree.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) struct btrfs_qgroup {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) u64 qgroupid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) * state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) u64 rfer; /* referenced */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) u64 rfer_cmpr; /* referenced compressed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) u64 excl; /* exclusive */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) u64 excl_cmpr; /* exclusive compressed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) * limits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) u64 lim_flags; /* which limits are set */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) u64 max_rfer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) u64 max_excl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) u64 rsv_rfer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) u64 rsv_excl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) * reservation tracking
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) struct btrfs_qgroup_rsv rsv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) * lists
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) struct list_head groups; /* groups this group is member of */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) struct list_head members; /* groups that are members of this group */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) struct list_head dirty; /* dirty groups */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) struct rb_node node; /* tree of qgroups */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) * temp variables for accounting operations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) * Refer to qgroup_shared_accounting() for details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) u64 old_refcnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) u64 new_refcnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) * Sysfs kobjectid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) struct kobject kobj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) static inline u64 btrfs_qgroup_subvolid(u64 qgroupid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) return (qgroupid & ((1ULL << BTRFS_QGROUP_LEVEL_SHIFT) - 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) * For qgroup event trace points only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) #define QGROUP_RESERVE (1<<0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) #define QGROUP_RELEASE (1<<1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) #define QGROUP_FREE (1<<2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) int btrfs_quota_enable(struct btrfs_fs_info *fs_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) int btrfs_quota_disable(struct btrfs_fs_info *fs_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) int btrfs_qgroup_rescan(struct btrfs_fs_info *fs_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) void btrfs_qgroup_rescan_resume(struct btrfs_fs_info *fs_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) int btrfs_qgroup_wait_for_completion(struct btrfs_fs_info *fs_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) bool interruptible);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) int btrfs_add_qgroup_relation(struct btrfs_trans_handle *trans, u64 src,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) u64 dst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) int btrfs_del_qgroup_relation(struct btrfs_trans_handle *trans, u64 src,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) u64 dst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) int btrfs_create_qgroup(struct btrfs_trans_handle *trans, u64 qgroupid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) int btrfs_remove_qgroup(struct btrfs_trans_handle *trans, u64 qgroupid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) int btrfs_limit_qgroup(struct btrfs_trans_handle *trans, u64 qgroupid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) struct btrfs_qgroup_limit *limit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) int btrfs_read_qgroup_config(struct btrfs_fs_info *fs_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) void btrfs_free_qgroup_config(struct btrfs_fs_info *fs_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) struct btrfs_delayed_extent_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) * Inform qgroup to trace one dirty extent, its info is recorded in @record.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) * So qgroup can account it at transaction committing time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) * No lock version, caller must acquire delayed ref lock and allocated memory,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) * then call btrfs_qgroup_trace_extent_post() after exiting lock context.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) * Return 0 for success insert
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) * Return >0 for existing record, caller can free @record safely.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) * Error is not possible
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) int btrfs_qgroup_trace_extent_nolock(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) struct btrfs_fs_info *fs_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) struct btrfs_delayed_ref_root *delayed_refs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) struct btrfs_qgroup_extent_record *record);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) * Post handler after qgroup_trace_extent_nolock().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) * NOTE: Current qgroup does the expensive backref walk at transaction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) * committing time with TRANS_STATE_COMMIT_DOING, this blocks incoming
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) * new transaction.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) * This is designed to allow btrfs_find_all_roots() to get correct new_roots
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) * result.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) * However for old_roots there is no need to do backref walk at that time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) * since we search commit roots to walk backref and result will always be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) * correct.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) * Due to the nature of no lock version, we can't do backref there.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) * So we must call btrfs_qgroup_trace_extent_post() after exiting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) * spinlock context.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) * TODO: If we can fix and prove btrfs_find_all_roots() can get correct result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) * using current root, then we can move all expensive backref walk out of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) * transaction committing, but not now as qgroup accounting will be wrong again.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) int btrfs_qgroup_trace_extent_post(struct btrfs_fs_info *fs_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) struct btrfs_qgroup_extent_record *qrecord);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) * Inform qgroup to trace one dirty extent, specified by @bytenr and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) * @num_bytes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) * So qgroup can account it at commit trans time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) * Better encapsulated version, with memory allocation and backref walk for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) * commit roots.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) * So this can sleep.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) * Return 0 if the operation is done.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) * Return <0 for error, like memory allocation failure or invalid parameter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) * (NULL trans)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) int btrfs_qgroup_trace_extent(struct btrfs_trans_handle *trans, u64 bytenr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) u64 num_bytes, gfp_t gfp_flag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) * Inform qgroup to trace all leaf items of data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) * Return 0 for success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) * Return <0 for error(ENOMEM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) int btrfs_qgroup_trace_leaf_items(struct btrfs_trans_handle *trans,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) struct extent_buffer *eb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) * Inform qgroup to trace a whole subtree, including all its child tree
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) * blocks and data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) * The root tree block is specified by @root_eb.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) * Normally used by relocation(tree block swap) and subvolume deletion.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) * Return 0 for success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) * Return <0 for error(ENOMEM or tree search error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) int btrfs_qgroup_trace_subtree(struct btrfs_trans_handle *trans,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) struct extent_buffer *root_eb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) u64 root_gen, int root_level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) int btrfs_qgroup_account_extent(struct btrfs_trans_handle *trans, u64 bytenr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) u64 num_bytes, struct ulist *old_roots,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) struct ulist *new_roots);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) int btrfs_qgroup_account_extents(struct btrfs_trans_handle *trans);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) int btrfs_run_qgroups(struct btrfs_trans_handle *trans);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans, u64 srcid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) u64 objectid, struct btrfs_qgroup_inherit *inherit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) void btrfs_qgroup_free_refroot(struct btrfs_fs_info *fs_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) u64 ref_root, u64 num_bytes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) enum btrfs_qgroup_rsv_type type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) #ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) int btrfs_verify_qgroup_counts(struct btrfs_fs_info *fs_info, u64 qgroupid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) u64 rfer, u64 excl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) /* New io_tree based accurate qgroup reserve API */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) int btrfs_qgroup_reserve_data(struct btrfs_inode *inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) struct extent_changeset **reserved, u64 start, u64 len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) int btrfs_qgroup_release_data(struct btrfs_inode *inode, u64 start, u64 len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) int btrfs_qgroup_free_data(struct btrfs_inode *inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) struct extent_changeset *reserved, u64 start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) u64 len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) int btrfs_qgroup_reserve_meta(struct btrfs_root *root, int num_bytes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) enum btrfs_qgroup_rsv_type type, bool enforce);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) int __btrfs_qgroup_reserve_meta(struct btrfs_root *root, int num_bytes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) enum btrfs_qgroup_rsv_type type, bool enforce);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) /* Reserve metadata space for pertrans and prealloc type */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) static inline int btrfs_qgroup_reserve_meta_pertrans(struct btrfs_root *root,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) int num_bytes, bool enforce)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) return __btrfs_qgroup_reserve_meta(root, num_bytes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) BTRFS_QGROUP_RSV_META_PERTRANS, enforce);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) static inline int btrfs_qgroup_reserve_meta_prealloc(struct btrfs_root *root,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) int num_bytes, bool enforce)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) return __btrfs_qgroup_reserve_meta(root, num_bytes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) BTRFS_QGROUP_RSV_META_PREALLOC, enforce);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) void __btrfs_qgroup_free_meta(struct btrfs_root *root, int num_bytes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) enum btrfs_qgroup_rsv_type type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) /* Free per-transaction meta reservation for error handling */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) static inline void btrfs_qgroup_free_meta_pertrans(struct btrfs_root *root,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) int num_bytes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) __btrfs_qgroup_free_meta(root, num_bytes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) BTRFS_QGROUP_RSV_META_PERTRANS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) /* Pre-allocated meta reservation can be freed at need */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) static inline void btrfs_qgroup_free_meta_prealloc(struct btrfs_root *root,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) int num_bytes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) __btrfs_qgroup_free_meta(root, num_bytes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) BTRFS_QGROUP_RSV_META_PREALLOC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) * Per-transaction meta reservation should be all freed at transaction commit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) * time
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) void btrfs_qgroup_free_meta_all_pertrans(struct btrfs_root *root);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) * Convert @num_bytes of META_PREALLOCATED reservation to META_PERTRANS.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) * This is called when preallocated meta reservation needs to be used.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) * Normally after btrfs_join_transaction() call.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) void btrfs_qgroup_convert_reserved_meta(struct btrfs_root *root, int num_bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) void btrfs_qgroup_check_reserved_leak(struct btrfs_inode *inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) /* btrfs_qgroup_swapped_blocks related functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) void btrfs_qgroup_init_swapped_blocks(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) struct btrfs_qgroup_swapped_blocks *swapped_blocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) void btrfs_qgroup_clean_swapped_blocks(struct btrfs_root *root);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) int btrfs_qgroup_add_swapped_blocks(struct btrfs_trans_handle *trans,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) struct btrfs_root *subvol_root,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) struct btrfs_block_group *bg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) struct extent_buffer *subvol_parent, int subvol_slot,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) struct extent_buffer *reloc_parent, int reloc_slot,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) u64 last_snapshot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) int btrfs_qgroup_trace_subtree_after_cow(struct btrfs_trans_handle *trans,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) struct btrfs_root *root, struct extent_buffer *eb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) void btrfs_qgroup_destroy_extent_records(struct btrfs_transaction *trans);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) bool btrfs_check_quota_leak(struct btrfs_fs_info *fs_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) #endif