Blame view
drivers/md/md-bitmap.c
70 KB
457c89965 treewide: Add SPD... |
1 |
// SPDX-License-Identifier: GPL-2.0-only |
32a7627cf [PATCH] md: optim... |
2 3 4 5 6 7 8 9 10 |
/* * bitmap.c two-level bitmap (C) Peter T. Breuer (ptb@ot.uc3m.es) 2003 * * bitmap_create - sets up the bitmap structure * bitmap_destroy - destroys the bitmap structure * * additions, Copyright (C) 2003-2004, Paul Clements, SteelEye Technology, Inc.: * - added disk storage for bitmap * - changes to allow various bitmap chunk sizes |
32a7627cf [PATCH] md: optim... |
11 12 13 14 15 16 |
*/ /* * Still to do: * * flush after percent set rather than just time based. (maybe both). |
32a7627cf [PATCH] md: optim... |
17 |
*/ |
bff61975b md: move lots of ... |
18 |
#include <linux/blkdev.h> |
32a7627cf [PATCH] md: optim... |
19 |
#include <linux/module.h> |
32a7627cf [PATCH] md: optim... |
20 21 22 |
#include <linux/errno.h> #include <linux/slab.h> #include <linux/init.h> |
32a7627cf [PATCH] md: optim... |
23 24 25 26 27 28 |
#include <linux/timer.h> #include <linux/sched.h> #include <linux/list.h> #include <linux/file.h> #include <linux/mount.h> #include <linux/buffer_head.h> |
57148964d md/bitmap: move p... |
29 |
#include <linux/seq_file.h> |
581dbd94d md/bitmap: add bl... |
30 |
#include <trace/events/block.h> |
43b2e5d86 md: move md_k.h f... |
31 |
#include "md.h" |
935fe0983 md: rename some d... |
32 |
#include "md-bitmap.h" |
32a7627cf [PATCH] md: optim... |
33 |
|
ac2f40be4 md/bitmap: white ... |
34 |
static inline char *bmname(struct bitmap *bitmap) |
32a7627cf [PATCH] md: optim... |
35 36 37 |
{ return bitmap->mddev ? mdname(bitmap->mddev) : "mdX"; } |
32a7627cf [PATCH] md: optim... |
38 |
/* |
32a7627cf [PATCH] md: optim... |
39 40 41 42 43 44 45 46 47 |
* check a page and, if necessary, allocate it (or hijack it if the alloc fails) * * 1) check to see if this page is allocated, if it's not then try to alloc * 2) if the alloc fails, set the page's hijacked flag so we'll use the * page pointer directly as a counter * * if we find our page, we increment the page's refcount so that it stays * allocated while we're using it */ |
e64e4018d md: Avoid namespa... |
48 49 |
static int md_bitmap_checkpage(struct bitmap_counts *bitmap, unsigned long page, int create, int no_hijack) |
ee305acef md: remove sparse... |
50 51 |
__releases(bitmap->lock) __acquires(bitmap->lock) |
32a7627cf [PATCH] md: optim... |
52 53 54 55 |
{ unsigned char *mappage; if (page >= bitmap->pages) { |
1187cf0a3 md: Allow write-i... |
56 57 58 59 |
/* This can happen if bitmap_start_sync goes beyond * End-of-device while looking for a whole page. * It is harmless. */ |
32a7627cf [PATCH] md: optim... |
60 61 |
return -EINVAL; } |
32a7627cf [PATCH] md: optim... |
62 63 64 65 66 67 68 69 |
if (bitmap->bp[page].hijacked) /* it's hijacked, don't try to alloc */ return 0; if (bitmap->bp[page].map) /* page is already allocated, just return */ return 0; if (!create) return -ENOENT; |
32a7627cf [PATCH] md: optim... |
70 |
/* this page has not been allocated yet */ |
ac2f40be4 md/bitmap: white ... |
71 |
spin_unlock_irq(&bitmap->lock); |
d95901433 md/bitmap: fix a ... |
72 73 74 75 76 77 78 79 80 81 82 83 84 |
/* It is possible that this is being called inside a * prepare_to_wait/finish_wait loop from raid5c:make_request(). * In general it is not permitted to sleep in that context as it * can cause the loop to spin freely. * That doesn't apply here as we can only reach this point * once with any loop. * When this function completes, either bp[page].map or * bp[page].hijacked. In either case, this function will * abort before getting to this point again. So there is * no risk of a free-spin, and so it is safe to assert * that sleeping here is allowed. */ sched_annotate_sleep(); |
792a1d4bb md/bitmap: remove... |
85 |
mappage = kzalloc(PAGE_SIZE, GFP_NOIO); |
ac2f40be4 md/bitmap: white ... |
86 87 88 |
spin_lock_irq(&bitmap->lock); if (mappage == NULL) { |
40cffcc0e md/bitmap: create... |
89 90 |
pr_debug("md/bitmap: map page allocation failed, hijacking "); |
c9d650322 md-cluster: alway... |
91 92 93 |
/* We don't support hijack for cluster raid */ if (no_hijack) return -ENOMEM; |
32a7627cf [PATCH] md: optim... |
94 95 |
/* failed - set the hijacked flag so that we can use the * pointer as a counter */ |
32a7627cf [PATCH] md: optim... |
96 97 |
if (!bitmap->bp[page].map) bitmap->bp[page].hijacked = 1; |
ac2f40be4 md/bitmap: white ... |
98 99 |
} else if (bitmap->bp[page].map || bitmap->bp[page].hijacked) { |
32a7627cf [PATCH] md: optim... |
100 |
/* somebody beat us to getting the page */ |
792a1d4bb md/bitmap: remove... |
101 |
kfree(mappage); |
ac2f40be4 md/bitmap: white ... |
102 |
} else { |
32a7627cf [PATCH] md: optim... |
103 |
|
ac2f40be4 md/bitmap: white ... |
104 |
/* no page was in place and we have one, so install it */ |
32a7627cf [PATCH] md: optim... |
105 |
|
ac2f40be4 md/bitmap: white ... |
106 107 108 |
bitmap->bp[page].map = mappage; bitmap->missing_pages--; } |
32a7627cf [PATCH] md: optim... |
109 110 |
return 0; } |
32a7627cf [PATCH] md: optim... |
111 112 113 |
/* if page is completely empty, put it back on the free list, or dealloc it */ /* if page was hijacked, unmark the flag so it might get alloced next time */ /* Note: lock should be held when calling this */ |
e64e4018d md: Avoid namespa... |
114 |
static void md_bitmap_checkfree(struct bitmap_counts *bitmap, unsigned long page) |
32a7627cf [PATCH] md: optim... |
115 116 117 118 119 120 121 122 123 124 125 |
{ char *ptr; if (bitmap->bp[page].count) /* page is still busy */ return; /* page is no longer in use, it can be released */ if (bitmap->bp[page].hijacked) { /* page was hijacked, undo this now */ bitmap->bp[page].hijacked = 0; bitmap->bp[page].map = NULL; |
ac2f40be4 md/bitmap: white ... |
126 127 128 129 130 |
} else { /* normal case, free the page */ ptr = bitmap->bp[page].map; bitmap->bp[page].map = NULL; bitmap->missing_pages++; |
792a1d4bb md/bitmap: remove... |
131 |
kfree(ptr); |
32a7627cf [PATCH] md: optim... |
132 |
} |
32a7627cf [PATCH] md: optim... |
133 |
} |
32a7627cf [PATCH] md: optim... |
134 135 136 |
/* * bitmap file handling - read and write the bitmap file and its superblock */ |
32a7627cf [PATCH] md: optim... |
137 138 139 |
/* * basic page I/O operations */ |
a654b9d8f [PATCH] md: allow... |
140 |
/* IO operations when bitmap is stored near all superblocks */ |
27581e5ae md/bitmap: centra... |
141 142 143 |
static int read_sb_page(struct mddev *mddev, loff_t offset, struct page *page, unsigned long index, int size) |
a654b9d8f [PATCH] md: allow... |
144 145 |
{ /* choose a good rdev and read the page from there */ |
3cb030020 md: removing type... |
146 |
struct md_rdev *rdev; |
a654b9d8f [PATCH] md: allow... |
147 |
sector_t target; |
a654b9d8f [PATCH] md: allow... |
148 |
|
dafb20fa3 md: tidy up rdev_... |
149 |
rdev_for_each(rdev, mddev) { |
b2d444d7a [PATCH] md: conve... |
150 |
if (! test_bit(In_sync, &rdev->flags) |
4aaf7694f md/bitmap: don't ... |
151 152 |
|| test_bit(Faulty, &rdev->flags) || test_bit(Bitmap_sync, &rdev->flags)) |
ab904d634 [PATCH] md: fix b... |
153 |
continue; |
ccebd4c41 md-new-param-to_s... |
154 |
target = offset + index * (PAGE_SIZE/512); |
a654b9d8f [PATCH] md: allow... |
155 |
|
2b193363e md: change type o... |
156 |
if (sync_page_io(rdev, target, |
e1defc4ff block: Do away wi... |
157 |
roundup(size, bdev_logical_block_size(rdev->bdev)), |
796a5cf08 md: use bio op ac... |
158 |
page, REQ_OP_READ, 0, true)) { |
ab904d634 [PATCH] md: fix b... |
159 |
page->index = index; |
27581e5ae md/bitmap: centra... |
160 |
return 0; |
ab904d634 [PATCH] md: fix b... |
161 162 |
} } |
27581e5ae md/bitmap: centra... |
163 |
return -EIO; |
a654b9d8f [PATCH] md: allow... |
164 |
} |
fd01b88c7 md: remove typede... |
165 |
static struct md_rdev *next_active_rdev(struct md_rdev *rdev, struct mddev *mddev) |
b2d2c4cea Fix problem with ... |
166 167 168 169 170 171 172 |
{ /* Iterate the disks of an mddev, using rcu to protect access to the * linked list, and raising the refcount of devices we return to ensure * they don't disappear while in use. * As devices are only added or removed when raid_disk is < 0 and * nr_pending is 0 and In_sync is clear, the entries we return will * still be in the same position on the list when we re-enter |
fd177481b raid: replace lis... |
173 |
* list_for_each_entry_continue_rcu. |
8532e3439 md/bitmap: remove... |
174 175 176 177 178 |
* * Note that if entered with 'rdev == NULL' to start at the * beginning, we temporarily assign 'rdev' to an address which * isn't really an rdev, but which can be used by * list_for_each_entry_continue_rcu() to find the first entry. |
b2d2c4cea Fix problem with ... |
179 |
*/ |
b2d2c4cea Fix problem with ... |
180 181 182 |
rcu_read_lock(); if (rdev == NULL) /* start at the beginning */ |
8532e3439 md/bitmap: remove... |
183 |
rdev = list_entry(&mddev->disks, struct md_rdev, same_set); |
b2d2c4cea Fix problem with ... |
184 185 186 |
else { /* release the previous rdev and start from there. */ rdev_dec_pending(rdev, mddev); |
b2d2c4cea Fix problem with ... |
187 |
} |
fd177481b raid: replace lis... |
188 |
list_for_each_entry_continue_rcu(rdev, &mddev->disks, same_set) { |
b2d2c4cea Fix problem with ... |
189 |
if (rdev->raid_disk >= 0 && |
b2d2c4cea Fix problem with ... |
190 191 192 193 194 195 196 197 198 199 |
!test_bit(Faulty, &rdev->flags)) { /* this is a usable devices */ atomic_inc(&rdev->nr_pending); rcu_read_unlock(); return rdev; } } rcu_read_unlock(); return NULL; } |
ab6085c79 md: don't write m... |
200 |
static int write_sb_page(struct bitmap *bitmap, struct page *page, int wait) |
a654b9d8f [PATCH] md: allow... |
201 |
{ |
46533ff7f md: Use REQ_FAILF... |
202 |
struct md_rdev *rdev; |
a6ff7e089 md: separate meta... |
203 |
struct block_device *bdev; |
fd01b88c7 md: remove typede... |
204 |
struct mddev *mddev = bitmap->mddev; |
1ec885cdd md/bitmap: move s... |
205 |
struct bitmap_storage *store = &bitmap->storage; |
a654b9d8f [PATCH] md: allow... |
206 |
|
46533ff7f md: Use REQ_FAILF... |
207 208 |
restart: rdev = NULL; |
b2d2c4cea Fix problem with ... |
209 |
while ((rdev = next_active_rdev(rdev, mddev)) != NULL) { |
ac2f40be4 md/bitmap: white ... |
210 211 |
int size = PAGE_SIZE; loff_t offset = mddev->bitmap_info.offset; |
a6ff7e089 md: separate meta... |
212 213 |
bdev = (rdev->meta_bdev) ? rdev->meta_bdev : rdev->bdev; |
9b1215c10 md/bitmap: store ... |
214 215 216 217 218 |
if (page->index == store->file_pages-1) { int last_page_size = store->bytes & (PAGE_SIZE-1); if (last_page_size == 0) last_page_size = PAGE_SIZE; size = roundup(last_page_size, |
a6ff7e089 md: separate meta... |
219 |
bdev_logical_block_size(bdev)); |
9b1215c10 md/bitmap: store ... |
220 |
} |
ac2f40be4 md/bitmap: white ... |
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 |
/* Just make sure we aren't corrupting data or * metadata */ if (mddev->external) { /* Bitmap could be anywhere. */ if (rdev->sb_start + offset + (page->index * (PAGE_SIZE/512)) > rdev->data_offset && rdev->sb_start + offset < (rdev->data_offset + mddev->dev_sectors + (PAGE_SIZE/512))) goto bad_alignment; } else if (offset < 0) { /* DATA BITMAP METADATA */ if (offset + (long)(page->index * (PAGE_SIZE/512)) + size/512 > 0) /* bitmap runs in to metadata */ goto bad_alignment; if (rdev->data_offset + mddev->dev_sectors > rdev->sb_start + offset) /* data runs in to bitmap */ goto bad_alignment; } else if (rdev->sb_start < rdev->data_offset) { /* METADATA BITMAP DATA */ if (rdev->sb_start + offset + page->index*(PAGE_SIZE/512) + size/512 > rdev->data_offset) /* bitmap runs in to data */ goto bad_alignment; } else { /* DATA METADATA BITMAP - no problems */ } md_super_write(mddev, rdev, rdev->sb_start + offset + page->index * (PAGE_SIZE/512), size, page); |
b2d2c4cea Fix problem with ... |
261 |
} |
a654b9d8f [PATCH] md: allow... |
262 |
|
46533ff7f md: Use REQ_FAILF... |
263 264 |
if (wait && md_super_wait(mddev) < 0) goto restart; |
a654b9d8f [PATCH] md: allow... |
265 |
return 0; |
4b80991c6 md: Protect acces... |
266 267 |
bad_alignment: |
4b80991c6 md: Protect acces... |
268 |
return -EINVAL; |
a654b9d8f [PATCH] md: allow... |
269 |
} |
e64e4018d md: Avoid namespa... |
270 |
static void md_bitmap_file_kick(struct bitmap *bitmap); |
32a7627cf [PATCH] md: optim... |
271 |
/* |
a654b9d8f [PATCH] md: allow... |
272 |
* write out a page to a file |
32a7627cf [PATCH] md: optim... |
273 |
*/ |
4ad136637 md: change bitmap... |
274 |
static void write_page(struct bitmap *bitmap, struct page *page, int wait) |
32a7627cf [PATCH] md: optim... |
275 |
{ |
d785a06a0 [PATCH] md/bitmap... |
276 |
struct buffer_head *bh; |
32a7627cf [PATCH] md: optim... |
277 |
|
1ec885cdd md/bitmap: move s... |
278 |
if (bitmap->storage.file == NULL) { |
f0d76d70b md: check that in... |
279 280 |
switch (write_sb_page(bitmap, page, wait)) { case -EINVAL: |
b405fe91e md/bitmap: use se... |
281 |
set_bit(BITMAP_WRITE_ERROR, &bitmap->flags); |
f0d76d70b md: check that in... |
282 |
} |
4ad136637 md: change bitmap... |
283 |
} else { |
a654b9d8f [PATCH] md: allow... |
284 |
|
4ad136637 md: change bitmap... |
285 |
bh = page_buffers(page); |
c708443c0 [PATCH] md: make ... |
286 |
|
4ad136637 md: change bitmap... |
287 288 289 290 |
while (bh && bh->b_blocknr) { atomic_inc(&bitmap->pending_writes); set_buffer_locked(bh); set_buffer_mapped(bh); |
2a222ca99 fs: have submit_b... |
291 |
submit_bh(REQ_OP_WRITE, REQ_SYNC, bh); |
4ad136637 md: change bitmap... |
292 293 |
bh = bh->b_this_page; } |
d785a06a0 [PATCH] md/bitmap... |
294 |
|
ac2f40be4 md/bitmap: white ... |
295 |
if (wait) |
4ad136637 md: change bitmap... |
296 297 |
wait_event(bitmap->write_wait, atomic_read(&bitmap->pending_writes)==0); |
8a5e9cf1d [PATCH] md: make ... |
298 |
} |
b405fe91e md/bitmap: use se... |
299 |
if (test_bit(BITMAP_WRITE_ERROR, &bitmap->flags)) |
e64e4018d md: Avoid namespa... |
300 |
md_bitmap_file_kick(bitmap); |
d785a06a0 [PATCH] md/bitmap... |
301 302 303 304 305 |
} static void end_bitmap_write(struct buffer_head *bh, int uptodate) { struct bitmap *bitmap = bh->b_private; |
32a7627cf [PATCH] md: optim... |
306 |
|
b405fe91e md/bitmap: use se... |
307 308 |
if (!uptodate) set_bit(BITMAP_WRITE_ERROR, &bitmap->flags); |
d785a06a0 [PATCH] md/bitmap... |
309 310 311 |
if (atomic_dec_and_test(&bitmap->pending_writes)) wake_up(&bitmap->write_wait); } |
32a7627cf [PATCH] md: optim... |
312 |
|
d785a06a0 [PATCH] md/bitmap... |
313 314 |
static void free_buffers(struct page *page) { |
27581e5ae md/bitmap: centra... |
315 |
struct buffer_head *bh; |
77ad4bc70 [PATCH] md: enabl... |
316 |
|
27581e5ae md/bitmap: centra... |
317 318 319 320 |
if (!PagePrivate(page)) return; bh = page_buffers(page); |
d785a06a0 [PATCH] md/bitmap... |
321 322 323 324 |
while (bh) { struct buffer_head *next = bh->b_this_page; free_buffer_head(bh); bh = next; |
77ad4bc70 [PATCH] md: enabl... |
325 |
} |
db2c1d86c md: remove __clea... |
326 |
detach_page_private(page); |
d785a06a0 [PATCH] md/bitmap... |
327 |
put_page(page); |
32a7627cf [PATCH] md: optim... |
328 |
} |
d785a06a0 [PATCH] md/bitmap... |
329 330 331 332 333 334 335 |
/* read a page from a file. * We both read the page, and attach buffers to the page to record the * address of each block (using bmap). These addresses will be used * to write the block later, completely bypassing the filesystem. * This usage is similar to how swap files are handled, and allows us * to write to a file with no concerns of memory allocation failing. */ |
27581e5ae md/bitmap: centra... |
336 337 338 339 |
static int read_page(struct file *file, unsigned long index, struct bitmap *bitmap, unsigned long count, struct page *page) |
32a7627cf [PATCH] md: optim... |
340 |
{ |
27581e5ae md/bitmap: centra... |
341 |
int ret = 0; |
496ad9aa8 new helper: file_... |
342 |
struct inode *inode = file_inode(file); |
d785a06a0 [PATCH] md/bitmap... |
343 |
struct buffer_head *bh; |
30460e1ea fs: Enable bmap()... |
344 |
sector_t block, blk_cur; |
313b825fa md: only calculat... |
345 |
unsigned long blocksize = i_blocksize(inode); |
32a7627cf [PATCH] md: optim... |
346 |
|
36a4e1fe0 md: remove PRINTK... |
347 348 349 |
pr_debug("read bitmap file (%dB @ %llu) ", (int)PAGE_SIZE, (unsigned long long)index << PAGE_SHIFT); |
32a7627cf [PATCH] md: optim... |
350 |
|
313b825fa md: only calculat... |
351 |
bh = alloc_page_buffers(page, blocksize, false); |
d785a06a0 [PATCH] md/bitmap... |
352 |
if (!bh) { |
27581e5ae md/bitmap: centra... |
353 |
ret = -ENOMEM; |
32a7627cf [PATCH] md: optim... |
354 355 |
goto out; } |
db2c1d86c md: remove __clea... |
356 |
attach_page_private(page, bh); |
30460e1ea fs: Enable bmap()... |
357 |
blk_cur = index << (PAGE_SHIFT - inode->i_blkbits); |
d785a06a0 [PATCH] md/bitmap... |
358 |
while (bh) { |
30460e1ea fs: Enable bmap()... |
359 |
block = blk_cur; |
d785a06a0 [PATCH] md/bitmap... |
360 361 362 |
if (count == 0) bh->b_blocknr = 0; else { |
30460e1ea fs: Enable bmap()... |
363 364 |
ret = bmap(inode, &block); if (ret || !block) { |
27581e5ae md/bitmap: centra... |
365 |
ret = -EINVAL; |
30460e1ea fs: Enable bmap()... |
366 |
bh->b_blocknr = 0; |
d785a06a0 [PATCH] md/bitmap... |
367 368 |
goto out; } |
30460e1ea fs: Enable bmap()... |
369 370 |
bh->b_blocknr = block; |
d785a06a0 [PATCH] md/bitmap... |
371 |
bh->b_bdev = inode->i_sb->s_bdev; |
313b825fa md: only calculat... |
372 |
if (count < blocksize) |
d785a06a0 [PATCH] md/bitmap... |
373 374 |
count = 0; else |
313b825fa md: only calculat... |
375 |
count -= blocksize; |
d785a06a0 [PATCH] md/bitmap... |
376 377 378 |
bh->b_end_io = end_bitmap_write; bh->b_private = bitmap; |
ce25c31bd [PATCH] md: Chang... |
379 380 381 |
atomic_inc(&bitmap->pending_writes); set_buffer_locked(bh); set_buffer_mapped(bh); |
2a222ca99 fs: have submit_b... |
382 |
submit_bh(REQ_OP_READ, 0, bh); |
d785a06a0 [PATCH] md/bitmap... |
383 |
} |
30460e1ea fs: Enable bmap()... |
384 |
blk_cur++; |
d785a06a0 [PATCH] md/bitmap... |
385 386 |
bh = bh->b_this_page; } |
d785a06a0 [PATCH] md/bitmap... |
387 |
page->index = index; |
ce25c31bd [PATCH] md: Chang... |
388 389 390 |
wait_event(bitmap->write_wait, atomic_read(&bitmap->pending_writes)==0); |
b405fe91e md/bitmap: use se... |
391 |
if (test_bit(BITMAP_WRITE_ERROR, &bitmap->flags)) |
27581e5ae md/bitmap: centra... |
392 |
ret = -EIO; |
32a7627cf [PATCH] md: optim... |
393 |
out: |
27581e5ae md/bitmap: centra... |
394 |
if (ret) |
ec0cc2268 md/bitmap: change... |
395 396 397 398 399 |
pr_err("md: bitmap read error: (%dB @ %llu): %d ", (int)PAGE_SIZE, (unsigned long long)index << PAGE_SHIFT, ret); |
27581e5ae md/bitmap: centra... |
400 |
return ret; |
32a7627cf [PATCH] md: optim... |
401 402 403 404 405 |
} /* * bitmap file superblock operations */ |
85c9ccd4f md/bitmap: Don't ... |
406 |
/* |
e64e4018d md: Avoid namespa... |
407 |
* md_bitmap_wait_writes() should be called before writing any bitmap |
85c9ccd4f md/bitmap: Don't ... |
408 |
* blocks, to ensure previous writes, particularly from |
e64e4018d md: Avoid namespa... |
409 |
* md_bitmap_daemon_work(), have completed. |
85c9ccd4f md/bitmap: Don't ... |
410 |
*/ |
e64e4018d md: Avoid namespa... |
411 |
static void md_bitmap_wait_writes(struct bitmap *bitmap) |
85c9ccd4f md/bitmap: Don't ... |
412 413 414 415 416 |
{ if (bitmap->storage.file) wait_event(bitmap->write_wait, atomic_read(&bitmap->pending_writes)==0); else |
46533ff7f md: Use REQ_FAILF... |
417 418 419 420 421 422 423 |
/* Note that we ignore the return value. The writes * might have failed, but that would just mean that * some bits which should be cleared haven't been, * which is safe. The relevant bitmap blocks will * probably get written again, but there is no great * loss if they aren't. */ |
85c9ccd4f md/bitmap: Don't ... |
424 425 |
md_super_wait(bitmap->mddev); } |
32a7627cf [PATCH] md: optim... |
426 |
/* update the event counter and sync the superblock to disk */ |
e64e4018d md: Avoid namespa... |
427 |
void md_bitmap_update_sb(struct bitmap *bitmap) |
32a7627cf [PATCH] md: optim... |
428 429 |
{ bitmap_super_t *sb; |
32a7627cf [PATCH] md: optim... |
430 431 |
if (!bitmap || !bitmap->mddev) /* no bitmap for this array */ |
4ad136637 md: change bitmap... |
432 |
return; |
ece5cff0d md: Support write... |
433 434 |
if (bitmap->mddev->bitmap_info.external) return; |
1ec885cdd md/bitmap: move s... |
435 |
if (!bitmap->storage.sb_page) /* no superblock */ |
4ad136637 md: change bitmap... |
436 |
return; |
1ec885cdd md/bitmap: move s... |
437 |
sb = kmap_atomic(bitmap->storage.sb_page); |
32a7627cf [PATCH] md: optim... |
438 |
sb->events = cpu_to_le64(bitmap->mddev->events); |
8258c5320 md/bitmap: fix sa... |
439 |
if (bitmap->mddev->events < bitmap->events_cleared) |
a0da84f35 Improve setting o... |
440 441 |
/* rocking back to read-only */ bitmap->events_cleared = bitmap->mddev->events; |
8258c5320 md/bitmap: fix sa... |
442 |
sb->events_cleared = cpu_to_le64(bitmap->events_cleared); |
97f0eb9f0 md/bitmap: clear ... |
443 444 445 446 447 |
/* * clear BITMAP_WRITE_ERROR bit to protect against the case that * a bitmap write error occurred but the later writes succeeded. */ sb->state = cpu_to_le32(bitmap->flags & ~BIT(BITMAP_WRITE_ERROR)); |
43a705076 md: support updat... |
448 449 450 |
/* Just in case these have been changed via sysfs: */ sb->daemon_sleep = cpu_to_le32(bitmap->mddev->bitmap_info.daemon_sleep/HZ); sb->write_behind = cpu_to_le32(bitmap->mddev->bitmap_info.max_write_behind); |
b81a04048 md/bitmap: make s... |
451 452 453 |
/* This might have been changed by a reshape */ sb->sync_size = cpu_to_le64(bitmap->mddev->resync_max_sectors); sb->chunksize = cpu_to_le32(bitmap->mddev->bitmap_info.chunksize); |
c4ce867fd Introduce md_clus... |
454 |
sb->nodes = cpu_to_le32(bitmap->mddev->bitmap_info.nodes); |
1dff2b87a md/bitmap: record... |
455 456 |
sb->sectors_reserved = cpu_to_le32(bitmap->mddev-> bitmap_info.space); |
b2f46e688 md: remove the se... |
457 |
kunmap_atomic(sb); |
1ec885cdd md/bitmap: move s... |
458 |
write_page(bitmap, bitmap->storage.sb_page, 1); |
32a7627cf [PATCH] md: optim... |
459 |
} |
e64e4018d md: Avoid namespa... |
460 |
EXPORT_SYMBOL(md_bitmap_update_sb); |
32a7627cf [PATCH] md: optim... |
461 462 |
/* print out the bitmap file superblock */ |
e64e4018d md: Avoid namespa... |
463 |
void md_bitmap_print_sb(struct bitmap *bitmap) |
32a7627cf [PATCH] md: optim... |
464 465 |
{ bitmap_super_t *sb; |
1ec885cdd md/bitmap: move s... |
466 |
if (!bitmap || !bitmap->storage.sb_page) |
32a7627cf [PATCH] md: optim... |
467 |
return; |
1ec885cdd md/bitmap: move s... |
468 |
sb = kmap_atomic(bitmap->storage.sb_page); |
ec0cc2268 md/bitmap: change... |
469 470 471 472 473 474 475 476 |
pr_debug("%s: bitmap file superblock: ", bmname(bitmap)); pr_debug(" magic: %08x ", le32_to_cpu(sb->magic)); pr_debug(" version: %d ", le32_to_cpu(sb->version)); pr_debug(" uuid: %08x.%08x.%08x.%08x ", |
c35403f82 md: use correct t... |
477 478 479 480 |
le32_to_cpu(*(__le32 *)(sb->uuid+0)), le32_to_cpu(*(__le32 *)(sb->uuid+4)), le32_to_cpu(*(__le32 *)(sb->uuid+8)), le32_to_cpu(*(__le32 *)(sb->uuid+12))); |
ec0cc2268 md/bitmap: change... |
481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 |
pr_debug(" events: %llu ", (unsigned long long) le64_to_cpu(sb->events)); pr_debug("events cleared: %llu ", (unsigned long long) le64_to_cpu(sb->events_cleared)); pr_debug(" state: %08x ", le32_to_cpu(sb->state)); pr_debug(" chunksize: %d B ", le32_to_cpu(sb->chunksize)); pr_debug(" daemon sleep: %ds ", le32_to_cpu(sb->daemon_sleep)); pr_debug(" sync size: %llu KB ", (unsigned long long)le64_to_cpu(sb->sync_size)/2); pr_debug("max write behind: %d ", le32_to_cpu(sb->write_behind)); |
b2f46e688 md: remove the se... |
498 |
kunmap_atomic(sb); |
32a7627cf [PATCH] md: optim... |
499 |
} |
9c81075f4 MD: support initi... |
500 501 502 503 504 505 506 507 508 509 510 |
/* * bitmap_new_disk_sb * @bitmap * * This function is somewhat the reverse of bitmap_read_sb. bitmap_read_sb * reads and verifies the on-disk bitmap superblock and populates bitmap_info. * This function verifies 'bitmap_info' and populates the on-disk bitmap * structure, which is to be written to disk. * * Returns: 0 on success, -Exxx on error */ |
e64e4018d md: Avoid namespa... |
511 |
static int md_bitmap_new_disk_sb(struct bitmap *bitmap) |
9c81075f4 MD: support initi... |
512 513 514 |
{ bitmap_super_t *sb; unsigned long chunksize, daemon_sleep, write_behind; |
9c81075f4 MD: support initi... |
515 |
|
d3b178adb md: Skip cluster ... |
516 |
bitmap->storage.sb_page = alloc_page(GFP_KERNEL | __GFP_ZERO); |
582e2e056 md/bitmap:Don't u... |
517 518 |
if (bitmap->storage.sb_page == NULL) return -ENOMEM; |
1ec885cdd md/bitmap: move s... |
519 |
bitmap->storage.sb_page->index = 0; |
9c81075f4 MD: support initi... |
520 |
|
1ec885cdd md/bitmap: move s... |
521 |
sb = kmap_atomic(bitmap->storage.sb_page); |
9c81075f4 MD: support initi... |
522 523 524 525 526 527 528 |
sb->magic = cpu_to_le32(BITMAP_MAGIC); sb->version = cpu_to_le32(BITMAP_MAJOR_HI); chunksize = bitmap->mddev->bitmap_info.chunksize; BUG_ON(!chunksize); if (!is_power_of_2(chunksize)) { |
b2f46e688 md: remove the se... |
529 |
kunmap_atomic(sb); |
ec0cc2268 md/bitmap: change... |
530 531 |
pr_warn("bitmap chunksize not a power of 2 "); |
9c81075f4 MD: support initi... |
532 533 534 535 536 |
return -EINVAL; } sb->chunksize = cpu_to_le32(chunksize); daemon_sleep = bitmap->mddev->bitmap_info.daemon_sleep; |
c97e0602b md/bitmap: remove... |
537 |
if (!daemon_sleep || (daemon_sleep > MAX_SCHEDULE_TIMEOUT)) { |
ec0cc2268 md/bitmap: change... |
538 539 |
pr_debug("Choosing daemon_sleep default (5 sec) "); |
9c81075f4 MD: support initi... |
540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 |
daemon_sleep = 5 * HZ; } sb->daemon_sleep = cpu_to_le32(daemon_sleep); bitmap->mddev->bitmap_info.daemon_sleep = daemon_sleep; /* * FIXME: write_behind for RAID1. If not specified, what * is a good choice? We choose COUNTER_MAX / 2 arbitrarily. */ write_behind = bitmap->mddev->bitmap_info.max_write_behind; if (write_behind > COUNTER_MAX) write_behind = COUNTER_MAX / 2; sb->write_behind = cpu_to_le32(write_behind); bitmap->mddev->bitmap_info.max_write_behind = write_behind; /* keep the array size field of the bitmap superblock up to date */ sb->sync_size = cpu_to_le64(bitmap->mddev->resync_max_sectors); memcpy(sb->uuid, bitmap->mddev->uuid, 16); |
b405fe91e md/bitmap: use se... |
559 |
set_bit(BITMAP_STALE, &bitmap->flags); |
84e923453 md/bitmap: remove... |
560 |
sb->state = cpu_to_le32(bitmap->flags); |
9c81075f4 MD: support initi... |
561 562 |
bitmap->events_cleared = bitmap->mddev->events; sb->events_cleared = cpu_to_le64(bitmap->mddev->events); |
d3b178adb md: Skip cluster ... |
563 |
bitmap->mddev->bitmap_info.nodes = 0; |
9c81075f4 MD: support initi... |
564 |
|
b2f46e688 md: remove the se... |
565 |
kunmap_atomic(sb); |
9c81075f4 MD: support initi... |
566 567 568 |
return 0; } |
32a7627cf [PATCH] md: optim... |
569 |
/* read the superblock from the bitmap file and initialize some bitmap fields */ |
e64e4018d md: Avoid namespa... |
570 |
static int md_bitmap_read_sb(struct bitmap *bitmap) |
32a7627cf [PATCH] md: optim... |
571 572 573 |
{ char *reason = NULL; bitmap_super_t *sb; |
4b6d287f6 [PATCH] md: add w... |
574 |
unsigned long chunksize, daemon_sleep, write_behind; |
32a7627cf [PATCH] md: optim... |
575 |
unsigned long long events; |
c4ce867fd Introduce md_clus... |
576 |
int nodes = 0; |
1dff2b87a md/bitmap: record... |
577 |
unsigned long sectors_reserved = 0; |
32a7627cf [PATCH] md: optim... |
578 |
int err = -EINVAL; |
27581e5ae md/bitmap: centra... |
579 |
struct page *sb_page; |
33e38ac68 md-cluster: fix b... |
580 |
loff_t offset = bitmap->mddev->bitmap_info.offset; |
32a7627cf [PATCH] md: optim... |
581 |
|
1ec885cdd md/bitmap: move s... |
582 |
if (!bitmap->storage.file && !bitmap->mddev->bitmap_info.offset) { |
ef99bf480 md/bitmap: allow ... |
583 584 585 |
chunksize = 128 * 1024 * 1024; daemon_sleep = 5 * HZ; write_behind = 0; |
b405fe91e md/bitmap: use se... |
586 |
set_bit(BITMAP_STALE, &bitmap->flags); |
ef99bf480 md/bitmap: allow ... |
587 588 589 |
err = 0; goto out_no_sb; } |
32a7627cf [PATCH] md: optim... |
590 |
/* page 0 is the superblock, read it... */ |
27581e5ae md/bitmap: centra... |
591 592 593 |
sb_page = alloc_page(GFP_KERNEL); if (!sb_page) return -ENOMEM; |
1ec885cdd md/bitmap: move s... |
594 |
bitmap->storage.sb_page = sb_page; |
27581e5ae md/bitmap: centra... |
595 |
|
b97e92574 Use separate bitm... |
596 |
re_read: |
f9209a323 bitmap_create ret... |
597 598 |
/* If cluster_slot is set, the cluster is setup */ if (bitmap->cluster_slot >= 0) { |
3b0e6aacb md/bitmap: use se... |
599 |
sector_t bm_blocks = bitmap->mddev->resync_max_sectors; |
f9209a323 bitmap_create ret... |
600 |
|
a913096de md/bitmap: md_bit... |
601 602 |
bm_blocks = DIV_ROUND_UP_SECTOR_T(bm_blocks, (bitmap->mddev->bitmap_info.chunksize >> 9)); |
124eb761e md: Fix bitmap of... |
603 604 605 |
/* bits to bytes */ bm_blocks = ((bm_blocks+7) >> 3) + sizeof(bitmap_super_t); /* to 4k blocks */ |
935f3d4fc md/bitmap: fix in... |
606 |
bm_blocks = DIV_ROUND_UP_SECTOR_T(bm_blocks, 4096); |
33e38ac68 md-cluster: fix b... |
607 |
offset = bitmap->mddev->bitmap_info.offset + (bitmap->cluster_slot * (bm_blocks << 3)); |
ec0cc2268 md/bitmap: change... |
608 609 |
pr_debug("%s:%d bm slot: %d offset: %llu ", __func__, __LINE__, |
33e38ac68 md-cluster: fix b... |
610 |
bitmap->cluster_slot, offset); |
f9209a323 bitmap_create ret... |
611 |
} |
1ec885cdd md/bitmap: move s... |
612 613 |
if (bitmap->storage.file) { loff_t isize = i_size_read(bitmap->storage.file->f_mapping->host); |
f49d5e62d [PATCH] md: avoid... |
614 |
int bytes = isize > PAGE_SIZE ? PAGE_SIZE : isize; |
1ec885cdd md/bitmap: move s... |
615 |
err = read_page(bitmap->storage.file, 0, |
27581e5ae md/bitmap: centra... |
616 |
bitmap, bytes, sb_page); |
f49d5e62d [PATCH] md: avoid... |
617 |
} else { |
27581e5ae md/bitmap: centra... |
618 |
err = read_sb_page(bitmap->mddev, |
33e38ac68 md-cluster: fix b... |
619 |
offset, |
27581e5ae md/bitmap: centra... |
620 |
sb_page, |
938b533d4 md/bitmap: revert... |
621 |
0, sizeof(bitmap_super_t)); |
a654b9d8f [PATCH] md: allow... |
622 |
} |
27581e5ae md/bitmap: centra... |
623 |
if (err) |
32a7627cf [PATCH] md: optim... |
624 |
return err; |
32a7627cf [PATCH] md: optim... |
625 |
|
b97e92574 Use separate bitm... |
626 |
err = -EINVAL; |
27581e5ae md/bitmap: centra... |
627 |
sb = kmap_atomic(sb_page); |
32a7627cf [PATCH] md: optim... |
628 |
|
32a7627cf [PATCH] md: optim... |
629 |
chunksize = le32_to_cpu(sb->chunksize); |
1b04be96f md: change daemon... |
630 |
daemon_sleep = le32_to_cpu(sb->daemon_sleep) * HZ; |
4b6d287f6 [PATCH] md: add w... |
631 |
write_behind = le32_to_cpu(sb->write_behind); |
1dff2b87a md/bitmap: record... |
632 |
sectors_reserved = le32_to_cpu(sb->sectors_reserved); |
3c462c880 md: Increment ver... |
633 634 |
/* Setup nodes/clustername only if bitmap version is * cluster-compatible |
d3b178adb md: Skip cluster ... |
635 |
*/ |
3c462c880 md: Increment ver... |
636 |
if (sb->version == cpu_to_le32(BITMAP_MAJOR_CLUSTERED)) { |
d3b178adb md: Skip cluster ... |
637 638 639 640 |
nodes = le32_to_cpu(sb->nodes); strlcpy(bitmap->mddev->bitmap_info.cluster_name, sb->cluster_name, 64); } |
32a7627cf [PATCH] md: optim... |
641 642 643 644 |
/* verify that the bitmap-specific fields are valid */ if (sb->magic != cpu_to_le32(BITMAP_MAGIC)) reason = "bad magic"; |
bd926c63b [PATCH] md: make ... |
645 |
else if (le32_to_cpu(sb->version) < BITMAP_MAJOR_LO || |
3c462c880 md: Increment ver... |
646 |
le32_to_cpu(sb->version) > BITMAP_MAJOR_CLUSTERED) |
32a7627cf [PATCH] md: optim... |
647 |
reason = "unrecognized superblock version"; |
1187cf0a3 md: Allow write-i... |
648 |
else if (chunksize < 512) |
7dd5d34c6 [PATCH] md: remov... |
649 |
reason = "bitmap chunksize too small"; |
d744540cd MD: use is_power_... |
650 |
else if (!is_power_of_2(chunksize)) |
32a7627cf [PATCH] md: optim... |
651 |
reason = "bitmap chunksize not a power of 2"; |
1b04be96f md: change daemon... |
652 |
else if (daemon_sleep < 1 || daemon_sleep > MAX_SCHEDULE_TIMEOUT) |
7dd5d34c6 [PATCH] md: remov... |
653 |
reason = "daemon sleep period out of range"; |
4b6d287f6 [PATCH] md: add w... |
654 655 |
else if (write_behind > COUNTER_MAX) reason = "write-behind limit out of range (0 - 16383)"; |
32a7627cf [PATCH] md: optim... |
656 |
if (reason) { |
ec0cc2268 md/bitmap: change... |
657 658 |
pr_warn("%s: invalid bitmap file superblock: %s ", |
32a7627cf [PATCH] md: optim... |
659 660 661 662 663 664 |
bmname(bitmap), reason); goto out; } /* keep the array size field of the bitmap superblock up to date */ sb->sync_size = cpu_to_le64(bitmap->mddev->resync_max_sectors); |
278c1ca2f md/bitmap: change... |
665 666 667 668 669 670 |
if (bitmap->mddev->persistent) { /* * We have a persistent array superblock, so compare the * bitmap's UUID and event counter to the mddev's */ if (memcmp(sb->uuid, bitmap->mddev->uuid, 16)) { |
ec0cc2268 md/bitmap: change... |
671 672 673 |
pr_warn("%s: bitmap superblock UUID mismatch ", bmname(bitmap)); |
278c1ca2f md/bitmap: change... |
674 675 676 |
goto out; } events = le64_to_cpu(sb->events); |
b97e92574 Use separate bitm... |
677 |
if (!nodes && (events < bitmap->mddev->events)) { |
ec0cc2268 md/bitmap: change... |
678 679 680 681 |
pr_warn("%s: bitmap file is out of date (%llu < %llu) -- forcing full recovery ", bmname(bitmap), events, (unsigned long long) bitmap->mddev->events); |
b405fe91e md/bitmap: use se... |
682 |
set_bit(BITMAP_STALE, &bitmap->flags); |
278c1ca2f md/bitmap: change... |
683 |
} |
32a7627cf [PATCH] md: optim... |
684 |
} |
278c1ca2f md/bitmap: change... |
685 |
|
32a7627cf [PATCH] md: optim... |
686 |
/* assign fields using values from superblock */ |
4f2e639af [PATCH] md: endia... |
687 |
bitmap->flags |= le32_to_cpu(sb->state); |
bd926c63b [PATCH] md: make ... |
688 |
if (le32_to_cpu(sb->version) == BITMAP_MAJOR_HOSTENDIAN) |
b405fe91e md/bitmap: use se... |
689 |
set_bit(BITMAP_HOSTENDIAN, &bitmap->flags); |
32a7627cf [PATCH] md: optim... |
690 |
bitmap->events_cleared = le64_to_cpu(sb->events_cleared); |
cf921cc19 Add node recovery... |
691 |
strlcpy(bitmap->mddev->bitmap_info.cluster_name, sb->cluster_name, 64); |
32a7627cf [PATCH] md: optim... |
692 |
err = 0; |
b97e92574 Use separate bitm... |
693 |
|
32a7627cf [PATCH] md: optim... |
694 |
out: |
b2f46e688 md: remove the se... |
695 |
kunmap_atomic(sb); |
3560741e3 md: fix several t... |
696 |
/* Assigning chunksize is required for "re_read" */ |
f9209a323 bitmap_create ret... |
697 |
bitmap->mddev->bitmap_info.chunksize = chunksize; |
f73572731 md: Skip cluster ... |
698 |
if (err == 0 && nodes && (bitmap->cluster_slot < 0)) { |
b97e92574 Use separate bitm... |
699 700 |
err = md_setup_cluster(bitmap->mddev, nodes); if (err) { |
ec0cc2268 md/bitmap: change... |
701 702 703 |
pr_warn("%s: Could not setup cluster service (%d) ", bmname(bitmap), err); |
b97e92574 Use separate bitm... |
704 705 706 |
goto out_no_sb; } bitmap->cluster_slot = md_cluster_ops->slot_number(bitmap->mddev); |
b97e92574 Use separate bitm... |
707 708 |
goto re_read; } |
ef99bf480 md/bitmap: allow ... |
709 |
out_no_sb: |
b405fe91e md/bitmap: use se... |
710 |
if (test_bit(BITMAP_STALE, &bitmap->flags)) |
ef99bf480 md/bitmap: allow ... |
711 712 713 714 |
bitmap->events_cleared = bitmap->mddev->events; bitmap->mddev->bitmap_info.chunksize = chunksize; bitmap->mddev->bitmap_info.daemon_sleep = daemon_sleep; bitmap->mddev->bitmap_info.max_write_behind = write_behind; |
c4ce867fd Introduce md_clus... |
715 |
bitmap->mddev->bitmap_info.nodes = nodes; |
1dff2b87a md/bitmap: record... |
716 717 718 |
if (bitmap->mddev->bitmap_info.space == 0 || bitmap->mddev->bitmap_info.space > sectors_reserved) bitmap->mddev->bitmap_info.space = sectors_reserved; |
b97e92574 Use separate bitm... |
719 |
if (err) { |
e64e4018d md: Avoid namespa... |
720 |
md_bitmap_print_sb(bitmap); |
f9209a323 bitmap_create ret... |
721 |
if (bitmap->cluster_slot < 0) |
b97e92574 Use separate bitm... |
722 723 |
md_cluster_stop(bitmap->mddev); } |
32a7627cf [PATCH] md: optim... |
724 725 |
return err; } |
32a7627cf [PATCH] md: optim... |
726 727 728 |
/* * general bitmap file operations */ |
ece5cff0d md: Support write... |
729 730 731 732 733 734 |
/* * on-disk bitmap: * * Use one bit per "chunk" (block set). We do the disk I/O on the bitmap * file a page at a time. There's a superblock at the start of the file. */ |
32a7627cf [PATCH] md: optim... |
735 |
/* calculate the index of the page that contains this bit */ |
1ec885cdd md/bitmap: move s... |
736 737 |
static inline unsigned long file_page_index(struct bitmap_storage *store, unsigned long chunk) |
32a7627cf [PATCH] md: optim... |
738 |
{ |
1ec885cdd md/bitmap: move s... |
739 |
if (store->sb_page) |
ece5cff0d md: Support write... |
740 741 |
chunk += sizeof(bitmap_super_t) << 3; return chunk >> PAGE_BIT_SHIFT; |
32a7627cf [PATCH] md: optim... |
742 743 744 |
} /* calculate the (bit) offset of this bit within a page */ |
1ec885cdd md/bitmap: move s... |
745 746 |
static inline unsigned long file_page_offset(struct bitmap_storage *store, unsigned long chunk) |
32a7627cf [PATCH] md: optim... |
747 |
{ |
1ec885cdd md/bitmap: move s... |
748 |
if (store->sb_page) |
ece5cff0d md: Support write... |
749 750 |
chunk += sizeof(bitmap_super_t) << 3; return chunk & (PAGE_BITS - 1); |
32a7627cf [PATCH] md: optim... |
751 752 753 754 755 |
} /* * return a pointer to the page in the filemap that contains the given bit * |
32a7627cf [PATCH] md: optim... |
756 |
*/ |
1ec885cdd md/bitmap: move s... |
757 |
static inline struct page *filemap_get_page(struct bitmap_storage *store, |
3520fa4db MD bitmap: Revert... |
758 |
unsigned long chunk) |
32a7627cf [PATCH] md: optim... |
759 |
{ |
1ec885cdd md/bitmap: move s... |
760 |
if (file_page_index(store, chunk) >= store->file_pages) |
ac2f40be4 md/bitmap: white ... |
761 |
return NULL; |
f2e06c588 md/bitmap: remove... |
762 |
return store->filemap[file_page_index(store, chunk)]; |
32a7627cf [PATCH] md: optim... |
763 |
} |
e64e4018d md: Avoid namespa... |
764 765 766 |
static int md_bitmap_storage_alloc(struct bitmap_storage *store, unsigned long chunks, int with_super, int slot_number) |
d1244cb06 md/bitmap: separa... |
767 |
{ |
b97e92574 Use separate bitm... |
768 |
int pnum, offset = 0; |
d1244cb06 md/bitmap: separa... |
769 770 771 772 773 774 775 776 |
unsigned long num_pages; unsigned long bytes; bytes = DIV_ROUND_UP(chunks, 8); if (with_super) bytes += sizeof(bitmap_super_t); num_pages = DIV_ROUND_UP(bytes, PAGE_SIZE); |
7f86ffed9 md-cluster/bitmap... |
777 |
offset = slot_number * num_pages; |
d1244cb06 md/bitmap: separa... |
778 |
|
6da2ec560 treewide: kmalloc... |
779 780 |
store->filemap = kmalloc_array(num_pages, sizeof(struct page *), GFP_KERNEL); |
d1244cb06 md/bitmap: separa... |
781 782 783 784 |
if (!store->filemap) return -ENOMEM; if (with_super && !store->sb_page) { |
d60b479d1 md/bitmap: add bi... |
785 |
store->sb_page = alloc_page(GFP_KERNEL|__GFP_ZERO); |
d1244cb06 md/bitmap: separa... |
786 787 |
if (store->sb_page == NULL) return -ENOMEM; |
d1244cb06 md/bitmap: separa... |
788 |
} |
b97e92574 Use separate bitm... |
789 |
|
d1244cb06 md/bitmap: separa... |
790 791 792 793 |
pnum = 0; if (store->sb_page) { store->filemap[0] = store->sb_page; pnum = 1; |
b97e92574 Use separate bitm... |
794 |
store->sb_page->index = offset; |
d1244cb06 md/bitmap: separa... |
795 |
} |
b97e92574 Use separate bitm... |
796 |
|
d1244cb06 md/bitmap: separa... |
797 |
for ( ; pnum < num_pages; pnum++) { |
d60b479d1 md/bitmap: add bi... |
798 |
store->filemap[pnum] = alloc_page(GFP_KERNEL|__GFP_ZERO); |
d1244cb06 md/bitmap: separa... |
799 800 801 802 |
if (!store->filemap[pnum]) { store->file_pages = pnum; return -ENOMEM; } |
b97e92574 Use separate bitm... |
803 |
store->filemap[pnum]->index = pnum + offset; |
d1244cb06 md/bitmap: separa... |
804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 |
} store->file_pages = pnum; /* We need 4 bits per page, rounded up to a multiple * of sizeof(unsigned long) */ store->filemap_attr = kzalloc( roundup(DIV_ROUND_UP(num_pages*4, 8), sizeof(unsigned long)), GFP_KERNEL); if (!store->filemap_attr) return -ENOMEM; store->bytes = bytes; return 0; } |
e64e4018d md: Avoid namespa... |
819 |
static void md_bitmap_file_unmap(struct bitmap_storage *store) |
32a7627cf [PATCH] md: optim... |
820 821 |
{ struct page **map, *sb_page; |
32a7627cf [PATCH] md: optim... |
822 |
int pages; |
fae7d326c md/bitmap: merge ... |
823 |
struct file *file; |
32a7627cf [PATCH] md: optim... |
824 |
|
fae7d326c md/bitmap: merge ... |
825 |
file = store->file; |
1ec885cdd md/bitmap: move s... |
826 |
map = store->filemap; |
1ec885cdd md/bitmap: move s... |
827 |
pages = store->file_pages; |
1ec885cdd md/bitmap: move s... |
828 |
sb_page = store->sb_page; |
32a7627cf [PATCH] md: optim... |
829 830 |
while (pages--) |
ece5cff0d md: Support write... |
831 |
if (map[pages] != sb_page) /* 0 is sb_page, release it below */ |
d785a06a0 [PATCH] md/bitmap... |
832 |
free_buffers(map[pages]); |
32a7627cf [PATCH] md: optim... |
833 |
kfree(map); |
fae7d326c md/bitmap: merge ... |
834 |
kfree(store->filemap_attr); |
32a7627cf [PATCH] md: optim... |
835 |
|
d785a06a0 [PATCH] md/bitmap... |
836 837 |
if (sb_page) free_buffers(sb_page); |
32a7627cf [PATCH] md: optim... |
838 |
|
d785a06a0 [PATCH] md/bitmap... |
839 |
if (file) { |
496ad9aa8 new helper: file_... |
840 |
struct inode *inode = file_inode(file); |
fc0ecff69 [PATCH] remove in... |
841 |
invalidate_mapping_pages(inode->i_mapping, 0, -1); |
32a7627cf [PATCH] md: optim... |
842 |
fput(file); |
d785a06a0 [PATCH] md/bitmap... |
843 |
} |
32a7627cf [PATCH] md: optim... |
844 |
} |
32a7627cf [PATCH] md: optim... |
845 846 847 848 849 |
/* * bitmap_file_kick - if an error occurs while manipulating the bitmap file * then it is no longer reliable, so we stop using it and we mark the file * as failed in the superblock */ |
e64e4018d md: Avoid namespa... |
850 |
static void md_bitmap_file_kick(struct bitmap *bitmap) |
32a7627cf [PATCH] md: optim... |
851 852 |
{ char *path, *ptr = NULL; |
b405fe91e md/bitmap: use se... |
853 |
if (!test_and_set_bit(BITMAP_STALE, &bitmap->flags)) { |
e64e4018d md: Avoid namespa... |
854 |
md_bitmap_update_sb(bitmap); |
32a7627cf [PATCH] md: optim... |
855 |
|
1ec885cdd md/bitmap: move s... |
856 |
if (bitmap->storage.file) { |
4ad136637 md: change bitmap... |
857 858 |
path = kmalloc(PAGE_SIZE, GFP_KERNEL); if (path) |
9bf39ab2a vfs: add file_pat... |
859 |
ptr = file_path(bitmap->storage.file, |
1ec885cdd md/bitmap: move s... |
860 |
path, PAGE_SIZE); |
6bcfd6018 md: kill file_pat... |
861 |
|
ec0cc2268 md/bitmap: change... |
862 863 864 |
pr_warn("%s: kicking failed bitmap file %s from array! ", bmname(bitmap), IS_ERR(ptr) ? "" : ptr); |
32a7627cf [PATCH] md: optim... |
865 |
|
4ad136637 md: change bitmap... |
866 867 |
kfree(path); } else |
ec0cc2268 md/bitmap: change... |
868 869 870 |
pr_warn("%s: disabling internal bitmap due to errors ", bmname(bitmap)); |
a654b9d8f [PATCH] md: allow... |
871 |
} |
32a7627cf [PATCH] md: optim... |
872 873 874 |
} enum bitmap_page_attr { |
ac2f40be4 md/bitmap: white ... |
875 |
BITMAP_PAGE_DIRTY = 0, /* there are set bits that need to be synced */ |
5a537df44 md/bitmap: rename... |
876 877 |
BITMAP_PAGE_PENDING = 1, /* there are bits that are being cleaned. * i.e. counter is 1 or 2. */ |
ac2f40be4 md/bitmap: white ... |
878 |
BITMAP_PAGE_NEEDWRITE = 2, /* there are cleared bits that need to be synced */ |
32a7627cf [PATCH] md: optim... |
879 |
}; |
d189122d4 md/bitmap: change... |
880 881 |
static inline void set_page_attr(struct bitmap *bitmap, int pnum, enum bitmap_page_attr attr) |
32a7627cf [PATCH] md: optim... |
882 |
{ |
bdfd11407 md/bitmap: make _... |
883 |
set_bit((pnum<<2) + attr, bitmap->storage.filemap_attr); |
32a7627cf [PATCH] md: optim... |
884 |
} |
d189122d4 md/bitmap: change... |
885 886 |
static inline void clear_page_attr(struct bitmap *bitmap, int pnum, enum bitmap_page_attr attr) |
32a7627cf [PATCH] md: optim... |
887 |
{ |
bdfd11407 md/bitmap: make _... |
888 |
clear_bit((pnum<<2) + attr, bitmap->storage.filemap_attr); |
32a7627cf [PATCH] md: optim... |
889 |
} |
bdfd11407 md/bitmap: make _... |
890 891 |
static inline int test_page_attr(struct bitmap *bitmap, int pnum, enum bitmap_page_attr attr) |
32a7627cf [PATCH] md: optim... |
892 |
{ |
1ec885cdd md/bitmap: move s... |
893 |
return test_bit((pnum<<2) + attr, bitmap->storage.filemap_attr); |
32a7627cf [PATCH] md: optim... |
894 |
} |
bdfd11407 md/bitmap: make _... |
895 896 897 898 899 900 |
static inline int test_and_clear_page_attr(struct bitmap *bitmap, int pnum, enum bitmap_page_attr attr) { return test_and_clear_bit((pnum<<2) + attr, bitmap->storage.filemap_attr); } |
32a7627cf [PATCH] md: optim... |
901 902 903 904 905 906 907 |
/* * bitmap_file_set_bit -- called before performing a write to the md device * to set (and eventually sync) a particular bit in the bitmap file * * we set the bit immediately, then we record the page number so that * when an unplug occurs, we can flush the dirty pages out to disk */ |
e64e4018d md: Avoid namespa... |
908 |
static void md_bitmap_file_set_bit(struct bitmap *bitmap, sector_t block) |
32a7627cf [PATCH] md: optim... |
909 910 |
{ unsigned long bit; |
3520fa4db MD bitmap: Revert... |
911 |
struct page *page; |
32a7627cf [PATCH] md: optim... |
912 |
void *kaddr; |
40cffcc0e md/bitmap: create... |
913 |
unsigned long chunk = block >> bitmap->counts.chunkshift; |
23cea66a3 md-cluster/bitmap... |
914 915 916 917 918 |
struct bitmap_storage *store = &bitmap->storage; unsigned long node_offset = 0; if (mddev_is_clustered(bitmap->mddev)) node_offset = bitmap->cluster_slot * store->file_pages; |
32a7627cf [PATCH] md: optim... |
919 |
|
1ec885cdd md/bitmap: move s... |
920 |
page = filemap_get_page(&bitmap->storage, chunk); |
3520fa4db MD bitmap: Revert... |
921 922 |
if (!page) return; |
1ec885cdd md/bitmap: move s... |
923 |
bit = file_page_offset(&bitmap->storage, chunk); |
32a7627cf [PATCH] md: optim... |
924 |
|
3520fa4db MD bitmap: Revert... |
925 |
/* set the bit */ |
b2f46e688 md: remove the se... |
926 |
kaddr = kmap_atomic(page); |
b405fe91e md/bitmap: use se... |
927 |
if (test_bit(BITMAP_HOSTENDIAN, &bitmap->flags)) |
3520fa4db MD bitmap: Revert... |
928 929 |
set_bit(bit, kaddr); else |
3f810b6c4 md: use set_bit_l... |
930 |
set_bit_le(bit, kaddr); |
b2f46e688 md: remove the se... |
931 |
kunmap_atomic(kaddr); |
36a4e1fe0 md: remove PRINTK... |
932 933 |
pr_debug("set file bit %lu page %lu ", bit, page->index); |
32a7627cf [PATCH] md: optim... |
934 |
/* record page number so it gets flushed to disk when unplug occurs */ |
23cea66a3 md-cluster/bitmap... |
935 |
set_page_attr(bitmap, page->index - node_offset, BITMAP_PAGE_DIRTY); |
32a7627cf [PATCH] md: optim... |
936 |
} |
e64e4018d md: Avoid namespa... |
937 |
static void md_bitmap_file_clear_bit(struct bitmap *bitmap, sector_t block) |
ef99bf480 md/bitmap: allow ... |
938 939 940 941 |
{ unsigned long bit; struct page *page; void *paddr; |
40cffcc0e md/bitmap: create... |
942 |
unsigned long chunk = block >> bitmap->counts.chunkshift; |
23cea66a3 md-cluster/bitmap... |
943 944 945 946 947 |
struct bitmap_storage *store = &bitmap->storage; unsigned long node_offset = 0; if (mddev_is_clustered(bitmap->mddev)) node_offset = bitmap->cluster_slot * store->file_pages; |
ef99bf480 md/bitmap: allow ... |
948 |
|
1ec885cdd md/bitmap: move s... |
949 |
page = filemap_get_page(&bitmap->storage, chunk); |
ef99bf480 md/bitmap: allow ... |
950 951 |
if (!page) return; |
1ec885cdd md/bitmap: move s... |
952 |
bit = file_page_offset(&bitmap->storage, chunk); |
ef99bf480 md/bitmap: allow ... |
953 |
paddr = kmap_atomic(page); |
b405fe91e md/bitmap: use se... |
954 |
if (test_bit(BITMAP_HOSTENDIAN, &bitmap->flags)) |
ef99bf480 md/bitmap: allow ... |
955 956 |
clear_bit(bit, paddr); else |
3f810b6c4 md: use set_bit_l... |
957 |
clear_bit_le(bit, paddr); |
ef99bf480 md/bitmap: allow ... |
958 |
kunmap_atomic(paddr); |
23cea66a3 md-cluster/bitmap... |
959 960 |
if (!test_page_attr(bitmap, page->index - node_offset, BITMAP_PAGE_NEEDWRITE)) { set_page_attr(bitmap, page->index - node_offset, BITMAP_PAGE_PENDING); |
ef99bf480 md/bitmap: allow ... |
961 962 963 |
bitmap->allclean = 0; } } |
e64e4018d md: Avoid namespa... |
964 |
static int md_bitmap_file_test_bit(struct bitmap *bitmap, sector_t block) |
11dd35daa Copy set bits fro... |
965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 |
{ unsigned long bit; struct page *page; void *paddr; unsigned long chunk = block >> bitmap->counts.chunkshift; int set = 0; page = filemap_get_page(&bitmap->storage, chunk); if (!page) return -EINVAL; bit = file_page_offset(&bitmap->storage, chunk); paddr = kmap_atomic(page); if (test_bit(BITMAP_HOSTENDIAN, &bitmap->flags)) set = test_bit(bit, paddr); else set = test_bit_le(bit, paddr); kunmap_atomic(paddr); return set; } |
32a7627cf [PATCH] md: optim... |
984 985 986 |
/* this gets called when the md device is ready to unplug its underlying * (slave) device queues -- before we let any writes go down, we need to * sync the dirty pages of the bitmap file to disk */ |
e64e4018d md: Avoid namespa... |
987 |
void md_bitmap_unplug(struct bitmap *bitmap) |
32a7627cf [PATCH] md: optim... |
988 |
{ |
746671234 md/bitmap: conver... |
989 |
unsigned long i; |
ec7a3197f [PATCH] md/bitmap... |
990 |
int dirty, need_write; |
85c9ccd4f md/bitmap: Don't ... |
991 |
int writing = 0; |
32a7627cf [PATCH] md: optim... |
992 |
|
62f82faac md/bitmap: remove... |
993 994 |
if (!bitmap || !bitmap->storage.filemap || test_bit(BITMAP_STALE, &bitmap->flags)) |
4ad136637 md: change bitmap... |
995 |
return; |
32a7627cf [PATCH] md: optim... |
996 997 998 |
/* look at each page to see if there are any set bits that need to be * flushed out to disk */ |
1ec885cdd md/bitmap: move s... |
999 |
for (i = 0; i < bitmap->storage.file_pages; i++) { |
bdfd11407 md/bitmap: make _... |
1000 1001 1002 1003 |
dirty = test_and_clear_page_attr(bitmap, i, BITMAP_PAGE_DIRTY); need_write = test_and_clear_page_attr(bitmap, i, BITMAP_PAGE_NEEDWRITE); if (dirty || need_write) { |
581dbd94d md/bitmap: add bl... |
1004 |
if (!writing) { |
e64e4018d md: Avoid namespa... |
1005 |
md_bitmap_wait_writes(bitmap); |
581dbd94d md/bitmap: add bl... |
1006 1007 1008 1009 |
if (bitmap->mddev->queue) blk_add_trace_msg(bitmap->mddev->queue, "md bitmap_unplug"); } |
d189122d4 md/bitmap: change... |
1010 |
clear_page_attr(bitmap, i, BITMAP_PAGE_PENDING); |
bdfd11407 md/bitmap: make _... |
1011 |
write_page(bitmap, bitmap->storage.filemap[i], 0); |
85c9ccd4f md/bitmap: Don't ... |
1012 |
writing = 1; |
bdfd11407 md/bitmap: make _... |
1013 |
} |
32a7627cf [PATCH] md: optim... |
1014 |
} |
85c9ccd4f md/bitmap: Don't ... |
1015 |
if (writing) |
e64e4018d md: Avoid namespa... |
1016 |
md_bitmap_wait_writes(bitmap); |
4b5060dda md/bitmap: always... |
1017 |
|
b405fe91e md/bitmap: use se... |
1018 |
if (test_bit(BITMAP_WRITE_ERROR, &bitmap->flags)) |
e64e4018d md: Avoid namespa... |
1019 |
md_bitmap_file_kick(bitmap); |
32a7627cf [PATCH] md: optim... |
1020 |
} |
e64e4018d md: Avoid namespa... |
1021 |
EXPORT_SYMBOL(md_bitmap_unplug); |
32a7627cf [PATCH] md: optim... |
1022 |
|
e64e4018d md: Avoid namespa... |
1023 |
static void md_bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int needed); |
32a7627cf [PATCH] md: optim... |
1024 1025 1026 1027 1028 1029 1030 |
/* * bitmap_init_from_disk -- called at bitmap_create time to initialize * the in-memory bitmap from the on-disk bitmap -- also, sets up the * memory mapping of the bitmap file * Special cases: * if there's no bitmap file, or if the bitmap file had been * previously kicked from the array, we mark all the bits as * 1's in order to cause a full resync. |
6a07997fc [PATCH] md: impro... |
1031 1032 1033 |
* * We ignore all bits for sectors that end earlier than 'start'. * This is used when reading an out-of-date bitmap... |
32a7627cf [PATCH] md: optim... |
1034 |
*/ |
e64e4018d md: Avoid namespa... |
1035 |
static int md_bitmap_init_from_disk(struct bitmap *bitmap, sector_t start) |
32a7627cf [PATCH] md: optim... |
1036 |
{ |
b97e92574 Use separate bitm... |
1037 |
unsigned long i, chunks, index, oldindex, bit, node_offset = 0; |
27581e5ae md/bitmap: centra... |
1038 |
struct page *page = NULL; |
d1244cb06 md/bitmap: separa... |
1039 |
unsigned long bit_cnt = 0; |
32a7627cf [PATCH] md: optim... |
1040 |
struct file *file; |
d1244cb06 md/bitmap: separa... |
1041 |
unsigned long offset; |
32a7627cf [PATCH] md: optim... |
1042 1043 |
int outofdate; int ret = -ENOSPC; |
ea03aff93 [PATCH] md: conve... |
1044 |
void *paddr; |
1ec885cdd md/bitmap: move s... |
1045 |
struct bitmap_storage *store = &bitmap->storage; |
32a7627cf [PATCH] md: optim... |
1046 |
|
40cffcc0e md/bitmap: create... |
1047 |
chunks = bitmap->counts.chunks; |
1ec885cdd md/bitmap: move s... |
1048 |
file = store->file; |
32a7627cf [PATCH] md: optim... |
1049 |
|
ef99bf480 md/bitmap: allow ... |
1050 1051 |
if (!file && !bitmap->mddev->bitmap_info.offset) { /* No permanent bitmap - fill with '1s'. */ |
1ec885cdd md/bitmap: move s... |
1052 1053 |
store->filemap = NULL; store->file_pages = 0; |
ef99bf480 md/bitmap: allow ... |
1054 1055 |
for (i = 0; i < chunks ; i++) { /* if the disk bit is set, set the memory bit */ |
40cffcc0e md/bitmap: create... |
1056 |
int needed = ((sector_t)(i+1) << (bitmap->counts.chunkshift) |
ef99bf480 md/bitmap: allow ... |
1057 |
>= start); |
e64e4018d md: Avoid namespa... |
1058 1059 1060 |
md_bitmap_set_memory_bits(bitmap, (sector_t)i << bitmap->counts.chunkshift, needed); |
ef99bf480 md/bitmap: allow ... |
1061 1062 1063 |
} return 0; } |
32a7627cf [PATCH] md: optim... |
1064 |
|
b405fe91e md/bitmap: use se... |
1065 |
outofdate = test_bit(BITMAP_STALE, &bitmap->flags); |
32a7627cf [PATCH] md: optim... |
1066 |
if (outofdate) |
ec0cc2268 md/bitmap: change... |
1067 1068 |
pr_warn("%s: bitmap file is out of date, doing full recovery ", bmname(bitmap)); |
32a7627cf [PATCH] md: optim... |
1069 |
|
d1244cb06 md/bitmap: separa... |
1070 |
if (file && i_size_read(file->f_mapping->host) < store->bytes) { |
ec0cc2268 md/bitmap: change... |
1071 1072 1073 1074 1075 |
pr_warn("%s: bitmap file too short %lu < %lu ", bmname(bitmap), (unsigned long) i_size_read(file->f_mapping->host), store->bytes); |
4ad136637 md: change bitmap... |
1076 |
goto err; |
32a7627cf [PATCH] md: optim... |
1077 |
} |
bc7f77de2 [PATCH] md: minor... |
1078 |
|
d1244cb06 md/bitmap: separa... |
1079 |
oldindex = ~0L; |
27581e5ae md/bitmap: centra... |
1080 |
offset = 0; |
d1244cb06 md/bitmap: separa... |
1081 |
if (!bitmap->mddev->bitmap_info.external) |
27581e5ae md/bitmap: centra... |
1082 |
offset = sizeof(bitmap_super_t); |
32a7627cf [PATCH] md: optim... |
1083 |
|
b97e92574 Use separate bitm... |
1084 1085 |
if (mddev_is_clustered(bitmap->mddev)) node_offset = bitmap->cluster_slot * (DIV_ROUND_UP(store->bytes, PAGE_SIZE)); |
32a7627cf [PATCH] md: optim... |
1086 |
for (i = 0; i < chunks; i++) { |
bd926c63b [PATCH] md: make ... |
1087 |
int b; |
1ec885cdd md/bitmap: move s... |
1088 1089 |
index = file_page_index(&bitmap->storage, i); bit = file_page_offset(&bitmap->storage, i); |
32a7627cf [PATCH] md: optim... |
1090 |
if (index != oldindex) { /* this is a new page, read it in */ |
d785a06a0 [PATCH] md/bitmap... |
1091 |
int count; |
32a7627cf [PATCH] md: optim... |
1092 |
/* unmap the old page, we're done with it */ |
d1244cb06 md/bitmap: separa... |
1093 1094 |
if (index == store->file_pages-1) count = store->bytes - index * PAGE_SIZE; |
d785a06a0 [PATCH] md/bitmap... |
1095 1096 |
else count = PAGE_SIZE; |
1ec885cdd md/bitmap: move s... |
1097 |
page = store->filemap[index]; |
27581e5ae md/bitmap: centra... |
1098 1099 1100 1101 1102 1103 1104 1105 |
if (file) ret = read_page(file, index, bitmap, count, page); else ret = read_sb_page( bitmap->mddev, bitmap->mddev->bitmap_info.offset, page, |
b97e92574 Use separate bitm... |
1106 |
index + node_offset, count); |
27581e5ae md/bitmap: centra... |
1107 1108 |
if (ret) |
4ad136637 md: change bitmap... |
1109 |
goto err; |
a654b9d8f [PATCH] md: allow... |
1110 |
|
32a7627cf [PATCH] md: optim... |
1111 |
oldindex = index; |
32a7627cf [PATCH] md: optim... |
1112 1113 1114 1115 |
if (outofdate) { /* * if bitmap is out of date, dirty the |
ac2f40be4 md/bitmap: white ... |
1116 |
* whole page and write it out |
32a7627cf [PATCH] md: optim... |
1117 |
*/ |
b2f46e688 md: remove the se... |
1118 |
paddr = kmap_atomic(page); |
ea03aff93 [PATCH] md: conve... |
1119 |
memset(paddr + offset, 0xff, |
6a07997fc [PATCH] md: impro... |
1120 |
PAGE_SIZE - offset); |
b2f46e688 md: remove the se... |
1121 |
kunmap_atomic(paddr); |
4ad136637 md: change bitmap... |
1122 1123 1124 |
write_page(bitmap, page, 1); ret = -EIO; |
b405fe91e md/bitmap: use se... |
1125 1126 |
if (test_bit(BITMAP_WRITE_ERROR, &bitmap->flags)) |
4ad136637 md: change bitmap... |
1127 |
goto err; |
32a7627cf [PATCH] md: optim... |
1128 |
} |
32a7627cf [PATCH] md: optim... |
1129 |
} |
b2f46e688 md: remove the se... |
1130 |
paddr = kmap_atomic(page); |
b405fe91e md/bitmap: use se... |
1131 |
if (test_bit(BITMAP_HOSTENDIAN, &bitmap->flags)) |
ea03aff93 [PATCH] md: conve... |
1132 |
b = test_bit(bit, paddr); |
bd926c63b [PATCH] md: make ... |
1133 |
else |
6b33aff36 md: use little-en... |
1134 |
b = test_bit_le(bit, paddr); |
b2f46e688 md: remove the se... |
1135 |
kunmap_atomic(paddr); |
bd926c63b [PATCH] md: make ... |
1136 |
if (b) { |
32a7627cf [PATCH] md: optim... |
1137 |
/* if the disk bit is set, set the memory bit */ |
40cffcc0e md/bitmap: create... |
1138 |
int needed = ((sector_t)(i+1) << bitmap->counts.chunkshift |
db305e507 md: fix some (mor... |
1139 |
>= start); |
e64e4018d md: Avoid namespa... |
1140 1141 1142 |
md_bitmap_set_memory_bits(bitmap, (sector_t)i << bitmap->counts.chunkshift, needed); |
32a7627cf [PATCH] md: optim... |
1143 1144 |
bit_cnt++; } |
27581e5ae md/bitmap: centra... |
1145 |
offset = 0; |
32a7627cf [PATCH] md: optim... |
1146 |
} |
ec0cc2268 md/bitmap: change... |
1147 1148 1149 1150 |
pr_debug("%s: bitmap initialized from disk: read %lu pages, set %lu of %lu bits ", bmname(bitmap), store->file_pages, bit_cnt, chunks); |
4ad136637 md: change bitmap... |
1151 1152 |
return 0; |
32a7627cf [PATCH] md: optim... |
1153 |
|
4ad136637 md: change bitmap... |
1154 |
err: |
ec0cc2268 md/bitmap: change... |
1155 1156 1157 |
pr_warn("%s: bitmap initialisation failed: %d ", bmname(bitmap), ret); |
32a7627cf [PATCH] md: optim... |
1158 1159 |
return ret; } |
e64e4018d md: Avoid namespa... |
1160 |
void md_bitmap_write_all(struct bitmap *bitmap) |
a654b9d8f [PATCH] md: allow... |
1161 1162 1163 1164 |
{ /* We don't actually write all bitmap blocks here, * just flag them as needing to be written */ |
ec7a3197f [PATCH] md/bitmap... |
1165 |
int i; |
a654b9d8f [PATCH] md: allow... |
1166 |
|
1ec885cdd md/bitmap: move s... |
1167 |
if (!bitmap || !bitmap->storage.filemap) |
ef99bf480 md/bitmap: allow ... |
1168 |
return; |
1ec885cdd md/bitmap: move s... |
1169 |
if (bitmap->storage.file) |
ef99bf480 md/bitmap: allow ... |
1170 1171 |
/* Only one copy, so nothing needed */ return; |
1ec885cdd md/bitmap: move s... |
1172 |
for (i = 0; i < bitmap->storage.file_pages; i++) |
d189122d4 md/bitmap: change... |
1173 |
set_page_attr(bitmap, i, |
ec7a3197f [PATCH] md/bitmap... |
1174 |
BITMAP_PAGE_NEEDWRITE); |
2585f3ef8 md/bitmap: improv... |
1175 |
bitmap->allclean = 0; |
a654b9d8f [PATCH] md: allow... |
1176 |
} |
e64e4018d md: Avoid namespa... |
1177 1178 |
static void md_bitmap_count_page(struct bitmap_counts *bitmap, sector_t offset, int inc) |
32a7627cf [PATCH] md: optim... |
1179 |
{ |
61a0d80ce md/bitmap: discar... |
1180 |
sector_t chunk = offset >> bitmap->chunkshift; |
32a7627cf [PATCH] md: optim... |
1181 1182 |
unsigned long page = chunk >> PAGE_COUNTER_SHIFT; bitmap->bp[page].count += inc; |
e64e4018d md: Avoid namespa... |
1183 |
md_bitmap_checkfree(bitmap, page); |
32a7627cf [PATCH] md: optim... |
1184 |
} |
bf07bb7d5 md/bitmap: disent... |
1185 |
|
e64e4018d md: Avoid namespa... |
1186 |
static void md_bitmap_set_pending(struct bitmap_counts *bitmap, sector_t offset) |
bf07bb7d5 md/bitmap: disent... |
1187 1188 1189 1190 1191 1192 1193 1194 |
{ sector_t chunk = offset >> bitmap->chunkshift; unsigned long page = chunk >> PAGE_COUNTER_SHIFT; struct bitmap_page *bp = &bitmap->bp[page]; if (!bp->pending) bp->pending = 1; } |
e64e4018d md: Avoid namespa... |
1195 1196 1197 |
static bitmap_counter_t *md_bitmap_get_counter(struct bitmap_counts *bitmap, sector_t offset, sector_t *blocks, int create); |
32a7627cf [PATCH] md: optim... |
1198 1199 1200 1201 1202 |
/* * bitmap daemon -- periodically wakes up to clean bits and flush pages * out to disk */ |
e64e4018d md: Avoid namespa... |
1203 |
void md_bitmap_daemon_work(struct mddev *mddev) |
32a7627cf [PATCH] md: optim... |
1204 |
{ |
aa5cbd103 md/bitmap: protec... |
1205 |
struct bitmap *bitmap; |
aa3163f81 [PATCH] md: don't... |
1206 |
unsigned long j; |
bf07bb7d5 md/bitmap: disent... |
1207 |
unsigned long nextpage; |
57dab0bdf md: use sector_t ... |
1208 |
sector_t blocks; |
40cffcc0e md/bitmap: create... |
1209 |
struct bitmap_counts *counts; |
32a7627cf [PATCH] md: optim... |
1210 |
|
aa5cbd103 md/bitmap: protec... |
1211 1212 1213 |
/* Use a mutex to guard daemon_work against * bitmap_destroy. */ |
c3d9714e8 md: collect bitma... |
1214 |
mutex_lock(&mddev->bitmap_info.mutex); |
aa5cbd103 md/bitmap: protec... |
1215 1216 |
bitmap = mddev->bitmap; if (bitmap == NULL) { |
c3d9714e8 md: collect bitma... |
1217 |
mutex_unlock(&mddev->bitmap_info.mutex); |
4ad136637 md: change bitmap... |
1218 |
return; |
aa5cbd103 md/bitmap: protec... |
1219 |
} |
42a04b507 md: move offset, ... |
1220 |
if (time_before(jiffies, bitmap->daemon_lastrun |
2e61ebbcc md/bitmap: daemon... |
1221 |
+ mddev->bitmap_info.daemon_sleep)) |
7be3dfec4 md: reduce CPU wa... |
1222 |
goto done; |
32a7627cf [PATCH] md: optim... |
1223 |
bitmap->daemon_lastrun = jiffies; |
8311c29d4 md: reduce CPU wa... |
1224 |
if (bitmap->allclean) { |
2e61ebbcc md/bitmap: daemon... |
1225 |
mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT; |
aa5cbd103 md/bitmap: protec... |
1226 |
goto done; |
8311c29d4 md: reduce CPU wa... |
1227 1228 |
} bitmap->allclean = 1; |
32a7627cf [PATCH] md: optim... |
1229 |
|
581dbd94d md/bitmap: add bl... |
1230 1231 1232 |
if (bitmap->mddev->queue) blk_add_trace_msg(bitmap->mddev->queue, "md bitmap_daemon_work"); |
bf07bb7d5 md/bitmap: disent... |
1233 1234 1235 1236 |
/* Any file-page which is PENDING now needs to be written. * So set NEEDWRITE now, then after we make any last-minute changes * we will write it. */ |
1ec885cdd md/bitmap: move s... |
1237 |
for (j = 0; j < bitmap->storage.file_pages; j++) |
bdfd11407 md/bitmap: make _... |
1238 1239 |
if (test_and_clear_page_attr(bitmap, j, BITMAP_PAGE_PENDING)) |
d189122d4 md/bitmap: change... |
1240 |
set_page_attr(bitmap, j, |
bf07bb7d5 md/bitmap: disent... |
1241 |
BITMAP_PAGE_NEEDWRITE); |
bf07bb7d5 md/bitmap: disent... |
1242 1243 1244 1245 1246 1247 1248 |
if (bitmap->need_sync && mddev->bitmap_info.external == 0) { /* Arrange for superblock update as well as * other changes */ bitmap_super_t *sb; bitmap->need_sync = 0; |
1ec885cdd md/bitmap: move s... |
1249 1250 |
if (bitmap->storage.filemap) { sb = kmap_atomic(bitmap->storage.sb_page); |
ef99bf480 md/bitmap: allow ... |
1251 1252 1253 |
sb->events_cleared = cpu_to_le64(bitmap->events_cleared); kunmap_atomic(sb); |
d189122d4 md/bitmap: change... |
1254 |
set_page_attr(bitmap, 0, |
ef99bf480 md/bitmap: allow ... |
1255 1256 |
BITMAP_PAGE_NEEDWRITE); } |
bf07bb7d5 md/bitmap: disent... |
1257 1258 1259 1260 |
} /* Now look at the bitmap counters and if any are '2' or '1', * decrement and handle accordingly. */ |
40cffcc0e md/bitmap: create... |
1261 1262 |
counts = &bitmap->counts; spin_lock_irq(&counts->lock); |
bf07bb7d5 md/bitmap: disent... |
1263 |
nextpage = 0; |
40cffcc0e md/bitmap: create... |
1264 |
for (j = 0; j < counts->chunks; j++) { |
32a7627cf [PATCH] md: optim... |
1265 |
bitmap_counter_t *bmc; |
40cffcc0e md/bitmap: create... |
1266 |
sector_t block = (sector_t)j << counts->chunkshift; |
3520fa4db MD bitmap: Revert... |
1267 |
|
bf07bb7d5 md/bitmap: disent... |
1268 1269 |
if (j == nextpage) { nextpage += PAGE_COUNTER_RATIO; |
40cffcc0e md/bitmap: create... |
1270 |
if (!counts->bp[j >> PAGE_COUNTER_SHIFT].pending) { |
bf07bb7d5 md/bitmap: disent... |
1271 |
j |= PAGE_COUNTER_MASK; |
aa3163f81 [PATCH] md: don't... |
1272 1273 |
continue; } |
40cffcc0e md/bitmap: create... |
1274 |
counts->bp[j >> PAGE_COUNTER_SHIFT].pending = 0; |
32a7627cf [PATCH] md: optim... |
1275 |
} |
bf07bb7d5 md/bitmap: disent... |
1276 |
|
e64e4018d md: Avoid namespa... |
1277 |
bmc = md_bitmap_get_counter(counts, block, &blocks, 0); |
bf07bb7d5 md/bitmap: disent... |
1278 |
if (!bmc) { |
5a537df44 md/bitmap: rename... |
1279 |
j |= PAGE_COUNTER_MASK; |
bf07bb7d5 md/bitmap: disent... |
1280 1281 1282 1283 |
continue; } if (*bmc == 1 && !bitmap->need_sync) { /* We can clear the bit */ |
bf07bb7d5 md/bitmap: disent... |
1284 |
*bmc = 0; |
e64e4018d md: Avoid namespa... |
1285 1286 |
md_bitmap_count_page(counts, block, -1); md_bitmap_file_clear_bit(bitmap, block); |
bf07bb7d5 md/bitmap: disent... |
1287 1288 |
} else if (*bmc && *bmc <= 2) { *bmc = 1; |
e64e4018d md: Avoid namespa... |
1289 |
md_bitmap_set_pending(counts, block); |
bf07bb7d5 md/bitmap: disent... |
1290 |
bitmap->allclean = 0; |
5a537df44 md/bitmap: rename... |
1291 |
} |
32a7627cf [PATCH] md: optim... |
1292 |
} |
40cffcc0e md/bitmap: create... |
1293 |
spin_unlock_irq(&counts->lock); |
32a7627cf [PATCH] md: optim... |
1294 |
|
e64e4018d md: Avoid namespa... |
1295 |
md_bitmap_wait_writes(bitmap); |
bf07bb7d5 md/bitmap: disent... |
1296 1297 1298 1299 1300 1301 1302 1303 |
/* Now start writeout on any page in NEEDWRITE that isn't DIRTY. * DIRTY pages need to be written by bitmap_unplug so it can wait * for them. * If we find any DIRTY page we stop there and let bitmap_unplug * handle all the rest. This is important in the case where * the first blocking holds the superblock and it has been updated. * We mustn't write any other blocks before the superblock. */ |
62f82faac md/bitmap: remove... |
1304 1305 1306 1307 |
for (j = 0; j < bitmap->storage.file_pages && !test_bit(BITMAP_STALE, &bitmap->flags); j++) { |
d189122d4 md/bitmap: change... |
1308 |
if (test_page_attr(bitmap, j, |
bf07bb7d5 md/bitmap: disent... |
1309 1310 1311 |
BITMAP_PAGE_DIRTY)) /* bitmap_unplug will handle the rest */ break; |
55180498d md-bitmap: small ... |
1312 1313 |
if (bitmap->storage.filemap && test_and_clear_page_attr(bitmap, j, |
bdfd11407 md/bitmap: make _... |
1314 |
BITMAP_PAGE_NEEDWRITE)) { |
1ec885cdd md/bitmap: move s... |
1315 |
write_page(bitmap, bitmap->storage.filemap[j], 0); |
32a7627cf [PATCH] md: optim... |
1316 |
} |
32a7627cf [PATCH] md: optim... |
1317 |
} |
7be3dfec4 md: reduce CPU wa... |
1318 |
done: |
8311c29d4 md: reduce CPU wa... |
1319 |
if (bitmap->allclean == 0) |
2e61ebbcc md/bitmap: daemon... |
1320 1321 |
mddev->thread->timeout = mddev->bitmap_info.daemon_sleep; |
c3d9714e8 md: collect bitma... |
1322 |
mutex_unlock(&mddev->bitmap_info.mutex); |
32a7627cf [PATCH] md: optim... |
1323 |
} |
e64e4018d md: Avoid namespa... |
1324 1325 1326 |
static bitmap_counter_t *md_bitmap_get_counter(struct bitmap_counts *bitmap, sector_t offset, sector_t *blocks, int create) |
ee305acef md: remove sparse... |
1327 1328 |
__releases(bitmap->lock) __acquires(bitmap->lock) |
32a7627cf [PATCH] md: optim... |
1329 1330 1331 1332 1333 |
{ /* If 'create', we might release the lock and reclaim it. * The lock must have been taken with interrupts enabled. * If !create, we don't release the lock. */ |
61a0d80ce md/bitmap: discar... |
1334 |
sector_t chunk = offset >> bitmap->chunkshift; |
32a7627cf [PATCH] md: optim... |
1335 1336 1337 |
unsigned long page = chunk >> PAGE_COUNTER_SHIFT; unsigned long pageoff = (chunk & PAGE_COUNTER_MASK) << COUNTER_BYTE_SHIFT; sector_t csize; |
ef4256733 md/bitmap: optimi... |
1338 |
int err; |
32a7627cf [PATCH] md: optim... |
1339 |
|
e64e4018d md: Avoid namespa... |
1340 |
err = md_bitmap_checkpage(bitmap, page, create, 0); |
ef4256733 md/bitmap: optimi... |
1341 1342 1343 |
if (bitmap->bp[page].hijacked || bitmap->bp[page].map == NULL) |
61a0d80ce md/bitmap: discar... |
1344 |
csize = ((sector_t)1) << (bitmap->chunkshift + |
d837f7277 md/bitmap: md_bit... |
1345 |
PAGE_COUNTER_SHIFT); |
ef4256733 md/bitmap: optimi... |
1346 |
else |
61a0d80ce md/bitmap: discar... |
1347 |
csize = ((sector_t)1) << bitmap->chunkshift; |
ef4256733 md/bitmap: optimi... |
1348 1349 1350 |
*blocks = csize - (offset & (csize - 1)); if (err < 0) |
32a7627cf [PATCH] md: optim... |
1351 |
return NULL; |
ef4256733 md/bitmap: optimi... |
1352 |
|
32a7627cf [PATCH] md: optim... |
1353 1354 1355 1356 1357 1358 |
/* now locked ... */ if (bitmap->bp[page].hijacked) { /* hijacked pointer */ /* should we use the first or second counter field * of the hijacked pointer? */ int hi = (pageoff > PAGE_COUNTER_MASK); |
32a7627cf [PATCH] md: optim... |
1359 1360 |
return &((bitmap_counter_t *) &bitmap->bp[page].map)[hi]; |
ef4256733 md/bitmap: optimi... |
1361 |
} else /* page is allocated */ |
32a7627cf [PATCH] md: optim... |
1362 1363 |
return (bitmap_counter_t *) &(bitmap->bp[page].map[pageoff]); |
32a7627cf [PATCH] md: optim... |
1364 |
} |
e64e4018d md: Avoid namespa... |
1365 |
int md_bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors, int behind) |
32a7627cf [PATCH] md: optim... |
1366 |
{ |
ac2f40be4 md/bitmap: white ... |
1367 1368 |
if (!bitmap) return 0; |
4b6d287f6 [PATCH] md: add w... |
1369 1370 |
if (behind) { |
696fcd535 md: expose max va... |
1371 |
int bw; |
4b6d287f6 [PATCH] md: add w... |
1372 |
atomic_inc(&bitmap->behind_writes); |
696fcd535 md: expose max va... |
1373 1374 1375 |
bw = atomic_read(&bitmap->behind_writes); if (bw > bitmap->behind_writes_used) bitmap->behind_writes_used = bw; |
36a4e1fe0 md: remove PRINTK... |
1376 1377 1378 |
pr_debug("inc write-behind count %d/%lu ", bw, bitmap->mddev->bitmap_info.max_write_behind); |
4b6d287f6 [PATCH] md: add w... |
1379 |
} |
32a7627cf [PATCH] md: optim... |
1380 |
while (sectors) { |
57dab0bdf md: use sector_t ... |
1381 |
sector_t blocks; |
32a7627cf [PATCH] md: optim... |
1382 |
bitmap_counter_t *bmc; |
40cffcc0e md/bitmap: create... |
1383 |
spin_lock_irq(&bitmap->counts.lock); |
e64e4018d md: Avoid namespa... |
1384 |
bmc = md_bitmap_get_counter(&bitmap->counts, offset, &blocks, 1); |
32a7627cf [PATCH] md: optim... |
1385 |
if (!bmc) { |
40cffcc0e md/bitmap: create... |
1386 |
spin_unlock_irq(&bitmap->counts.lock); |
32a7627cf [PATCH] md: optim... |
1387 1388 |
return 0; } |
27d5ea04d md/bitmap: use pr... |
1389 |
if (unlikely(COUNTER(*bmc) == COUNTER_MAX)) { |
da6e1a32f [PATCH] md: avoid... |
1390 1391 1392 1393 1394 1395 1396 |
DEFINE_WAIT(__wait); /* note that it is safe to do the prepare_to_wait * after the test as long as we do it before dropping * the spinlock. */ prepare_to_wait(&bitmap->overflow_wait, &__wait, TASK_UNINTERRUPTIBLE); |
40cffcc0e md/bitmap: create... |
1397 |
spin_unlock_irq(&bitmap->counts.lock); |
f54a9d0e5 md/raid1: submit ... |
1398 |
schedule(); |
da6e1a32f [PATCH] md: avoid... |
1399 1400 1401 |
finish_wait(&bitmap->overflow_wait, &__wait); continue; } |
ac2f40be4 md/bitmap: white ... |
1402 |
switch (*bmc) { |
32a7627cf [PATCH] md: optim... |
1403 |
case 0: |
e64e4018d md: Avoid namespa... |
1404 1405 |
md_bitmap_file_set_bit(bitmap, offset); md_bitmap_count_page(&bitmap->counts, offset, 1); |
df561f668 treewide: Use fal... |
1406 |
fallthrough; |
32a7627cf [PATCH] md: optim... |
1407 1408 1409 |
case 1: *bmc = 2; } |
da6e1a32f [PATCH] md: avoid... |
1410 |
|
32a7627cf [PATCH] md: optim... |
1411 |
(*bmc)++; |
40cffcc0e md/bitmap: create... |
1412 |
spin_unlock_irq(&bitmap->counts.lock); |
32a7627cf [PATCH] md: optim... |
1413 1414 1415 1416 |
offset += blocks; if (sectors > blocks) sectors -= blocks; |
ac2f40be4 md/bitmap: white ... |
1417 1418 |
else sectors = 0; |
32a7627cf [PATCH] md: optim... |
1419 1420 1421 |
} return 0; } |
e64e4018d md: Avoid namespa... |
1422 |
EXPORT_SYMBOL(md_bitmap_startwrite); |
32a7627cf [PATCH] md: optim... |
1423 |
|
e64e4018d md: Avoid namespa... |
1424 1425 |
void md_bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors, int success, int behind) |
32a7627cf [PATCH] md: optim... |
1426 |
{ |
ac2f40be4 md/bitmap: white ... |
1427 1428 |
if (!bitmap) return; |
4b6d287f6 [PATCH] md: add w... |
1429 |
if (behind) { |
e555190d8 md/raid1: delay r... |
1430 1431 |
if (atomic_dec_and_test(&bitmap->behind_writes)) wake_up(&bitmap->behind_wait); |
36a4e1fe0 md: remove PRINTK... |
1432 1433 1434 1435 |
pr_debug("dec write-behind count %d/%lu ", atomic_read(&bitmap->behind_writes), bitmap->mddev->bitmap_info.max_write_behind); |
4b6d287f6 [PATCH] md: add w... |
1436 |
} |
32a7627cf [PATCH] md: optim... |
1437 |
while (sectors) { |
57dab0bdf md: use sector_t ... |
1438 |
sector_t blocks; |
32a7627cf [PATCH] md: optim... |
1439 1440 |
unsigned long flags; bitmap_counter_t *bmc; |
40cffcc0e md/bitmap: create... |
1441 |
spin_lock_irqsave(&bitmap->counts.lock, flags); |
e64e4018d md: Avoid namespa... |
1442 |
bmc = md_bitmap_get_counter(&bitmap->counts, offset, &blocks, 0); |
32a7627cf [PATCH] md: optim... |
1443 |
if (!bmc) { |
40cffcc0e md/bitmap: create... |
1444 |
spin_unlock_irqrestore(&bitmap->counts.lock, flags); |
32a7627cf [PATCH] md: optim... |
1445 1446 |
return; } |
961902c0f md/bitmap: It is ... |
1447 |
if (success && !bitmap->mddev->degraded && |
a0da84f35 Improve setting o... |
1448 1449 1450 |
bitmap->events_cleared < bitmap->mddev->events) { bitmap->events_cleared = bitmap->mddev->events; bitmap->need_sync = 1; |
5ff5afffe md/bitmap: reduce... |
1451 |
sysfs_notify_dirent_safe(bitmap->sysfs_can_clear); |
a0da84f35 Improve setting o... |
1452 |
} |
27d5ea04d md/bitmap: use pr... |
1453 |
if (!success && !NEEDED(*bmc)) |
32a7627cf [PATCH] md: optim... |
1454 |
*bmc |= NEEDED_MASK; |
27d5ea04d md/bitmap: use pr... |
1455 |
if (COUNTER(*bmc) == COUNTER_MAX) |
da6e1a32f [PATCH] md: avoid... |
1456 |
wake_up(&bitmap->overflow_wait); |
32a7627cf [PATCH] md: optim... |
1457 |
(*bmc)--; |
2585f3ef8 md/bitmap: improv... |
1458 |
if (*bmc <= 2) { |
e64e4018d md: Avoid namespa... |
1459 |
md_bitmap_set_pending(&bitmap->counts, offset); |
2585f3ef8 md/bitmap: improv... |
1460 1461 |
bitmap->allclean = 0; } |
40cffcc0e md/bitmap: create... |
1462 |
spin_unlock_irqrestore(&bitmap->counts.lock, flags); |
32a7627cf [PATCH] md: optim... |
1463 1464 1465 |
offset += blocks; if (sectors > blocks) sectors -= blocks; |
ac2f40be4 md/bitmap: white ... |
1466 1467 |
else sectors = 0; |
32a7627cf [PATCH] md: optim... |
1468 1469 |
} } |
e64e4018d md: Avoid namespa... |
1470 |
EXPORT_SYMBOL(md_bitmap_endwrite); |
32a7627cf [PATCH] md: optim... |
1471 |
|
57dab0bdf md: use sector_t ... |
1472 |
static int __bitmap_start_sync(struct bitmap *bitmap, sector_t offset, sector_t *blocks, |
1187cf0a3 md: Allow write-i... |
1473 |
int degraded) |
32a7627cf [PATCH] md: optim... |
1474 1475 1476 1477 1478 1479 1480 |
{ bitmap_counter_t *bmc; int rv; if (bitmap == NULL) {/* FIXME or bitmap set as 'failed' */ *blocks = 1024; return 1; /* always resync if no bitmap */ } |
40cffcc0e md/bitmap: create... |
1481 |
spin_lock_irq(&bitmap->counts.lock); |
e64e4018d md: Avoid namespa... |
1482 |
bmc = md_bitmap_get_counter(&bitmap->counts, offset, blocks, 0); |
32a7627cf [PATCH] md: optim... |
1483 1484 1485 1486 1487 1488 1489 |
rv = 0; if (bmc) { /* locked */ if (RESYNC(*bmc)) rv = 1; else if (NEEDED(*bmc)) { rv = 1; |
6a806c510 [PATCH] md/raid1:... |
1490 1491 1492 1493 |
if (!degraded) { /* don't set/clear bits if degraded */ *bmc |= RESYNC_MASK; *bmc &= ~NEEDED_MASK; } |
32a7627cf [PATCH] md: optim... |
1494 1495 |
} } |
40cffcc0e md/bitmap: create... |
1496 |
spin_unlock_irq(&bitmap->counts.lock); |
32a7627cf [PATCH] md: optim... |
1497 1498 |
return rv; } |
e64e4018d md: Avoid namespa... |
1499 1500 |
int md_bitmap_start_sync(struct bitmap *bitmap, sector_t offset, sector_t *blocks, int degraded) |
1187cf0a3 md: Allow write-i... |
1501 1502 1503 1504 1505 1506 1507 1508 1509 |
{ /* bitmap_start_sync must always report on multiples of whole * pages, otherwise resync (which is very PAGE_SIZE based) will * get confused. * So call __bitmap_start_sync repeatedly (if needed) until * At least PAGE_SIZE>>9 blocks are covered. * Return the 'or' of the result. */ int rv = 0; |
57dab0bdf md: use sector_t ... |
1510 |
sector_t blocks1; |
1187cf0a3 md: Allow write-i... |
1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 |
*blocks = 0; while (*blocks < (PAGE_SIZE>>9)) { rv |= __bitmap_start_sync(bitmap, offset, &blocks1, degraded); offset += blocks1; *blocks += blocks1; } return rv; } |
e64e4018d md: Avoid namespa... |
1521 |
EXPORT_SYMBOL(md_bitmap_start_sync); |
1187cf0a3 md: Allow write-i... |
1522 |
|
e64e4018d md: Avoid namespa... |
1523 |
void md_bitmap_end_sync(struct bitmap *bitmap, sector_t offset, sector_t *blocks, int aborted) |
32a7627cf [PATCH] md: optim... |
1524 1525 1526 |
{ bitmap_counter_t *bmc; unsigned long flags; |
ac2f40be4 md/bitmap: white ... |
1527 1528 |
if (bitmap == NULL) { |
32a7627cf [PATCH] md: optim... |
1529 1530 1531 |
*blocks = 1024; return; } |
40cffcc0e md/bitmap: create... |
1532 |
spin_lock_irqsave(&bitmap->counts.lock, flags); |
e64e4018d md: Avoid namespa... |
1533 |
bmc = md_bitmap_get_counter(&bitmap->counts, offset, blocks, 0); |
32a7627cf [PATCH] md: optim... |
1534 1535 1536 |
if (bmc == NULL) goto unlock; /* locked */ |
32a7627cf [PATCH] md: optim... |
1537 1538 1539 1540 1541 1542 |
if (RESYNC(*bmc)) { *bmc &= ~RESYNC_MASK; if (!NEEDED(*bmc) && aborted) *bmc |= NEEDED_MASK; else { |
2585f3ef8 md/bitmap: improv... |
1543 |
if (*bmc <= 2) { |
e64e4018d md: Avoid namespa... |
1544 |
md_bitmap_set_pending(&bitmap->counts, offset); |
2585f3ef8 md/bitmap: improv... |
1545 1546 |
bitmap->allclean = 0; } |
32a7627cf [PATCH] md: optim... |
1547 1548 1549 |
} } unlock: |
40cffcc0e md/bitmap: create... |
1550 |
spin_unlock_irqrestore(&bitmap->counts.lock, flags); |
32a7627cf [PATCH] md: optim... |
1551 |
} |
e64e4018d md: Avoid namespa... |
1552 |
EXPORT_SYMBOL(md_bitmap_end_sync); |
32a7627cf [PATCH] md: optim... |
1553 |
|
e64e4018d md: Avoid namespa... |
1554 |
void md_bitmap_close_sync(struct bitmap *bitmap) |
32a7627cf [PATCH] md: optim... |
1555 1556 1557 1558 1559 1560 |
{ /* Sync has finished, and any bitmap chunks that weren't synced * properly have been aborted. It remains to us to clear the * RESYNC bit wherever it is still on */ sector_t sector = 0; |
57dab0bdf md: use sector_t ... |
1561 |
sector_t blocks; |
b47490c9b md: Update md bit... |
1562 1563 |
if (!bitmap) return; |
32a7627cf [PATCH] md: optim... |
1564 |
while (sector < bitmap->mddev->resync_max_sectors) { |
e64e4018d md: Avoid namespa... |
1565 |
md_bitmap_end_sync(bitmap, sector, &blocks, 0); |
b47490c9b md: Update md bit... |
1566 1567 1568 |
sector += blocks; } } |
e64e4018d md: Avoid namespa... |
1569 |
EXPORT_SYMBOL(md_bitmap_close_sync); |
b47490c9b md: Update md bit... |
1570 |
|
e64e4018d md: Avoid namespa... |
1571 |
void md_bitmap_cond_end_sync(struct bitmap *bitmap, sector_t sector, bool force) |
b47490c9b md: Update md bit... |
1572 1573 |
{ sector_t s = 0; |
57dab0bdf md: use sector_t ... |
1574 |
sector_t blocks; |
b47490c9b md: Update md bit... |
1575 1576 1577 1578 1579 1580 1581 |
if (!bitmap) return; if (sector == 0) { bitmap->last_end_sync = jiffies; return; } |
c40f341f1 md-cluster: Use a... |
1582 |
if (!force && time_before(jiffies, (bitmap->last_end_sync |
1b04be96f md: change daemon... |
1583 |
+ bitmap->mddev->bitmap_info.daemon_sleep))) |
b47490c9b md: Update md bit... |
1584 1585 1586 |
return; wait_event(bitmap->mddev->recovery_wait, atomic_read(&bitmap->mddev->recovery_active) == 0); |
75d3da43c md: Don't let imp... |
1587 |
bitmap->mddev->curr_resync_completed = sector; |
2953079c6 md: separate flag... |
1588 |
set_bit(MD_SB_CHANGE_CLEAN, &bitmap->mddev->sb_flags); |
40cffcc0e md/bitmap: create... |
1589 |
sector &= ~((1ULL << bitmap->counts.chunkshift) - 1); |
b47490c9b md: Update md bit... |
1590 1591 |
s = 0; while (s < sector && s < bitmap->mddev->resync_max_sectors) { |
e64e4018d md: Avoid namespa... |
1592 |
md_bitmap_end_sync(bitmap, s, &blocks, 0); |
b47490c9b md: Update md bit... |
1593 |
s += blocks; |
32a7627cf [PATCH] md: optim... |
1594 |
} |
b47490c9b md: Update md bit... |
1595 |
bitmap->last_end_sync = jiffies; |
e1a86dbbb md: fix deadlock ... |
1596 |
sysfs_notify_dirent_safe(bitmap->mddev->sysfs_completed); |
32a7627cf [PATCH] md: optim... |
1597 |
} |
e64e4018d md: Avoid namespa... |
1598 |
EXPORT_SYMBOL(md_bitmap_cond_end_sync); |
32a7627cf [PATCH] md: optim... |
1599 |
|
e64e4018d md: Avoid namespa... |
1600 |
void md_bitmap_sync_with_cluster(struct mddev *mddev, |
18c9ff7f4 md-cluster: sync ... |
1601 1602 1603 1604 1605 1606 1607 |
sector_t old_lo, sector_t old_hi, sector_t new_lo, sector_t new_hi) { struct bitmap *bitmap = mddev->bitmap; sector_t sector, blocks = 0; for (sector = old_lo; sector < new_lo; ) { |
e64e4018d md: Avoid namespa... |
1608 |
md_bitmap_end_sync(bitmap, sector, &blocks, 0); |
18c9ff7f4 md-cluster: sync ... |
1609 1610 1611 1612 1613 1614 |
sector += blocks; } WARN((blocks > new_lo) && old_lo, "alignment is not correct for lo "); for (sector = old_hi; sector < new_hi; ) { |
e64e4018d md: Avoid namespa... |
1615 |
md_bitmap_start_sync(bitmap, sector, &blocks, 0); |
18c9ff7f4 md-cluster: sync ... |
1616 1617 1618 1619 1620 |
sector += blocks; } WARN((blocks > new_hi) && old_hi, "alignment is not correct for hi "); } |
e64e4018d md: Avoid namespa... |
1621 |
EXPORT_SYMBOL(md_bitmap_sync_with_cluster); |
18c9ff7f4 md-cluster: sync ... |
1622 |
|
e64e4018d md: Avoid namespa... |
1623 |
static void md_bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int needed) |
32a7627cf [PATCH] md: optim... |
1624 1625 |
{ /* For each chunk covered by any of these sectors, set the |
ef99bf480 md/bitmap: allow ... |
1626 |
* counter to 2 and possibly set resync_needed. They should all |
32a7627cf [PATCH] md: optim... |
1627 1628 |
* be 0 at this point */ |
193f1c931 [PATCH] md: alway... |
1629 |
|
57dab0bdf md: use sector_t ... |
1630 |
sector_t secs; |
193f1c931 [PATCH] md: alway... |
1631 |
bitmap_counter_t *bmc; |
40cffcc0e md/bitmap: create... |
1632 |
spin_lock_irq(&bitmap->counts.lock); |
e64e4018d md: Avoid namespa... |
1633 |
bmc = md_bitmap_get_counter(&bitmap->counts, offset, &secs, 1); |
193f1c931 [PATCH] md: alway... |
1634 |
if (!bmc) { |
40cffcc0e md/bitmap: create... |
1635 |
spin_unlock_irq(&bitmap->counts.lock); |
193f1c931 [PATCH] md: alway... |
1636 |
return; |
32a7627cf [PATCH] md: optim... |
1637 |
} |
ac2f40be4 md/bitmap: white ... |
1638 |
if (!*bmc) { |
11dd35daa Copy set bits fro... |
1639 |
*bmc = 2; |
e64e4018d md: Avoid namespa... |
1640 1641 |
md_bitmap_count_page(&bitmap->counts, offset, 1); md_bitmap_set_pending(&bitmap->counts, offset); |
2585f3ef8 md/bitmap: improv... |
1642 |
bitmap->allclean = 0; |
193f1c931 [PATCH] md: alway... |
1643 |
} |
11dd35daa Copy set bits fro... |
1644 1645 |
if (needed) *bmc |= NEEDED_MASK; |
40cffcc0e md/bitmap: create... |
1646 |
spin_unlock_irq(&bitmap->counts.lock); |
32a7627cf [PATCH] md: optim... |
1647 |
} |
9b1d1dac1 [PATCH] md: new s... |
1648 |
/* dirty the memory and file bits for bitmap chunks "s" to "e" */ |
e64e4018d md: Avoid namespa... |
1649 |
void md_bitmap_dirty_bits(struct bitmap *bitmap, unsigned long s, unsigned long e) |
9b1d1dac1 [PATCH] md: new s... |
1650 1651 1652 1653 |
{ unsigned long chunk; for (chunk = s; chunk <= e; chunk++) { |
40cffcc0e md/bitmap: create... |
1654 |
sector_t sec = (sector_t)chunk << bitmap->counts.chunkshift; |
e64e4018d md: Avoid namespa... |
1655 1656 |
md_bitmap_set_memory_bits(bitmap, sec, 1); md_bitmap_file_set_bit(bitmap, sec); |
ffa23322b md/bitmap: update... |
1657 1658 1659 1660 1661 1662 |
if (sec < bitmap->mddev->recovery_cp) /* We are asserting that the array is dirty, * so move the recovery_cp address back so * that it is obvious that it is dirty */ bitmap->mddev->recovery_cp = sec; |
9b1d1dac1 [PATCH] md: new s... |
1663 1664 |
} } |
32a7627cf [PATCH] md: optim... |
1665 |
/* |
6b8b3e8a8 [PATCH] md: make ... |
1666 1667 |
* flush out any pending updates */ |
e64e4018d md: Avoid namespa... |
1668 |
void md_bitmap_flush(struct mddev *mddev) |
6b8b3e8a8 [PATCH] md: make ... |
1669 1670 |
{ struct bitmap *bitmap = mddev->bitmap; |
42a04b507 md: move offset, ... |
1671 |
long sleep; |
6b8b3e8a8 [PATCH] md: make ... |
1672 1673 1674 1675 1676 1677 1678 |
if (!bitmap) /* there was no bitmap */ return; /* run the daemon_work three time to ensure everything is flushed * that can be */ |
1b04be96f md: change daemon... |
1679 |
sleep = mddev->bitmap_info.daemon_sleep * 2; |
42a04b507 md: move offset, ... |
1680 |
bitmap->daemon_lastrun -= sleep; |
e64e4018d md: Avoid namespa... |
1681 |
md_bitmap_daemon_work(mddev); |
42a04b507 md: move offset, ... |
1682 |
bitmap->daemon_lastrun -= sleep; |
e64e4018d md: Avoid namespa... |
1683 |
md_bitmap_daemon_work(mddev); |
42a04b507 md: move offset, ... |
1684 |
bitmap->daemon_lastrun -= sleep; |
e64e4018d md: Avoid namespa... |
1685 1686 |
md_bitmap_daemon_work(mddev); md_bitmap_update_sb(bitmap); |
6b8b3e8a8 [PATCH] md: make ... |
1687 1688 1689 |
} /* |
32a7627cf [PATCH] md: optim... |
1690 1691 |
* free memory that was allocated */ |
e64e4018d md: Avoid namespa... |
1692 |
void md_bitmap_free(struct bitmap *bitmap) |
32a7627cf [PATCH] md: optim... |
1693 1694 1695 |
{ unsigned long k, pages; struct bitmap_page *bp; |
32a7627cf [PATCH] md: optim... |
1696 1697 1698 |
if (!bitmap) /* there was no bitmap */ return; |
f9a67b118 md/bitmap: clear ... |
1699 1700 |
if (bitmap->sysfs_can_clear) sysfs_put(bitmap->sysfs_can_clear); |
f9209a323 bitmap_create ret... |
1701 1702 |
if (mddev_is_clustered(bitmap->mddev) && bitmap->mddev->cluster_info && bitmap->cluster_slot == md_cluster_ops->slot_number(bitmap->mddev)) |
b97e92574 Use separate bitm... |
1703 |
md_cluster_stop(bitmap->mddev); |
fae7d326c md/bitmap: merge ... |
1704 1705 1706 1707 1708 |
/* Shouldn't be needed - but just in case.... */ wait_event(bitmap->write_wait, atomic_read(&bitmap->pending_writes) == 0); /* release the bitmap file */ |
e64e4018d md: Avoid namespa... |
1709 |
md_bitmap_file_unmap(&bitmap->storage); |
32a7627cf [PATCH] md: optim... |
1710 |
|
40cffcc0e md/bitmap: create... |
1711 1712 |
bp = bitmap->counts.bp; pages = bitmap->counts.pages; |
32a7627cf [PATCH] md: optim... |
1713 1714 |
/* free all allocated memory */ |
32a7627cf [PATCH] md: optim... |
1715 1716 1717 1718 1719 1720 1721 |
if (bp) /* deallocate the page memory */ for (k = 0; k < pages; k++) if (bp[k].map && !bp[k].hijacked) kfree(bp[k].map); kfree(bp); kfree(bitmap); } |
e64e4018d md: Avoid namespa... |
1722 |
EXPORT_SYMBOL(md_bitmap_free); |
aa5cbd103 md/bitmap: protec... |
1723 |
|
e64e4018d md: Avoid namespa... |
1724 |
void md_bitmap_wait_behind_writes(struct mddev *mddev) |
48df498da md: move bitmap_d... |
1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 |
{ struct bitmap *bitmap = mddev->bitmap; /* wait for behind writes to complete */ if (bitmap && atomic_read(&bitmap->behind_writes) > 0) { pr_debug("md:%s: behind writes in progress - waiting to stop. ", mdname(mddev)); /* need to kick something here to make sure I/O goes? */ wait_event(bitmap->behind_wait, atomic_read(&bitmap->behind_writes) == 0); } } |
e64e4018d md: Avoid namespa... |
1738 |
void md_bitmap_destroy(struct mddev *mddev) |
3178b0dbd [PATCH] md: do no... |
1739 1740 1741 1742 1743 |
{ struct bitmap *bitmap = mddev->bitmap; if (!bitmap) /* there was no bitmap */ return; |
e64e4018d md: Avoid namespa... |
1744 |
md_bitmap_wait_behind_writes(mddev); |
69b00b5bb md: introduce a n... |
1745 1746 |
if (!mddev->serialize_policy) mddev_destroy_serial_pool(mddev, NULL, true); |
48df498da md: move bitmap_d... |
1747 |
|
c3d9714e8 md: collect bitma... |
1748 |
mutex_lock(&mddev->bitmap_info.mutex); |
978a7a47c md/bitmap: protec... |
1749 |
spin_lock(&mddev->lock); |
3178b0dbd [PATCH] md: do no... |
1750 |
mddev->bitmap = NULL; /* disconnect from the md device */ |
978a7a47c md/bitmap: protec... |
1751 |
spin_unlock(&mddev->lock); |
c3d9714e8 md: collect bitma... |
1752 |
mutex_unlock(&mddev->bitmap_info.mutex); |
b15c2e57f [PATCH] md: move ... |
1753 1754 |
if (mddev->thread) mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT; |
3178b0dbd [PATCH] md: do no... |
1755 |
|
e64e4018d md: Avoid namespa... |
1756 |
md_bitmap_free(bitmap); |
3178b0dbd [PATCH] md: do no... |
1757 |
} |
32a7627cf [PATCH] md: optim... |
1758 1759 1760 1761 |
/* * initialize the bitmap structure * if this returns an error, bitmap_destroy must be called to do clean up |
f9a67b118 md/bitmap: clear ... |
1762 |
* once mddev->bitmap is set |
32a7627cf [PATCH] md: optim... |
1763 |
*/ |
e64e4018d md: Avoid namespa... |
1764 |
struct bitmap *md_bitmap_create(struct mddev *mddev, int slot) |
32a7627cf [PATCH] md: optim... |
1765 1766 |
{ struct bitmap *bitmap; |
1f5939033 md: support bitma... |
1767 |
sector_t blocks = mddev->resync_max_sectors; |
c3d9714e8 md: collect bitma... |
1768 |
struct file *file = mddev->bitmap_info.file; |
32a7627cf [PATCH] md: optim... |
1769 |
int err; |
324a56e16 kernfs: s/sysfs_d... |
1770 |
struct kernfs_node *bm = NULL; |
32a7627cf [PATCH] md: optim... |
1771 |
|
5f6e3c836 [PATCH] md: use B... |
1772 |
BUILD_BUG_ON(sizeof(bitmap_super_t) != 256); |
32a7627cf [PATCH] md: optim... |
1773 |
|
c3d9714e8 md: collect bitma... |
1774 |
BUG_ON(file && mddev->bitmap_info.offset); |
a654b9d8f [PATCH] md: allow... |
1775 |
|
230b55fa8 md: forbid a RAID... |
1776 1777 1778 1779 1780 1781 |
if (test_bit(MD_HAS_JOURNAL, &mddev->flags)) { pr_notice("md/raid:%s: array with journal cannot have bitmap ", mdname(mddev)); return ERR_PTR(-EBUSY); } |
9ffae0cf3 [PATCH] md: conve... |
1782 |
bitmap = kzalloc(sizeof(*bitmap), GFP_KERNEL); |
32a7627cf [PATCH] md: optim... |
1783 |
if (!bitmap) |
f9209a323 bitmap_create ret... |
1784 |
return ERR_PTR(-ENOMEM); |
32a7627cf [PATCH] md: optim... |
1785 |
|
40cffcc0e md/bitmap: create... |
1786 |
spin_lock_init(&bitmap->counts.lock); |
ce25c31bd [PATCH] md: Chang... |
1787 1788 |
atomic_set(&bitmap->pending_writes, 0); init_waitqueue_head(&bitmap->write_wait); |
da6e1a32f [PATCH] md: avoid... |
1789 |
init_waitqueue_head(&bitmap->overflow_wait); |
e555190d8 md/raid1: delay r... |
1790 |
init_waitqueue_head(&bitmap->behind_wait); |
ce25c31bd [PATCH] md: Chang... |
1791 |
|
32a7627cf [PATCH] md: optim... |
1792 |
bitmap->mddev = mddev; |
f9209a323 bitmap_create ret... |
1793 |
bitmap->cluster_slot = slot; |
32a7627cf [PATCH] md: optim... |
1794 |
|
5ff5afffe md/bitmap: reduce... |
1795 |
if (mddev->kobj.sd) |
388975ccc sysfs: clean up s... |
1796 |
bm = sysfs_get_dirent(mddev->kobj.sd, "bitmap"); |
ece5cff0d md: Support write... |
1797 |
if (bm) { |
388975ccc sysfs: clean up s... |
1798 |
bitmap->sysfs_can_clear = sysfs_get_dirent(bm, "can_clear"); |
ece5cff0d md: Support write... |
1799 1800 1801 |
sysfs_put(bm); } else bitmap->sysfs_can_clear = NULL; |
1ec885cdd md/bitmap: move s... |
1802 |
bitmap->storage.file = file; |
ce25c31bd [PATCH] md: Chang... |
1803 1804 |
if (file) { get_file(file); |
ae8fa2831 md: remove clumsy... |
1805 1806 1807 1808 |
/* As future accesses to this file will use bmap, * and bypass the page cache, we must sync the file * first. */ |
8018ab057 sanitize vfs_fsyn... |
1809 |
vfs_fsync(file, 1); |
ce25c31bd [PATCH] md: Chang... |
1810 |
} |
42a04b507 md: move offset, ... |
1811 |
/* read superblock from bitmap file (this sets mddev->bitmap_info.chunksize) */ |
9c81075f4 MD: support initi... |
1812 1813 1814 1815 1816 1817 |
if (!mddev->bitmap_info.external) { /* * If 'MD_ARRAY_FIRST_USE' is set, then device-mapper is * instructing us to create a new on-disk bitmap instance. */ if (test_and_clear_bit(MD_ARRAY_FIRST_USE, &mddev->flags)) |
e64e4018d md: Avoid namespa... |
1818 |
err = md_bitmap_new_disk_sb(bitmap); |
9c81075f4 MD: support initi... |
1819 |
else |
e64e4018d md: Avoid namespa... |
1820 |
err = md_bitmap_read_sb(bitmap); |
9c81075f4 MD: support initi... |
1821 |
} else { |
ece5cff0d md: Support write... |
1822 1823 1824 1825 1826 1827 1828 |
err = 0; if (mddev->bitmap_info.chunksize == 0 || mddev->bitmap_info.daemon_sleep == 0) /* chunksize and time_base need to be * set first. */ err = -EINVAL; } |
32a7627cf [PATCH] md: optim... |
1829 |
if (err) |
3178b0dbd [PATCH] md: do no... |
1830 |
goto error; |
32a7627cf [PATCH] md: optim... |
1831 |
|
624ce4f56 md/bitmap: move s... |
1832 |
bitmap->daemon_lastrun = jiffies; |
e64e4018d md: Avoid namespa... |
1833 |
err = md_bitmap_resize(bitmap, blocks, mddev->bitmap_info.chunksize, 1); |
d60b479d1 md/bitmap: add bi... |
1834 |
if (err) |
3178b0dbd [PATCH] md: do no... |
1835 |
goto error; |
32a7627cf [PATCH] md: optim... |
1836 |
|
ec0cc2268 md/bitmap: change... |
1837 1838 1839 |
pr_debug("created bitmap (%lu pages) for device %s ", bitmap->counts.pages, bmname(bitmap)); |
69e51b449 md/bitmap: separ... |
1840 |
|
f9209a323 bitmap_create ret... |
1841 1842 1843 |
err = test_bit(BITMAP_WRITE_ERROR, &bitmap->flags) ? -EIO : 0; if (err) goto error; |
69e51b449 md/bitmap: separ... |
1844 |
|
f9209a323 bitmap_create ret... |
1845 |
return bitmap; |
69e51b449 md/bitmap: separ... |
1846 |
error: |
e64e4018d md: Avoid namespa... |
1847 |
md_bitmap_free(bitmap); |
f9209a323 bitmap_create ret... |
1848 |
return ERR_PTR(err); |
69e51b449 md/bitmap: separ... |
1849 |
} |
e64e4018d md: Avoid namespa... |
1850 |
int md_bitmap_load(struct mddev *mddev) |
69e51b449 md/bitmap: separ... |
1851 1852 |
{ int err = 0; |
3520fa4db MD bitmap: Revert... |
1853 |
sector_t start = 0; |
69e51b449 md/bitmap: separ... |
1854 1855 |
sector_t sector = 0; struct bitmap *bitmap = mddev->bitmap; |
617b194a1 md-bitmap: create... |
1856 |
struct md_rdev *rdev; |
69e51b449 md/bitmap: separ... |
1857 1858 1859 |
if (!bitmap) goto out; |
617b194a1 md-bitmap: create... |
1860 |
rdev_for_each(rdev, mddev) |
404659cf1 md: rename wb stuffs |
1861 |
mddev_create_serial_pool(mddev, rdev, true); |
617b194a1 md-bitmap: create... |
1862 |
|
51e453aec md-cluster: gathe... |
1863 1864 |
if (mddev_is_clustered(mddev)) md_cluster_ops->load_bitmaps(mddev, mddev->bitmap_info.nodes); |
69e51b449 md/bitmap: separ... |
1865 1866 1867 1868 1869 1870 |
/* Clear out old bitmap info first: Either there is none, or we * are resuming after someone else has possibly changed things, * so we should forget old cached info. * All chunks should be clean, but some might need_sync. */ while (sector < mddev->resync_max_sectors) { |
57dab0bdf md: use sector_t ... |
1871 |
sector_t blocks; |
e64e4018d md: Avoid namespa... |
1872 |
md_bitmap_start_sync(bitmap, sector, &blocks, 0); |
69e51b449 md/bitmap: separ... |
1873 1874 |
sector += blocks; } |
e64e4018d md: Avoid namespa... |
1875 |
md_bitmap_close_sync(bitmap); |
69e51b449 md/bitmap: separ... |
1876 |
|
3520fa4db MD bitmap: Revert... |
1877 1878 1879 1880 1881 |
if (mddev->degraded == 0 || bitmap->events_cleared == mddev->events) /* no need to keep dirty bits to optimise a * re-add of a missing device */ start = mddev->recovery_cp; |
afbaa90b8 md/bitmap: preven... |
1882 |
mutex_lock(&mddev->bitmap_info.mutex); |
e64e4018d md: Avoid namespa... |
1883 |
err = md_bitmap_init_from_disk(bitmap, start); |
afbaa90b8 md/bitmap: preven... |
1884 |
mutex_unlock(&mddev->bitmap_info.mutex); |
3520fa4db MD bitmap: Revert... |
1885 |
|
32a7627cf [PATCH] md: optim... |
1886 |
if (err) |
69e51b449 md/bitmap: separ... |
1887 |
goto out; |
b405fe91e md/bitmap: use se... |
1888 |
clear_bit(BITMAP_STALE, &bitmap->flags); |
ef99bf480 md/bitmap: allow ... |
1889 1890 1891 |
/* Kick recovery in case any bits were set */ set_bit(MD_RECOVERY_NEEDED, &bitmap->mddev->recovery); |
3178b0dbd [PATCH] md: do no... |
1892 |
|
1b04be96f md: change daemon... |
1893 |
mddev->thread->timeout = mddev->bitmap_info.daemon_sleep; |
9cd30fdc3 md: remove needle... |
1894 |
md_wakeup_thread(mddev->thread); |
b15c2e57f [PATCH] md: move ... |
1895 |
|
e64e4018d md: Avoid namespa... |
1896 |
md_bitmap_update_sb(bitmap); |
4ad136637 md: change bitmap... |
1897 |
|
b405fe91e md/bitmap: use se... |
1898 |
if (test_bit(BITMAP_WRITE_ERROR, &bitmap->flags)) |
69e51b449 md/bitmap: separ... |
1899 1900 |
err = -EIO; out: |
3178b0dbd [PATCH] md: do no... |
1901 |
return err; |
32a7627cf [PATCH] md: optim... |
1902 |
} |
e64e4018d md: Avoid namespa... |
1903 |
EXPORT_SYMBOL_GPL(md_bitmap_load); |
32a7627cf [PATCH] md: optim... |
1904 |
|
1383b347a md/bitmap: fix me... |
1905 |
/* caller need to free returned bitmap with md_bitmap_free() */ |
b98938d16 md-cluster: intro... |
1906 1907 1908 1909 |
struct bitmap *get_bitmap_from_slot(struct mddev *mddev, int slot) { int rv = 0; struct bitmap *bitmap; |
e64e4018d md: Avoid namespa... |
1910 |
bitmap = md_bitmap_create(mddev, slot); |
b98938d16 md-cluster: intro... |
1911 1912 1913 1914 |
if (IS_ERR(bitmap)) { rv = PTR_ERR(bitmap); return ERR_PTR(rv); } |
e64e4018d md: Avoid namespa... |
1915 |
rv = md_bitmap_init_from_disk(bitmap, 0); |
b98938d16 md-cluster: intro... |
1916 |
if (rv) { |
e64e4018d md: Avoid namespa... |
1917 |
md_bitmap_free(bitmap); |
b98938d16 md-cluster: intro... |
1918 1919 1920 1921 1922 1923 |
return ERR_PTR(rv); } return bitmap; } EXPORT_SYMBOL(get_bitmap_from_slot); |
11dd35daa Copy set bits fro... |
1924 1925 1926 |
/* Loads the bitmap associated with slot and copies the resync information * to our bitmap */ |
e64e4018d md: Avoid namespa... |
1927 |
int md_bitmap_copy_from_slot(struct mddev *mddev, int slot, |
97f6cd39d md-cluster: re-ad... |
1928 |
sector_t *low, sector_t *high, bool clear_bits) |
11dd35daa Copy set bits fro... |
1929 1930 1931 1932 |
{ int rv = 0, i, j; sector_t block, lo = 0, hi = 0; struct bitmap_counts *counts; |
b98938d16 md-cluster: intro... |
1933 |
struct bitmap *bitmap; |
11dd35daa Copy set bits fro... |
1934 |
|
b98938d16 md-cluster: intro... |
1935 1936 1937 1938 1939 1940 |
bitmap = get_bitmap_from_slot(mddev, slot); if (IS_ERR(bitmap)) { pr_err("%s can't get bitmap from slot %d ", __func__, slot); return -1; } |
11dd35daa Copy set bits fro... |
1941 1942 1943 1944 |
counts = &bitmap->counts; for (j = 0; j < counts->chunks; j++) { block = (sector_t)j << counts->chunkshift; |
e64e4018d md: Avoid namespa... |
1945 |
if (md_bitmap_file_test_bit(bitmap, block)) { |
11dd35daa Copy set bits fro... |
1946 1947 1948 |
if (!lo) lo = block; hi = block; |
e64e4018d md: Avoid namespa... |
1949 1950 1951 |
md_bitmap_file_clear_bit(bitmap, block); md_bitmap_set_memory_bits(mddev->bitmap, block, 1); md_bitmap_file_set_bit(mddev->bitmap, block); |
11dd35daa Copy set bits fro... |
1952 1953 |
} } |
97f6cd39d md-cluster: re-ad... |
1954 |
if (clear_bits) { |
e64e4018d md: Avoid namespa... |
1955 |
md_bitmap_update_sb(bitmap); |
c84400c89 md-cluster/bitmap... |
1956 1957 |
/* BITMAP_PAGE_PENDING is set, but bitmap_unplug needs * BITMAP_PAGE_DIRTY or _NEEDWRITE to write ... */ |
97f6cd39d md-cluster: re-ad... |
1958 |
for (i = 0; i < bitmap->storage.file_pages; i++) |
c84400c89 md-cluster/bitmap... |
1959 1960 |
if (test_page_attr(bitmap, i, BITMAP_PAGE_PENDING)) set_page_attr(bitmap, i, BITMAP_PAGE_NEEDWRITE); |
e64e4018d md: Avoid namespa... |
1961 |
md_bitmap_unplug(bitmap); |
97f6cd39d md-cluster: re-ad... |
1962 |
} |
e64e4018d md: Avoid namespa... |
1963 |
md_bitmap_unplug(mddev->bitmap); |
11dd35daa Copy set bits fro... |
1964 1965 |
*low = lo; *high = hi; |
1383b347a md/bitmap: fix me... |
1966 |
md_bitmap_free(bitmap); |
b98938d16 md-cluster: intro... |
1967 |
|
11dd35daa Copy set bits fro... |
1968 1969 |
return rv; } |
e64e4018d md: Avoid namespa... |
1970 |
EXPORT_SYMBOL_GPL(md_bitmap_copy_from_slot); |
11dd35daa Copy set bits fro... |
1971 |
|
e64e4018d md: Avoid namespa... |
1972 |
void md_bitmap_status(struct seq_file *seq, struct bitmap *bitmap) |
57148964d md/bitmap: move p... |
1973 1974 |
{ unsigned long chunk_kb; |
40cffcc0e md/bitmap: create... |
1975 |
struct bitmap_counts *counts; |
57148964d md/bitmap: move p... |
1976 1977 1978 |
if (!bitmap) return; |
40cffcc0e md/bitmap: create... |
1979 |
counts = &bitmap->counts; |
57148964d md/bitmap: move p... |
1980 1981 1982 |
chunk_kb = bitmap->mddev->bitmap_info.chunksize >> 10; seq_printf(seq, "bitmap: %lu/%lu pages [%luKB], " "%lu%s chunk", |
40cffcc0e md/bitmap: create... |
1983 1984 1985 |
counts->pages - counts->missing_pages, counts->pages, (counts->pages - counts->missing_pages) |
57148964d md/bitmap: move p... |
1986 1987 1988 |
<< (PAGE_SHIFT - 10), chunk_kb ? chunk_kb : bitmap->mddev->bitmap_info.chunksize, chunk_kb ? "KB" : "B"); |
1ec885cdd md/bitmap: move s... |
1989 |
if (bitmap->storage.file) { |
57148964d md/bitmap: move p... |
1990 |
seq_printf(seq, ", file: "); |
2726d5662 vfs: add seq_file... |
1991 1992 |
seq_file_path(seq, bitmap->storage.file, " \t "); |
57148964d md/bitmap: move p... |
1993 1994 1995 1996 |
} seq_printf(seq, " "); |
57148964d md/bitmap: move p... |
1997 |
} |
e64e4018d md: Avoid namespa... |
1998 |
int md_bitmap_resize(struct bitmap *bitmap, sector_t blocks, |
d60b479d1 md/bitmap: add bi... |
1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 |
int chunksize, int init) { /* If chunk_size is 0, choose an appropriate chunk size. * Then possibly allocate new storage space. * Then quiesce, copy bits, replace bitmap, and re-start * * This function is called both to set up the initial bitmap * and to resize the bitmap while the array is active. * If this happens as a result of the array being resized, * chunksize will be zero, and we need to choose a suitable * chunksize, otherwise we use what we are given. */ struct bitmap_storage store; struct bitmap_counts old_counts; unsigned long chunks; sector_t block; sector_t old_blocks, new_blocks; int chunkshift; int ret = 0; long pages; struct bitmap_page *new_bp; |
e8a27f836 md/bitmap: disabl... |
2020 2021 2022 2023 2024 |
if (bitmap->storage.file && !init) { pr_info("md: cannot resize file-based bitmap "); return -EINVAL; } |
d60b479d1 md/bitmap: add bi... |
2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 |
if (chunksize == 0) { /* If there is enough space, leave the chunk size unchanged, * else increase by factor of two until there is enough space. */ long bytes; long space = bitmap->mddev->bitmap_info.space; if (space == 0) { /* We don't know how much space there is, so limit * to current size - in sectors. */ bytes = DIV_ROUND_UP(bitmap->counts.chunks, 8); if (!bitmap->mddev->bitmap_info.external) bytes += sizeof(bitmap_super_t); space = DIV_ROUND_UP(bytes, 512); bitmap->mddev->bitmap_info.space = space; } chunkshift = bitmap->counts.chunkshift; chunkshift--; do { /* 'chunkshift' is shift from block size to chunk size */ chunkshift++; chunks = DIV_ROUND_UP_SECTOR_T(blocks, 1 << chunkshift); bytes = DIV_ROUND_UP(chunks, 8); if (!bitmap->mddev->bitmap_info.external) bytes += sizeof(bitmap_super_t); } while (bytes > (space << 9)); } else chunkshift = ffz(~chunksize) - BITMAP_BLOCK_SHIFT; chunks = DIV_ROUND_UP_SECTOR_T(blocks, 1 << chunkshift); memset(&store, 0, sizeof(store)); if (bitmap->mddev->bitmap_info.offset || bitmap->mddev->bitmap_info.file) |
e64e4018d md: Avoid namespa... |
2058 2059 2060 2061 |
ret = md_bitmap_storage_alloc(&store, chunks, !bitmap->mddev->bitmap_info.external, mddev_is_clustered(bitmap->mddev) ? bitmap->cluster_slot : 0); |
cbb387323 md/bitmap: call b... |
2062 |
if (ret) { |
e64e4018d md: Avoid namespa... |
2063 |
md_bitmap_file_unmap(&store); |
d60b479d1 md/bitmap: add bi... |
2064 |
goto err; |
cbb387323 md/bitmap: call b... |
2065 |
} |
d60b479d1 md/bitmap: add bi... |
2066 2067 |
pages = DIV_ROUND_UP(chunks, PAGE_COUNTER_RATIO); |
6396bb221 treewide: kzalloc... |
2068 |
new_bp = kcalloc(pages, sizeof(*new_bp), GFP_KERNEL); |
d60b479d1 md/bitmap: add bi... |
2069 2070 |
ret = -ENOMEM; if (!new_bp) { |
e64e4018d md: Avoid namespa... |
2071 |
md_bitmap_file_unmap(&store); |
d60b479d1 md/bitmap: add bi... |
2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 |
goto err; } if (!init) bitmap->mddev->pers->quiesce(bitmap->mddev, 1); store.file = bitmap->storage.file; bitmap->storage.file = NULL; if (store.sb_page && bitmap->storage.sb_page) memcpy(page_address(store.sb_page), page_address(bitmap->storage.sb_page), |
938b533d4 md/bitmap: revert... |
2084 |
sizeof(bitmap_super_t)); |
fadcbd290 md/bitmap: avoid ... |
2085 |
spin_lock_irq(&bitmap->counts.lock); |
e64e4018d md: Avoid namespa... |
2086 |
md_bitmap_file_unmap(&bitmap->storage); |
d60b479d1 md/bitmap: add bi... |
2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 |
bitmap->storage = store; old_counts = bitmap->counts; bitmap->counts.bp = new_bp; bitmap->counts.pages = pages; bitmap->counts.missing_pages = pages; bitmap->counts.chunkshift = chunkshift; bitmap->counts.chunks = chunks; bitmap->mddev->bitmap_info.chunksize = 1 << (chunkshift + BITMAP_BLOCK_SHIFT); blocks = min(old_counts.chunks << old_counts.chunkshift, chunks << chunkshift); |
c9d650322 md-cluster: alway... |
2100 2101 2102 2103 |
/* For cluster raid, need to pre-allocate bitmap */ if (mddev_is_clustered(bitmap->mddev)) { unsigned long page; for (page = 0; page < pages; page++) { |
e64e4018d md: Avoid namespa... |
2104 |
ret = md_bitmap_checkpage(&bitmap->counts, page, 1, 1); |
c9d650322 md-cluster: alway... |
2105 2106 2107 2108 2109 |
if (ret) { unsigned long k; /* deallocate the page memory */ for (k = 0; k < page; k++) { |
bc47e8425 md-cluster: fix i... |
2110 |
kfree(new_bp[k].map); |
c9d650322 md-cluster: alway... |
2111 |
} |
0868b99c2 md: free unused m... |
2112 |
kfree(new_bp); |
c9d650322 md-cluster: alway... |
2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 |
/* restore some fields from old_counts */ bitmap->counts.bp = old_counts.bp; bitmap->counts.pages = old_counts.pages; bitmap->counts.missing_pages = old_counts.pages; bitmap->counts.chunkshift = old_counts.chunkshift; bitmap->counts.chunks = old_counts.chunks; bitmap->mddev->bitmap_info.chunksize = 1 << (old_counts.chunkshift + BITMAP_BLOCK_SHIFT); blocks = old_counts.chunks << old_counts.chunkshift; |
ec0cc2268 md/bitmap: change... |
2123 2124 |
pr_warn("Could not pre-allocate in-memory bitmap for cluster raid "); |
c9d650322 md-cluster: alway... |
2125 2126 2127 2128 2129 |
break; } else bitmap->counts.bp[page].count += 1; } } |
d60b479d1 md/bitmap: add bi... |
2130 2131 2132 |
for (block = 0; block < blocks; ) { bitmap_counter_t *bmc_old, *bmc_new; int set; |
e64e4018d md: Avoid namespa... |
2133 |
bmc_old = md_bitmap_get_counter(&old_counts, block, &old_blocks, 0); |
d60b479d1 md/bitmap: add bi... |
2134 2135 2136 |
set = bmc_old && NEEDED(*bmc_old); if (set) { |
e64e4018d md: Avoid namespa... |
2137 |
bmc_new = md_bitmap_get_counter(&bitmap->counts, block, &new_blocks, 1); |
d60b479d1 md/bitmap: add bi... |
2138 2139 2140 2141 2142 2143 |
if (*bmc_new == 0) { /* need to set on-disk bits too. */ sector_t end = block + new_blocks; sector_t start = block >> chunkshift; start <<= chunkshift; while (start < end) { |
e64e4018d md: Avoid namespa... |
2144 |
md_bitmap_file_set_bit(bitmap, block); |
d60b479d1 md/bitmap: add bi... |
2145 2146 2147 |
start += 1 << chunkshift; } *bmc_new = 2; |
e64e4018d md: Avoid namespa... |
2148 2149 |
md_bitmap_count_page(&bitmap->counts, block, 1); md_bitmap_set_pending(&bitmap->counts, block); |
d60b479d1 md/bitmap: add bi... |
2150 2151 2152 2153 2154 2155 2156 |
} *bmc_new |= NEEDED_MASK; if (new_blocks < old_blocks) old_blocks = new_blocks; } block += old_blocks; } |
0868b99c2 md: free unused m... |
2157 2158 2159 2160 2161 2162 2163 |
if (bitmap->counts.bp != old_counts.bp) { unsigned long k; for (k = 0; k < old_counts.pages; k++) if (!old_counts.bp[k].hijacked) kfree(old_counts.bp[k].map); kfree(old_counts.bp); } |
d60b479d1 md/bitmap: add bi... |
2164 2165 2166 2167 |
if (!init) { int i; while (block < (chunks << chunkshift)) { bitmap_counter_t *bmc; |
e64e4018d md: Avoid namespa... |
2168 |
bmc = md_bitmap_get_counter(&bitmap->counts, block, &new_blocks, 1); |
d60b479d1 md/bitmap: add bi... |
2169 2170 2171 2172 2173 2174 |
if (bmc) { /* new space. It needs to be resynced, so * we set NEEDED_MASK. */ if (*bmc == 0) { *bmc = NEEDED_MASK | 2; |
e64e4018d md: Avoid namespa... |
2175 2176 |
md_bitmap_count_page(&bitmap->counts, block, 1); md_bitmap_set_pending(&bitmap->counts, block); |
d60b479d1 md/bitmap: add bi... |
2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 |
} } block += new_blocks; } for (i = 0; i < bitmap->storage.file_pages; i++) set_page_attr(bitmap, i, BITMAP_PAGE_DIRTY); } spin_unlock_irq(&bitmap->counts.lock); if (!init) { |
e64e4018d md: Avoid namespa... |
2187 |
md_bitmap_unplug(bitmap); |
d60b479d1 md/bitmap: add bi... |
2188 2189 2190 2191 2192 2193 |
bitmap->mddev->pers->quiesce(bitmap->mddev, 0); } ret = 0; err: return ret; } |
e64e4018d md: Avoid namespa... |
2194 |
EXPORT_SYMBOL_GPL(md_bitmap_resize); |
d60b479d1 md/bitmap: add bi... |
2195 |
|
43a705076 md: support updat... |
2196 |
static ssize_t |
fd01b88c7 md: remove typede... |
2197 |
location_show(struct mddev *mddev, char *page) |
43a705076 md: support updat... |
2198 2199 |
{ ssize_t len; |
ac2f40be4 md/bitmap: white ... |
2200 |
if (mddev->bitmap_info.file) |
43a705076 md: support updat... |
2201 |
len = sprintf(page, "file"); |
ac2f40be4 md/bitmap: white ... |
2202 |
else if (mddev->bitmap_info.offset) |
43a705076 md: support updat... |
2203 |
len = sprintf(page, "%+lld", (long long)mddev->bitmap_info.offset); |
ac2f40be4 md/bitmap: white ... |
2204 |
else |
43a705076 md: support updat... |
2205 2206 2207 2208 2209 2210 2211 |
len = sprintf(page, "none"); len += sprintf(page+len, " "); return len; } static ssize_t |
fd01b88c7 md: remove typede... |
2212 |
location_store(struct mddev *mddev, const char *buf, size_t len) |
43a705076 md: support updat... |
2213 |
{ |
d9dd26b20 MD: hold mddev lo... |
2214 |
int rv; |
43a705076 md: support updat... |
2215 |
|
d9dd26b20 MD: hold mddev lo... |
2216 2217 2218 |
rv = mddev_lock(mddev); if (rv) return rv; |
43a705076 md: support updat... |
2219 |
if (mddev->pers) { |
d9dd26b20 MD: hold mddev lo... |
2220 2221 2222 2223 2224 2225 2226 2227 |
if (!mddev->pers->quiesce) { rv = -EBUSY; goto out; } if (mddev->recovery || mddev->sync_thread) { rv = -EBUSY; goto out; } |
43a705076 md: support updat... |
2228 2229 2230 2231 2232 |
} if (mddev->bitmap || mddev->bitmap_info.file || mddev->bitmap_info.offset) { /* bitmap already configured. Only option is to clear it */ |
d9dd26b20 MD: hold mddev lo... |
2233 2234 2235 2236 |
if (strncmp(buf, "none", 4) != 0) { rv = -EBUSY; goto out; } |
43a705076 md: support updat... |
2237 |
if (mddev->pers) { |
f8f83d8ff md/bitmap: use md... |
2238 |
mddev_suspend(mddev); |
e64e4018d md: Avoid namespa... |
2239 |
md_bitmap_destroy(mddev); |
f8f83d8ff md/bitmap: use md... |
2240 |
mddev_resume(mddev); |
43a705076 md: support updat... |
2241 2242 2243 2244 2245 |
} mddev->bitmap_info.offset = 0; if (mddev->bitmap_info.file) { struct file *f = mddev->bitmap_info.file; mddev->bitmap_info.file = NULL; |
43a705076 md: support updat... |
2246 2247 2248 2249 2250 2251 2252 2253 2254 |
fput(f); } } else { /* No bitmap, OK to set a location */ long long offset; if (strncmp(buf, "none", 4) == 0) /* nothing to be done */; else if (strncmp(buf, "file:", 5) == 0) { /* Not supported yet */ |
d9dd26b20 MD: hold mddev lo... |
2255 2256 |
rv = -EINVAL; goto out; |
43a705076 md: support updat... |
2257 |
} else { |
43a705076 md: support updat... |
2258 |
if (buf[0] == '+') |
b29bebd66 md: replace stric... |
2259 |
rv = kstrtoll(buf+1, 10, &offset); |
43a705076 md: support updat... |
2260 |
else |
b29bebd66 md: replace stric... |
2261 |
rv = kstrtoll(buf, 10, &offset); |
43a705076 md: support updat... |
2262 |
if (rv) |
d9dd26b20 MD: hold mddev lo... |
2263 2264 2265 2266 2267 |
goto out; if (offset == 0) { rv = -EINVAL; goto out; } |
ece5cff0d md: Support write... |
2268 2269 |
if (mddev->bitmap_info.external == 0 && mddev->major_version == 0 && |
d9dd26b20 MD: hold mddev lo... |
2270 2271 2272 2273 |
offset != mddev->bitmap_info.default_offset) { rv = -EINVAL; goto out; } |
43a705076 md: support updat... |
2274 2275 |
mddev->bitmap_info.offset = offset; if (mddev->pers) { |
f9209a323 bitmap_create ret... |
2276 |
struct bitmap *bitmap; |
e64e4018d md: Avoid namespa... |
2277 |
bitmap = md_bitmap_create(mddev, -1); |
f8f83d8ff md/bitmap: use md... |
2278 |
mddev_suspend(mddev); |
f9209a323 bitmap_create ret... |
2279 2280 2281 2282 |
if (IS_ERR(bitmap)) rv = PTR_ERR(bitmap); else { mddev->bitmap = bitmap; |
e64e4018d md: Avoid namespa... |
2283 |
rv = md_bitmap_load(mddev); |
f9a67b118 md/bitmap: clear ... |
2284 |
if (rv) |
f9209a323 bitmap_create ret... |
2285 |
mddev->bitmap_info.offset = 0; |
43a705076 md: support updat... |
2286 |
} |
f9a67b118 md/bitmap: clear ... |
2287 |
if (rv) { |
e64e4018d md: Avoid namespa... |
2288 |
md_bitmap_destroy(mddev); |
f8f83d8ff md/bitmap: use md... |
2289 |
mddev_resume(mddev); |
d9dd26b20 MD: hold mddev lo... |
2290 |
goto out; |
f9a67b118 md/bitmap: clear ... |
2291 |
} |
f8f83d8ff md/bitmap: use md... |
2292 |
mddev_resume(mddev); |
43a705076 md: support updat... |
2293 2294 2295 2296 2297 2298 2299 |
} } } if (!mddev->external) { /* Ensure new bitmap info is stored in * metadata promptly. */ |
2953079c6 md: separate flag... |
2300 |
set_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags); |
43a705076 md: support updat... |
2301 2302 |
md_wakeup_thread(mddev->thread); } |
d9dd26b20 MD: hold mddev lo... |
2303 2304 2305 2306 2307 |
rv = 0; out: mddev_unlock(mddev); if (rv) return rv; |
43a705076 md: support updat... |
2308 2309 2310 2311 2312 |
return len; } static struct md_sysfs_entry bitmap_location = __ATTR(location, S_IRUGO|S_IWUSR, location_show, location_store); |
6409bb05a md/bitmap: add ne... |
2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 |
/* 'bitmap/space' is the space available at 'location' for the * bitmap. This allows the kernel to know when it is safe to * resize the bitmap to match a resized array. */ static ssize_t space_show(struct mddev *mddev, char *page) { return sprintf(page, "%lu ", mddev->bitmap_info.space); } static ssize_t space_store(struct mddev *mddev, const char *buf, size_t len) { unsigned long sectors; int rv; rv = kstrtoul(buf, 10, §ors); if (rv) return rv; if (sectors == 0) return -EINVAL; if (mddev->bitmap && |
9b1215c10 md/bitmap: store ... |
2338 |
sectors < (mddev->bitmap->storage.bytes + 511) >> 9) |
6409bb05a md/bitmap: add ne... |
2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 |
return -EFBIG; /* Bitmap is too big for this small space */ /* could make sure it isn't too big, but that isn't really * needed - user-space should be careful. */ mddev->bitmap_info.space = sectors; return len; } static struct md_sysfs_entry bitmap_space = __ATTR(space, S_IRUGO|S_IWUSR, space_show, space_store); |
43a705076 md: support updat... |
2350 |
static ssize_t |
fd01b88c7 md: remove typede... |
2351 |
timeout_show(struct mddev *mddev, char *page) |
43a705076 md: support updat... |
2352 2353 2354 2355 |
{ ssize_t len; unsigned long secs = mddev->bitmap_info.daemon_sleep / HZ; unsigned long jifs = mddev->bitmap_info.daemon_sleep % HZ; |
ac2f40be4 md/bitmap: white ... |
2356 |
|
43a705076 md: support updat... |
2357 2358 2359 2360 2361 2362 2363 2364 2365 |
len = sprintf(page, "%lu", secs); if (jifs) len += sprintf(page+len, ".%03u", jiffies_to_msecs(jifs)); len += sprintf(page+len, " "); return len; } static ssize_t |
fd01b88c7 md: remove typede... |
2366 |
timeout_store(struct mddev *mddev, const char *buf, size_t len) |
43a705076 md: support updat... |
2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 |
{ /* timeout can be set at any time */ unsigned long timeout; int rv = strict_strtoul_scaled(buf, &timeout, 4); if (rv) return rv; /* just to make sure we don't overflow... */ if (timeout >= LONG_MAX / HZ) return -EINVAL; timeout = timeout * HZ / 10000; if (timeout >= MAX_SCHEDULE_TIMEOUT) timeout = MAX_SCHEDULE_TIMEOUT-1; if (timeout < 1) timeout = 1; mddev->bitmap_info.daemon_sleep = timeout; if (mddev->thread) { /* if thread->timeout is MAX_SCHEDULE_TIMEOUT, then * the bitmap is all clean and we don't need to * adjust the timeout right now */ if (mddev->thread->timeout < MAX_SCHEDULE_TIMEOUT) { mddev->thread->timeout = timeout; md_wakeup_thread(mddev->thread); } } return len; } static struct md_sysfs_entry bitmap_timeout = __ATTR(time_base, S_IRUGO|S_IWUSR, timeout_show, timeout_store); static ssize_t |
fd01b88c7 md: remove typede... |
2402 |
backlog_show(struct mddev *mddev, char *page) |
43a705076 md: support updat... |
2403 2404 2405 2406 2407 2408 |
{ return sprintf(page, "%lu ", mddev->bitmap_info.max_write_behind); } static ssize_t |
fd01b88c7 md: remove typede... |
2409 |
backlog_store(struct mddev *mddev, const char *buf, size_t len) |
43a705076 md: support updat... |
2410 2411 |
{ unsigned long backlog; |
10c92fca6 md-bitmap: create... |
2412 |
unsigned long old_mwb = mddev->bitmap_info.max_write_behind; |
b29bebd66 md: replace stric... |
2413 |
int rv = kstrtoul(buf, 10, &backlog); |
43a705076 md: support updat... |
2414 2415 2416 2417 2418 |
if (rv) return rv; if (backlog > COUNTER_MAX) return -EINVAL; mddev->bitmap_info.max_write_behind = backlog; |
404659cf1 md: rename wb stuffs |
2419 2420 |
if (!backlog && mddev->serial_info_pool) { /* serial_info_pool is not needed if backlog is zero */ |
69b00b5bb md: introduce a n... |
2421 2422 |
if (!mddev->serialize_policy) mddev_destroy_serial_pool(mddev, NULL, false); |
404659cf1 md: rename wb stuffs |
2423 2424 |
} else if (backlog && !mddev->serial_info_pool) { /* serial_info_pool is needed since backlog is not zero */ |
10c92fca6 md-bitmap: create... |
2425 2426 2427 |
struct md_rdev *rdev; rdev_for_each(rdev, mddev) |
404659cf1 md: rename wb stuffs |
2428 |
mddev_create_serial_pool(mddev, rdev, false); |
10c92fca6 md-bitmap: create... |
2429 2430 2431 |
} if (old_mwb != backlog) md_bitmap_update_sb(mddev->bitmap); |
43a705076 md: support updat... |
2432 2433 2434 2435 2436 2437 2438 |
return len; } static struct md_sysfs_entry bitmap_backlog = __ATTR(backlog, S_IRUGO|S_IWUSR, backlog_show, backlog_store); static ssize_t |
fd01b88c7 md: remove typede... |
2439 |
chunksize_show(struct mddev *mddev, char *page) |
43a705076 md: support updat... |
2440 2441 2442 2443 2444 2445 |
{ return sprintf(page, "%lu ", mddev->bitmap_info.chunksize); } static ssize_t |
fd01b88c7 md: remove typede... |
2446 |
chunksize_store(struct mddev *mddev, const char *buf, size_t len) |
43a705076 md: support updat... |
2447 2448 2449 2450 2451 2452 |
{ /* Can only be changed when no bitmap is active */ int rv; unsigned long csize; if (mddev->bitmap) return -EBUSY; |
b29bebd66 md: replace stric... |
2453 |
rv = kstrtoul(buf, 10, &csize); |
43a705076 md: support updat... |
2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 |
if (rv) return rv; if (csize < 512 || !is_power_of_2(csize)) return -EINVAL; mddev->bitmap_info.chunksize = csize; return len; } static struct md_sysfs_entry bitmap_chunksize = __ATTR(chunksize, S_IRUGO|S_IWUSR, chunksize_show, chunksize_store); |
fd01b88c7 md: remove typede... |
2465 |
static ssize_t metadata_show(struct mddev *mddev, char *page) |
ece5cff0d md: Support write... |
2466 |
{ |
c4ce867fd Introduce md_clus... |
2467 2468 2469 |
if (mddev_is_clustered(mddev)) return sprintf(page, "clustered "); |
ece5cff0d md: Support write... |
2470 2471 2472 2473 |
return sprintf(page, "%s ", (mddev->bitmap_info.external ? "external" : "internal")); } |
fd01b88c7 md: remove typede... |
2474 |
static ssize_t metadata_store(struct mddev *mddev, const char *buf, size_t len) |
ece5cff0d md: Support write... |
2475 2476 2477 2478 2479 2480 2481 |
{ if (mddev->bitmap || mddev->bitmap_info.file || mddev->bitmap_info.offset) return -EBUSY; if (strncmp(buf, "external", 8) == 0) mddev->bitmap_info.external = 1; |
c4ce867fd Introduce md_clus... |
2482 2483 |
else if ((strncmp(buf, "internal", 8) == 0) || (strncmp(buf, "clustered", 9) == 0)) |
ece5cff0d md: Support write... |
2484 2485 2486 2487 2488 2489 2490 2491 |
mddev->bitmap_info.external = 0; else return -EINVAL; return len; } static struct md_sysfs_entry bitmap_metadata = __ATTR(metadata, S_IRUGO|S_IWUSR, metadata_show, metadata_store); |
fd01b88c7 md: remove typede... |
2492 |
static ssize_t can_clear_show(struct mddev *mddev, char *page) |
ece5cff0d md: Support write... |
2493 2494 |
{ int len; |
b7b17c9b6 md: remove mddev_... |
2495 |
spin_lock(&mddev->lock); |
ece5cff0d md: Support write... |
2496 2497 2498 2499 2500 2501 2502 |
if (mddev->bitmap) len = sprintf(page, "%s ", (mddev->bitmap->need_sync ? "false" : "true")); else len = sprintf(page, " "); |
b7b17c9b6 md: remove mddev_... |
2503 |
spin_unlock(&mddev->lock); |
ece5cff0d md: Support write... |
2504 2505 |
return len; } |
fd01b88c7 md: remove typede... |
2506 |
static ssize_t can_clear_store(struct mddev *mddev, const char *buf, size_t len) |
ece5cff0d md: Support write... |
2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 |
{ if (mddev->bitmap == NULL) return -ENOENT; if (strncmp(buf, "false", 5) == 0) mddev->bitmap->need_sync = 1; else if (strncmp(buf, "true", 4) == 0) { if (mddev->degraded) return -EBUSY; mddev->bitmap->need_sync = 0; } else return -EINVAL; return len; } static struct md_sysfs_entry bitmap_can_clear = __ATTR(can_clear, S_IRUGO|S_IWUSR, can_clear_show, can_clear_store); |
696fcd535 md: expose max va... |
2523 |
static ssize_t |
fd01b88c7 md: remove typede... |
2524 |
behind_writes_used_show(struct mddev *mddev, char *page) |
696fcd535 md: expose max va... |
2525 |
{ |
b7b17c9b6 md: remove mddev_... |
2526 2527 |
ssize_t ret; spin_lock(&mddev->lock); |
696fcd535 md: expose max va... |
2528 |
if (mddev->bitmap == NULL) |
b7b17c9b6 md: remove mddev_... |
2529 2530 2531 2532 2533 2534 2535 2536 |
ret = sprintf(page, "0 "); else ret = sprintf(page, "%lu ", mddev->bitmap->behind_writes_used); spin_unlock(&mddev->lock); return ret; |
696fcd535 md: expose max va... |
2537 2538 2539 |
} static ssize_t |
fd01b88c7 md: remove typede... |
2540 |
behind_writes_used_reset(struct mddev *mddev, const char *buf, size_t len) |
696fcd535 md: expose max va... |
2541 2542 2543 2544 2545 2546 2547 2548 2549 |
{ if (mddev->bitmap) mddev->bitmap->behind_writes_used = 0; return len; } static struct md_sysfs_entry max_backlog_used = __ATTR(max_backlog_used, S_IRUGO | S_IWUSR, behind_writes_used_show, behind_writes_used_reset); |
43a705076 md: support updat... |
2550 2551 |
static struct attribute *md_bitmap_attrs[] = { &bitmap_location.attr, |
6409bb05a md/bitmap: add ne... |
2552 |
&bitmap_space.attr, |
43a705076 md: support updat... |
2553 2554 2555 |
&bitmap_timeout.attr, &bitmap_backlog.attr, &bitmap_chunksize.attr, |
ece5cff0d md: Support write... |
2556 2557 |
&bitmap_metadata.attr, &bitmap_can_clear.attr, |
696fcd535 md: expose max va... |
2558 |
&max_backlog_used.attr, |
43a705076 md: support updat... |
2559 2560 2561 2562 2563 2564 |
NULL }; struct attribute_group md_bitmap_group = { .name = "bitmap", .attrs = md_bitmap_attrs, }; |