ronnie
2022-10-14 1504bb53e29d3d46222c0b3ea994fc494b48e153
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
#ifndef _RAID1_H
#define _RAID1_H
 
struct raid1_info {
   struct md_rdev    *rdev;
   sector_t    head_position;
 
   /* When choose the best device for a read (read_balance())
    * we try to keep sequential reads one the same device
    */
   sector_t    next_seq_sect;
   sector_t    seq_start;
};
 
/*
 * memory pools need a pointer to the mddev, so they can force an unplug
 * when memory is tight, and a count of the number of drives that the
 * pool was allocated for, so they know how much to allocate and free.
 * mddev->raid_disks cannot be used, as it can change while a pool is active
 * These two datums are stored in a kmalloced struct.
 * The 'raid_disks' here is twice the raid_disks in r1conf.
 * This allows space for each 'real' device can have a replacement in the
 * second half of the array.
 */
 
struct pool_info {
   struct mddev *mddev;
   int    raid_disks;
};
 
struct r1conf {
   struct mddev        *mddev;
   struct raid1_info    *mirrors;    /* twice 'raid_disks' to
                        * allow for replacements.
                        */
   int            raid_disks;
 
   /* During resync, read_balancing is only allowed on the part
    * of the array that has been resynced.  'next_resync' tells us
    * where that is.
    */
   sector_t        next_resync;
 
   /* When raid1 starts resync, we divide array into four partitions
    * |---------|--------------|---------------------|-------------|
    *        next_resync   start_next_window       end_window
    * start_next_window = next_resync + NEXT_NORMALIO_DISTANCE
    * end_window = start_next_window + NEXT_NORMALIO_DISTANCE
    * current_window_requests means the count of normalIO between
    *   start_next_window and end_window.
    * next_window_requests means the count of normalIO after end_window.
    * */
   sector_t        start_next_window;
   int            current_window_requests;
   int            next_window_requests;
 
   spinlock_t        device_lock;
 
   /* list of 'struct r1bio' that need to be processed by raid1d,
    * whether to retry a read, writeout a resync or recovery
    * block, or anything else.
    */
   struct list_head    retry_list;
   /* A separate list of r1bio which just need raid_end_bio_io called.
    * This mustn't happen for writes which had any errors if the superblock
    * needs to be written.
    */
   struct list_head    bio_end_io_list;
 
   /* queue pending writes to be submitted on unplug */
   struct bio_list        pending_bio_list;
   int            pending_count;
 
   /* for use when syncing mirrors:
    * We don't allow both normal IO and resync/recovery IO at
    * the same time - resync/recovery can only happen when there
    * is no other IO.  So when either is active, the other has to wait.
    * See more details description in raid1.c near raise_barrier().
    */
   wait_queue_head_t    wait_barrier;
   spinlock_t        resync_lock;
   int            nr_pending;
   int            nr_waiting;
   int            nr_queued;
   int            barrier;
   int            array_frozen;
 
   /* Set to 1 if a full sync is needed, (fresh device added).
    * Cleared when a sync completes.
    */
   int            fullsync;
 
   /* When the same as mddev->recovery_disabled we don't allow
    * recovery to be attempted as we expect a read error.
    */
   int            recovery_disabled;
 
   /* poolinfo contains information about the content of the
    * mempools - it changes when the array grows or shrinks
    */
   struct pool_info    *poolinfo;
   mempool_t        *r1bio_pool;
   mempool_t        *r1buf_pool;
 
   /* temporary buffer to synchronous IO when attempting to repair
    * a read error.
    */
   struct page        *tmppage;
 
   /* When taking over an array from a different personality, we store
    * the new thread here until we fully activate the array.
    */
   struct md_thread    *thread;
 
   /* Keep track of cluster resync window to send to other
    * nodes.
    */
   sector_t        cluster_sync_low;
   sector_t        cluster_sync_high;
 
};
 
/*
 * this is our 'private' RAID1 bio.
 *
 * it contains information about what kind of IO operations were started
 * for this RAID1 operation, and about their status:
 */
 
struct r1bio {
   atomic_t        remaining; /* 'have we finished' count,
                       * used from IRQ handlers
                       */
   atomic_t        behind_remaining; /* number of write-behind ios remaining
                        * in this BehindIO request
                        */
   sector_t        sector;
   sector_t        start_next_window;
   int            sectors;
   unsigned long        state;
   struct mddev        *mddev;
   /*
    * original bio going to /dev/mdx
    */
   struct bio        *master_bio;
   /*
    * if the IO is in READ direction, then this is where we read
    */
   int            read_disk;
 
   struct list_head    retry_list;
   /* Next two are only valid when R1BIO_BehindIO is set */
   struct bio_vec        *behind_bvecs;
   int            behind_page_count;
   /*
    * if the IO is in WRITE direction, then multiple bios are used.
    * We choose the number when they are allocated.
    */
   struct bio        *bios[0];
   /* DO NOT PUT ANY NEW FIELDS HERE - bios array is contiguously alloced*/
};
 
/* bits for r1bio.state */
#define    R1BIO_Uptodate    0
#define    R1BIO_IsSync    1
#define    R1BIO_Degraded    2
#define    R1BIO_BehindIO    3
/* Set ReadError on bios that experience a readerror so that
 * raid1d knows what to do with them.
 */
#define R1BIO_ReadError 4
/* For write-behind requests, we call bi_end_io when
 * the last non-write-behind device completes, providing
 * any write was successful.  Otherwise we call when
 * any write-behind write succeeds, otherwise we call
 * with failure when last write completes (and all failed).
 * Record that bi_end_io was called with this flag...
 */
#define    R1BIO_Returned 6
/* If a write for this request means we can clear some
 * known-bad-block records, we set this flag
 */
#define    R1BIO_MadeGood 7
#define    R1BIO_WriteError 8
#endif